source: rtems/bsps/sparc/shared/net/greth.c @ cb68253

5
Last change on this file since cb68253 was cb68253, checked in by Sebastian Huber <sebastian.huber@…>, on 09/07/18 at 04:19:02

network: Use kernel/user space header files

Add and use <machine/rtems-bsd-kernel-space.h> and
<machine/rtems-bsd-user-space.h> similar to the libbsd to avoid command
line defines and defines scattered throught the code base.

Simplify cpukit/libnetworking/Makefile.am.

Update #3375.

  • Property mode set to 100644
File size: 48.6 KB
Line 
1/*
2 * Gaisler Research ethernet MAC driver
3 * adapted from Opencores driver by Marko Isomaki
4 *
5 *  The license and distribution terms for this file may be
6 *  found in found in the file LICENSE in this distribution or at
7 *  http://www.rtems.org/license/LICENSE.
8 *
9 *
10 *  2008-12-10, Converted to driver manager and added support for
11 *              multiple GRETH cores. <daniel@gaisler.com>
12 *  2007-09-07, Ported GBIT support from 4.6.5
13 */
14
15#include <machine/rtems-bsd-kernel-space.h>
16
17#include <rtems.h>
18#define CPU_U32_FIX
19#include <bsp.h>
20
21#ifdef GRETH_SUPPORTED
22
23#include <inttypes.h>
24#include <errno.h>
25#include <rtems/bspIo.h>
26#include <stdlib.h>
27#include <stdio.h>
28#include <stdarg.h>
29#include <rtems/error.h>
30#include <rtems/rtems_bsdnet.h>
31
32#include <bsp/greth.h>
33#include <drvmgr/drvmgr.h>
34#include <drvmgr/ambapp_bus.h>
35#include <ambapp.h>
36
37#include <sys/param.h>
38#include <sys/mbuf.h>
39
40#include <sys/socket.h>
41#include <sys/sockio.h>
42#include <net/if.h>
43#include <netinet/in.h>
44#include <netinet/if_ether.h>
45
46/* map via rtems_interrupt_lock_* API: */
47#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock)
48#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name)
49#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level)
50#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level)
51#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level)
52#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level)
53#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k
54#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k)
55
56#ifdef malloc
57#undef malloc
58#endif
59#ifdef free
60#undef free
61#endif
62
63#if defined(__m68k__)
64extern m68k_isr_entry set_vector( rtems_isr_entry, rtems_vector_number, int );
65#else
66extern rtems_isr_entry set_vector( rtems_isr_entry, rtems_vector_number, int );
67#endif
68
69
70/* #define GRETH_DEBUG */
71
72#ifdef GRETH_DEBUG
73#define DBG(args...) printk(args)
74#else
75#define DBG(args...)
76#endif
77
78/* #define GRETH_DEBUG_MII */
79
80#ifdef GRETH_DEBUG_MII
81#define MIIDBG(args...) printk(args)
82#else
83#define MIIDBG(args...)
84#endif
85
86#ifdef CPU_U32_FIX
87extern void ipalign(struct mbuf *m);
88#endif
89
90/* Used when reading from memory written by GRETH DMA unit */
91#ifndef GRETH_MEM_LOAD
92#define GRETH_MEM_LOAD(addr) (*(volatile unsigned int *)(addr))
93#endif
94
95/*
96 * Number of OCs supported by this driver
97 */
98#define NOCDRIVER       1
99
100/*
101 * Receive buffer size -- Allow for a full ethernet packet including CRC
102 */
103#define RBUF_SIZE 1518
104
105#define ET_MINLEN 64            /* minimum message length */
106
107/*
108 * RTEMS event used by interrupt handler to signal driver tasks.
109 * This must not be any of the events used by the network task synchronization.
110 */
111#define INTERRUPT_EVENT RTEMS_EVENT_1
112
113/*
114 * RTEMS event used to start transmit daemon.
115 * This must not be the same as INTERRUPT_EVENT.
116 */
117#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
118
119 /* event to send when tx buffers become available */
120#define GRETH_TX_WAIT_EVENT  RTEMS_EVENT_3
121
122#if (MCLBYTES < RBUF_SIZE)
123# error "Driver must have MCLBYTES > RBUF_SIZE"
124#endif
125
126/* 4s Autonegotiation Timeout */
127#ifndef GRETH_AUTONEGO_TIMEOUT_MS
128#define GRETH_AUTONEGO_TIMEOUT_MS 4000
129#endif
130const struct timespec greth_tan = {
131   GRETH_AUTONEGO_TIMEOUT_MS/1000,
132   (GRETH_AUTONEGO_TIMEOUT_MS % 1000) * 1000000
133};
134
135/* For optimizing the autonegotiation time */
136#define GRETH_AUTONEGO_PRINT_TIME
137
138/* Ethernet buffer descriptor */
139
140typedef struct _greth_rxtxdesc {
141   volatile uint32_t ctrl; /* Length and status */
142   uint32_t *addr;         /* Buffer pointer */
143} greth_rxtxdesc;
144
145
146/*
147 * Per-device data
148 */
149struct greth_softc
150{
151
152   struct arpcom arpcom;
153   struct drvmgr_dev *dev;              /* Driver manager device */
154   char devName[32];
155
156   greth_regs *regs;
157   int minor;
158   int phyaddr;  /* PHY Address configured by user (or -1 to autodetect) */
159   unsigned int edcl_dis;
160   int greth_rst;
161
162   int acceptBroadcast;
163   rtems_id daemonTid;
164   
165   unsigned int tx_ptr;
166   unsigned int tx_dptr;
167   unsigned int tx_cnt;
168   unsigned int rx_ptr;
169   unsigned int txbufs;
170   unsigned int rxbufs;
171   greth_rxtxdesc *txdesc;
172   greth_rxtxdesc *rxdesc;
173   unsigned int txdesc_remote;
174   unsigned int rxdesc_remote;
175   struct mbuf **rxmbuf;
176   struct mbuf **txmbuf;
177   rtems_vector_number vector;
178   
179   /* TX descriptor interrupt generation */
180   int tx_int_gen;
181   int tx_int_gen_cur;
182   struct mbuf *next_tx_mbuf;
183   int max_fragsize;
184   
185   /*Status*/
186   struct phy_device_info phydev;
187   int phy_read_access;
188   int phy_write_access;
189   int fd;
190   int sp;
191   int gb;
192   int gbit_mac;
193   int auto_neg;
194   unsigned int advmodes; /* advertise ethernet speed modes. 0 = all modes. */
195   struct timespec auto_neg_time;
196   int mc_available;
197
198   /*
199    * Statistics
200    */
201   unsigned long rxInterrupts;
202   
203   unsigned long rxPackets;
204   unsigned long rxLengthError;
205   unsigned long rxNonOctet;
206   unsigned long rxBadCRC;
207   unsigned long rxOverrun;
208   
209   unsigned long txInterrupts;
210   
211   unsigned long txDeferred;
212   unsigned long txHeartbeat;
213   unsigned long txLateCollision;
214   unsigned long txRetryLimit;
215   unsigned long txUnderrun;
216
217   /* Spin-lock ISR protection */
218   SPIN_DECLARE(devlock);
219};
220
221int greth_process_tx_gbit(struct greth_softc *sc);
222int greth_process_tx(struct greth_softc *sc);
223
224static char *almalloc(int sz, int alignment)
225{
226        char *tmp;
227        tmp = calloc(1, sz + (alignment-1));
228        tmp = (char *) (((int)tmp+alignment) & ~(alignment -1));
229        return(tmp);
230}
231
232/* GRETH interrupt handler */
233
234static void greth_interrupt (void *arg)
235{
236        uint32_t status;
237        uint32_t ctrl;
238        rtems_event_set events = 0;
239        struct greth_softc *greth = arg;
240        SPIN_ISR_IRQFLAGS(flags);
241
242        /* read and clear interrupt cause */
243        status = greth->regs->status;
244        greth->regs->status = status;
245
246        SPIN_LOCK(&greth->devlock, flags);
247        ctrl = greth->regs->ctrl;
248
249        /* Frame received? */
250        if ((ctrl & GRETH_CTRL_RXIRQ) && (status & (GRETH_STATUS_RXERR | GRETH_STATUS_RXIRQ)))
251        {
252                greth->rxInterrupts++;
253                /* Stop RX-Error and RX-Packet interrupts */
254                ctrl &= ~GRETH_CTRL_RXIRQ;
255                events |= INTERRUPT_EVENT;
256        }
257
258        if ( (ctrl & GRETH_CTRL_TXIRQ) && (status & (GRETH_STATUS_TXERR | GRETH_STATUS_TXIRQ)) )
259        {
260                greth->txInterrupts++;
261                ctrl &= ~GRETH_CTRL_TXIRQ;
262                events |= GRETH_TX_WAIT_EVENT;
263        }
264
265        /* Clear interrupt sources */
266        greth->regs->ctrl = ctrl;
267        SPIN_UNLOCK(&greth->devlock, flags);
268
269        /* Send the event(s) */
270        if ( events )
271            rtems_bsdnet_event_send(greth->daemonTid, events);
272}
273
274static uint32_t read_mii(struct greth_softc *sc, uint32_t phy_addr, uint32_t reg_addr)
275{
276    sc->phy_read_access++;
277    while (sc->regs->mdio_ctrl & GRETH_MDIO_BUSY) {}
278    sc->regs->mdio_ctrl = (phy_addr << 11) | (reg_addr << 6) | GRETH_MDIO_READ;
279    while (sc->regs->mdio_ctrl & GRETH_MDIO_BUSY) {}
280    if (!(sc->regs->mdio_ctrl & GRETH_MDIO_LINKFAIL)) {
281        MIIDBG("greth%d: mii read[%d] OK to %" PRIx32 ".%" PRIx32
282               " (0x%08" PRIx32 ",0x%08" PRIx32 ")\n",
283               sc->minor, sc->phy_read_access, phy_addr, reg_addr,
284               sc->regs->ctrl, sc->regs->mdio_ctrl);
285        return((sc->regs->mdio_ctrl >> 16) & 0xFFFF);
286    } else {
287        printf("greth%d: mii read[%d] failed to %" PRIx32 ".%" PRIx32
288               " (0x%08" PRIx32 ",0x%08" PRIx32 ")\n",
289               sc->minor, sc->phy_read_access, phy_addr, reg_addr,
290               sc->regs->ctrl, sc->regs->mdio_ctrl);
291        return (0xffff);
292    }
293}
294
295static void write_mii(struct greth_softc *sc, uint32_t phy_addr, uint32_t reg_addr, uint32_t data)
296{
297    sc->phy_write_access++;
298    while (sc->regs->mdio_ctrl & GRETH_MDIO_BUSY) {}
299    sc->regs->mdio_ctrl =
300     ((data & 0xFFFF) << 16) | (phy_addr << 11) | (reg_addr << 6) | GRETH_MDIO_WRITE;
301    while (sc->regs->mdio_ctrl & GRETH_MDIO_BUSY) {}
302    if (!(sc->regs->mdio_ctrl & GRETH_MDIO_LINKFAIL)) {
303        MIIDBG("greth%d: mii write[%d] OK to  to %" PRIx32 ".%" PRIx32
304               "(0x%08" PRIx32 ",0x%08" PRIx32 ")\n",
305               sc->minor, sc->phy_write_access, phy_addr, reg_addr,
306               sc->regs->ctrl, sc->regs->mdio_ctrl);
307    } else {
308        printf("greth%d: mii write[%d] failed to to %" PRIx32 ".%" PRIx32
309               " (0x%08" PRIx32 ",0x%08" PRIx32 ")\n",
310               sc->minor, sc->phy_write_access, phy_addr, reg_addr,
311               sc->regs->ctrl, sc->regs->mdio_ctrl);
312    }
313}
314
315static void print_init_info(struct greth_softc *sc)
316{
317    printf("greth: driver attached\n");
318    if ( sc->auto_neg == -1 ){
319        printf("Auto negotiation timed out. Selecting default config\n");
320    }
321    printf("**** PHY ****\n");
322    printf("Vendor: %x   Device: %x   Revision: %d\n",sc->phydev.vendor, sc->phydev.device, sc->phydev.rev);
323    printf("Current Operating Mode: ");
324    if (sc->gb) {
325        printf("1000 Mbit ");
326    } else if (sc->sp) {
327        printf("100 Mbit ");
328    } else {
329        printf("10 Mbit ");
330    }
331    if (sc->fd) {
332        printf("Full Duplex\n");
333    } else {
334        printf("Half Duplex\n");
335    }
336#ifdef GRETH_AUTONEGO_PRINT_TIME
337    if ( sc->auto_neg ) {
338        printf("Autonegotiation Time: %ldms\n", sc->auto_neg_time.tv_sec * 1000 +
339               sc->auto_neg_time.tv_nsec / 1000000);
340    }
341#endif
342}
343
344/*
345 * Generates the hash words based on CRCs of the enabled MAC addresses that are
346 * allowed to be received. The allowed MAC addresses are maintained in a linked
347 * "multi-cast" list available in the arpcom structure.
348 *
349 * Returns the number of MAC addresses that were processed (in the list)
350 */
351static int
352greth_mac_filter_calc(struct arpcom *ac, uint32_t *msb, uint32_t *lsb)
353{
354    struct ether_multistep step;
355    struct ether_multi *enm;
356    int cnt = 0;
357    uint32_t crc, htindex, ht[2] = {0, 0};
358
359    /* Go through the Ethernet Multicast addresses one by one and add their
360     * CRC contribution to the MAC filter.
361     */
362    ETHER_FIRST_MULTI(step, ac, enm);
363    while (enm) {
364        crc = ether_crc32_be((uint8_t *)enm->enm_addrlo, 6);
365        htindex = crc & 0x3f;
366        ht[htindex >> 5] |= (1 << (htindex & 0x1F));
367        cnt++;
368        ETHER_NEXT_MULTI(step, enm);
369    }
370
371    if (cnt > 0) {
372        *msb = ht[1];
373        *lsb = ht[0];
374    }
375
376    return cnt;
377}
378
379/*
380 * Initialize the ethernet hardware
381 */
382static int greth_mac_filter_set(struct greth_softc *sc)
383{
384    struct ifnet *ifp = &sc->arpcom.ac_if;
385    uint32_t hash_msb, hash_lsb, ctrl;
386    SPIN_IRQFLAGS(flags);
387
388    hash_msb = 0;
389    hash_lsb = 0;
390    ctrl = 0;
391    if (ifp->if_flags & IFF_PROMISC) {
392        /* No need to enable multi-cast when promiscous mode accepts all */
393        ctrl |= GRETH_CTRL_PRO;
394    } else if(!sc->mc_available) {
395        return EINVAL; /* no hardware support for multicast filtering. */
396    } else if (ifp->if_flags & IFF_ALLMULTI) {
397        /* We should accept all multicast addresses */
398        ctrl |= GRETH_CTRL_MCE;
399        hash_msb = 0xFFFFFFFF;
400        hash_lsb = 0xFFFFFFFF;
401    } else if (greth_mac_filter_calc(&sc->arpcom, &hash_msb, &hash_lsb) > 0) {
402        /* Generate hash for MAC filtering out multicast addresses */
403        ctrl |= GRETH_CTRL_MCE;
404    } else {
405        /* Multicast list is empty .. disable multicast */
406    }
407    SPIN_LOCK_IRQ(&sc->devlock, flags);
408    sc->regs->ht_msb = hash_msb;
409    sc->regs->ht_lsb = hash_lsb;
410    sc->regs->ctrl = (sc->regs->ctrl & ~(GRETH_CTRL_PRO | GRETH_CTRL_MCE)) |
411                     ctrl;
412    SPIN_UNLOCK_IRQ(&sc->devlock, flags);
413
414    return 0;
415}
416
417/*
418 * Initialize the ethernet hardware
419 */
420static void
421greth_initialize_hardware (struct greth_softc *sc)
422{
423    struct mbuf *m;
424    int i;
425    int phyaddr;
426    int phyctrl;
427    int phystatus;
428    int tmp1;
429    int tmp2;
430    struct timespec tstart, tnow;
431    greth_regs *regs;
432    unsigned int advmodes, speed;
433
434    regs = sc->regs;
435
436    /* Reset the controller.  */
437    sc->rxInterrupts = 0;
438    sc->rxPackets = 0;
439
440    if (sc->greth_rst) {
441        /* Reset ON */
442        regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED;
443        for (i = 0; i<100 && (regs->ctrl & GRETH_CTRL_RST); i++)
444            ;
445        speed = 0; /* probe mode below */
446    } else {
447        /* inherit EDCL mode for now */
448        speed = sc->regs->ctrl & (GRETH_CTRL_GB|GRETH_CTRL_SP|GRETH_CTRL_FULLD);
449    }
450    /* Reset OFF and RX/TX DMA OFF. SW do PHY Init */
451    regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
452
453    /* Check if mac is gbit capable*/
454    sc->gbit_mac = (regs->ctrl >> 27) & 1;
455
456    /* Get the phy address which assumed to have been set
457       correctly with the reset value in hardware*/
458    if ( sc->phyaddr == -1 ) {
459        phyaddr = (regs->mdio_ctrl >> 11) & 0x1F;
460    } else {
461        phyaddr = sc->phyaddr;
462    }
463    sc->phy_read_access = 0;
464    sc->phy_write_access = 0;
465
466    /* As I understand the PHY comes back to a good default state after
467     * Power-down or Reset, so we do both just in case. Power-down bit should
468     * be cleared.
469     * Wait for old reset (if asserted by boot loader) to complete, otherwise
470     * power-down instruction might not have any effect.
471     */
472    while (read_mii(sc, phyaddr, 0) & 0x8000) {}
473    write_mii(sc, phyaddr, 0, 0x0800); /* Power-down */
474    write_mii(sc, phyaddr, 0, 0x0000); /* Power-Up */
475    write_mii(sc, phyaddr, 0, 0x8000); /* Reset */
476
477    /* We wait about 30ms */
478    rtems_task_wake_after(rtems_clock_get_ticks_per_second()/32);
479
480    /* Wait for reset to complete and get default values */
481    while ((phyctrl = read_mii(sc, phyaddr, 0)) & 0x8000) {}
482
483    /* Set up PHY advertising modes for auto-negotiation */
484    advmodes = sc->advmodes;
485    if (advmodes == 0)
486        advmodes = GRETH_ADV_ALL;
487    if (!sc->gbit_mac)
488        advmodes &= ~(GRETH_ADV_1000_FD | GRETH_ADV_1000_HD);
489
490    /* Enable/Disable GBit auto-neg advetisement so that the link partner
491     * know that we have/haven't GBit capability. The MAC may not support
492     * Gbit even though PHY does...
493     */
494    phystatus = read_mii(sc, phyaddr, 1);
495    if (phystatus & 0x0100) {
496        tmp1 = read_mii(sc, phyaddr, 9);
497        tmp1 &= ~0x300;
498        if (advmodes & GRETH_ADV_1000_FD)
499            tmp1 |= 0x200;
500        if (advmodes & GRETH_ADV_1000_HD)
501            tmp1 |= 0x100;
502        write_mii(sc, phyaddr, 9, tmp1);
503    }
504
505    /* Optionally limit the 10/100 modes as configured by user */
506    tmp1 = read_mii(sc, phyaddr, 4);
507    tmp1 &= ~0x1e0;
508    if (advmodes & GRETH_ADV_100_FD)
509        tmp1 |= 0x100;
510    if (advmodes & GRETH_ADV_100_HD)
511        tmp1 |= 0x080;
512    if (advmodes & GRETH_ADV_10_FD)
513        tmp1 |= 0x040;
514    if (advmodes & GRETH_ADV_10_HD)
515        tmp1 |= 0x020;
516    write_mii(sc, phyaddr, 4, tmp1);
517
518    /* If autonegotiation implemented we start it */
519    if (phystatus & 0x0008) {
520        write_mii(sc, phyaddr, 0, phyctrl | 0x1200);
521        phyctrl = read_mii(sc, phyaddr, 0);
522    }
523
524    /* Check if PHY is autoneg capable and then determine operating mode,
525       otherwise force it to 10 Mbit halfduplex */
526    sc->gb = 0;
527    sc->fd = 0;
528    sc->sp = 0;
529    sc->auto_neg = 0;
530    _Timespec_Set_to_zero(&sc->auto_neg_time);
531    if ((phyctrl >> 12) & 1) {
532            /*wait for auto negotiation to complete*/
533            sc->auto_neg = 1;
534            if (rtems_clock_get_uptime(&tstart) != RTEMS_SUCCESSFUL)
535                    printk("rtems_clock_get_uptime failed\n");
536            while (!(((phystatus = read_mii(sc, phyaddr, 1)) >> 5) & 1)) {
537                    if (rtems_clock_get_uptime(&tnow) != RTEMS_SUCCESSFUL)
538                            printk("rtems_clock_get_uptime failed\n");
539                    _Timespec_Subtract(&tstart, &tnow, &sc->auto_neg_time);
540                    if (_Timespec_Greater_than(&sc->auto_neg_time, &greth_tan)) {
541                            sc->auto_neg = -1; /* Failed */
542                            tmp1 = read_mii(sc, phyaddr, 0);
543                            sc->gb = ((phyctrl >> 6) & 1) && !((phyctrl >> 13) & 1);
544                            sc->sp = !((phyctrl >> 6) & 1) && ((phyctrl >> 13) & 1);
545                            sc->fd = (phyctrl >> 8) & 1;
546                            goto auto_neg_done;
547                    }
548                    /* Wait about 30ms, time is PHY dependent */
549                    rtems_task_wake_after(rtems_clock_get_ticks_per_second()/32);
550            }
551            sc->phydev.adv = read_mii(sc, phyaddr, 4);
552            sc->phydev.part = read_mii(sc, phyaddr, 5);
553            if ((phystatus >> 8) & 1) {
554                    sc->phydev.extadv = read_mii(sc, phyaddr, 9);
555                    sc->phydev.extpart = read_mii(sc, phyaddr, 10);
556                       if ( (sc->phydev.extadv & GRETH_MII_EXTADV_1000HD) &&
557                            (sc->phydev.extpart & GRETH_MII_EXTPRT_1000HD)) {
558                               sc->gb = 1;
559                               sc->fd = 0;
560                       }
561                       if ( (sc->phydev.extadv & GRETH_MII_EXTADV_1000FD) &&
562                            (sc->phydev.extpart & GRETH_MII_EXTPRT_1000FD)) {
563                               sc->gb = 1;
564                               sc->fd = 1;
565                       }
566            }
567            if ((sc->gb == 0) || ((sc->gb == 1) && (sc->gbit_mac == 0))) {
568                    if ( (sc->phydev.adv & GRETH_MII_100TXFD) &&
569                         (sc->phydev.part & GRETH_MII_100TXFD)) {
570                            sc->sp = 1;
571                            sc->fd = 1;
572                    } else if ( (sc->phydev.adv & GRETH_MII_100TXHD) &&
573                                (sc->phydev.part & GRETH_MII_100TXHD)) {
574                            sc->sp = 1;
575                            sc->fd = 0;
576                    } else if ( (sc->phydev.adv & GRETH_MII_10FD) &&
577                                (sc->phydev.part & GRETH_MII_10FD)) {
578                            sc->fd = 1;
579                    }
580            }
581    }
582auto_neg_done:
583    sc->phydev.vendor = 0;
584    sc->phydev.device = 0;
585    sc->phydev.rev = 0;
586    phystatus = read_mii(sc, phyaddr, 1);
587
588    /* Read out PHY info if extended registers are available */
589    if (phystatus & 1) { 
590            tmp1 = read_mii(sc, phyaddr, 2);
591            tmp2 = read_mii(sc, phyaddr, 3);
592
593            sc->phydev.vendor = (tmp1 << 6) | ((tmp2 >> 10) & 0x3F);
594            sc->phydev.rev = tmp2 & 0xF;
595            sc->phydev.device = (tmp2 >> 4) & 0x3F;
596    }
597
598    /* Force to 10 mbit half duplex if the 10/100 MAC is used with a 1000 PHY */
599    if (((sc->gb) && !(sc->gbit_mac)) || !((phyctrl >> 12) & 1)) {
600        write_mii(sc, phyaddr, 0, sc->sp << 13);
601
602        /* check if marvell 88EE1111 PHY. Needs special reset handling */
603        if ((phystatus & 1) && (sc->phydev.vendor == 0x005043) &&
604            (sc->phydev.device == 0x0C))
605            write_mii(sc, phyaddr, 0, 0x8000);
606
607        sc->gb = 0;
608        sc->sp = 0;
609        sc->fd = 0;
610    }
611    while ((read_mii(sc, phyaddr, 0)) & 0x8000) {}
612
613    if (sc->greth_rst) {
614        /* Reset ON */
615        regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED;
616        for (i = 0; i < 100 && (regs->ctrl & GRETH_CTRL_RST); i++)
617            ;
618    }
619    /* Reset OFF. Set mode matching PHY settings. */
620    speed = (sc->gb << 8) | (sc->sp << 7) | (sc->fd << 4);
621    regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis | speed;
622
623    /* Initialize rx/tx descriptor table pointers. Due to alignment we
624     * always allocate maximum table size.
625     */
626    sc->txdesc = (greth_rxtxdesc *) almalloc(0x800, 0x400);
627    sc->rxdesc = (greth_rxtxdesc *) &sc->txdesc[128];
628    sc->tx_ptr = 0;
629    sc->tx_dptr = 0;
630    sc->tx_cnt = 0;
631    sc->rx_ptr = 0;
632
633    /* Translate the Descriptor DMA table base address into an address that
634     * the GRETH core can understand
635     */
636    drvmgr_translate_check(
637        sc->dev,
638        CPUMEM_TO_DMA,
639        (void *)sc->txdesc,
640        (void **)&sc->txdesc_remote,
641        0x800);
642    sc->rxdesc_remote = sc->txdesc_remote + 0x400;
643    regs->txdesc = (int) sc->txdesc_remote;
644    regs->rxdesc = (int) sc->rxdesc_remote;
645
646    sc->rxmbuf = calloc(sc->rxbufs, sizeof(*sc->rxmbuf));
647    sc->txmbuf = calloc(sc->txbufs, sizeof(*sc->txmbuf));
648
649    for (i = 0; i < sc->txbufs; i++)
650      {
651        sc->txdesc[i].ctrl = 0;
652        if (!(sc->gbit_mac)) {
653            drvmgr_translate_check(
654                sc->dev,
655                CPUMEM_TO_DMA,
656                (void *)malloc(GRETH_MAXBUF_LEN),
657                (void **)&sc->txdesc[i].addr,
658                GRETH_MAXBUF_LEN);
659        }
660#ifdef GRETH_DEBUG
661              /* printf("TXBUF: %08x\n", (int) sc->txdesc[i].addr); */
662#endif
663      }
664    for (i = 0; i < sc->rxbufs; i++)
665      {
666         MGETHDR (m, M_WAIT, MT_DATA);
667          MCLGET (m, M_WAIT);
668          if (sc->gbit_mac)
669                  m->m_data += 2;
670          m->m_pkthdr.rcvif = &sc->arpcom.ac_if;
671          sc->rxmbuf[i] = m;
672          drvmgr_translate_check(
673            sc->dev,
674            CPUMEM_TO_DMA,
675            (void *)mtod(m, uint32_t *),
676            (void **)&sc->rxdesc[i].addr,
677            GRETH_MAXBUF_LEN);
678          sc->rxdesc[i].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ;
679#ifdef GRETH_DEBUG
680/*        printf("RXBUF: %08x\n", (int) sc->rxdesc[i].addr); */
681#endif
682      }
683    sc->rxdesc[sc->rxbufs - 1].ctrl |= GRETH_RXD_WRAP;
684
685    /* set ethernet address.  */
686    regs->mac_addr_msb =
687      sc->arpcom.ac_enaddr[0] << 8 | sc->arpcom.ac_enaddr[1];
688    regs->mac_addr_lsb =
689      sc->arpcom.ac_enaddr[2] << 24 | sc->arpcom.ac_enaddr[3] << 16 |
690      sc->arpcom.ac_enaddr[4] << 8 | sc->arpcom.ac_enaddr[5];
691
692    if ( sc->rxbufs < 10 ) {
693        sc->tx_int_gen = sc->tx_int_gen_cur = 1;
694    }else{
695        sc->tx_int_gen = sc->tx_int_gen_cur = sc->txbufs/2;
696    }
697    sc->next_tx_mbuf = NULL;
698
699    if ( !sc->gbit_mac )
700        sc->max_fragsize = 1;
701
702    /* clear all pending interrupts */
703    regs->status = 0xffffffff;
704
705    /* install interrupt handler */
706    drvmgr_interrupt_register(sc->dev, 0, "greth", greth_interrupt, sc);
707
708    regs->ctrl |= GRETH_CTRL_RXEN | GRETH_CTRL_RXIRQ;
709
710    print_init_info(sc);
711}
712
713#ifdef CPU_U32_FIX
714
715/*
716 * Routine to align the received packet so that the ip header
717 * is on a 32-bit boundary. Necessary for cpu's that do not
718 * allow unaligned loads and stores and when the 32-bit DMA
719 * mode is used.
720 *
721 * Transfers are done on word basis to avoid possibly slow byte
722 * and half-word writes.
723 */
724
725void ipalign(struct mbuf *m)
726{
727  unsigned int *first, *last, data;
728  unsigned int tmp = 0;
729
730  if ((((int) m->m_data) & 2) && (m->m_len)) {
731    last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3);
732    first = (unsigned int *) (((int) m->m_data) & ~3);
733                /* tmp = *first << 16; */
734                asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(first) );
735                tmp = tmp << 16;
736    first++;
737    do {
738                        /* When snooping is not available the LDA instruction must be used
739                         * to avoid the cache to return an illegal value.
740                         ** Load with forced cache miss
741                         * data = *first;
742                         */
743      asm volatile (" lda [%1] 1, %0\n" : "=r"(data) : "r"(first) );
744      *first = tmp | (data >> 16);
745      tmp = data << 16;
746      first++;
747    } while (first <= last);
748
749    m->m_data = (caddr_t)(((int) m->m_data) + 2);
750  }
751}
752#endif
753
754static void
755greth_Daemon (void *arg)
756{
757    struct ether_header *eh;
758    struct greth_softc *dp = (struct greth_softc *) arg;
759    struct ifnet *ifp = &dp->arpcom.ac_if;
760    struct mbuf *m;
761    unsigned int len, len_status, bad;
762    rtems_event_set events;
763    SPIN_IRQFLAGS(flags);
764    int first;
765    int tmp;
766    unsigned int addr;
767
768    for (;;)
769      {
770        rtems_bsdnet_event_receive (INTERRUPT_EVENT | GRETH_TX_WAIT_EVENT,
771                                    RTEMS_WAIT | RTEMS_EVENT_ANY,
772                                    RTEMS_NO_TIMEOUT, &events);
773       
774        if ( events & GRETH_TX_WAIT_EVENT ){
775            /* TX interrupt.
776             * We only end up here when all TX descriptors has been used,
777             * and
778             */
779            if ( dp->gbit_mac )
780                greth_process_tx_gbit(dp);
781            else
782                greth_process_tx(dp);
783           
784            /* If we didn't get a RX interrupt we don't process it */
785            if ( (events & INTERRUPT_EVENT) == 0 )
786                continue;
787        }
788       
789       
790#ifdef GRETH_ETH_DEBUG
791    printf ("r\n");
792#endif
793    first=1;
794    /* Scan for Received packets */
795again:
796    while (!((len_status =
797                    GRETH_MEM_LOAD(&dp->rxdesc[dp->rx_ptr].ctrl)) & GRETH_RXD_ENABLE))
798            {
799                    bad = 0;
800                    if (len_status & GRETH_RXD_TOOLONG)
801                    {
802                            dp->rxLengthError++;
803                            bad = 1;
804                    }
805                    if (len_status & GRETH_RXD_DRIBBLE)
806                    {
807                            dp->rxNonOctet++;
808                            bad = 1;
809                    }
810                    if (len_status & GRETH_RXD_CRCERR)
811                    {
812                            dp->rxBadCRC++;
813                            bad = 1;
814                    }
815                    if (len_status & GRETH_RXD_OVERRUN)
816                    {
817                            dp->rxOverrun++;
818                            bad = 1;
819                    }
820                    if (len_status & GRETH_RXD_LENERR)
821                    {
822                            dp->rxLengthError++;
823                            bad = 1;
824                    }
825                    if (!bad)
826                    {
827                            /* pass on the packet in the receive buffer */
828                            len = len_status & 0x7FF;
829                            m = dp->rxmbuf[dp->rx_ptr];
830#ifdef GRETH_DEBUG
831                            int i;
832                            printf("RX: 0x%08x, Len: %d : ", (int) m->m_data, len);
833                            for (i=0; i<len; i++)
834                                    printf("%x%x", (m->m_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff);
835                            printf("\n");
836#endif
837                            m->m_len = m->m_pkthdr.len =
838                                    len - sizeof (struct ether_header);
839
840                            eh = mtod (m, struct ether_header *);
841
842                            m->m_data += sizeof (struct ether_header);
843#ifdef CPU_U32_FIX
844                            if(!dp->gbit_mac) {
845                                    /* OVERRIDE CACHED ETHERNET HEADER FOR NON-SNOOPING SYSTEMS */
846                                    addr = (unsigned int)eh;
847                                    asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) );
848                                    addr+=4;
849                                    asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) );
850                                    addr+=4;
851                                    asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) );
852                                    addr+=4;
853                                    asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) );
854
855                                    ipalign(m); /* Align packet on 32-bit boundary */
856                            }
857#endif
858/*
859                            if(!(dp->gbit_mac) && !CPU_SPARC_HAS_SNOOPING) {
860                                    rtems_cache_invalidate_entire_data();
861                            }
862*/
863                            ether_input (ifp, eh, m);
864                            MGETHDR (m, M_WAIT, MT_DATA);
865                            MCLGET (m, M_WAIT);
866                            if (dp->gbit_mac)
867                                    m->m_data += 2;
868                            dp->rxmbuf[dp->rx_ptr] = m;
869                            m->m_pkthdr.rcvif = ifp;
870                            drvmgr_translate_check(
871                                dp->dev,
872                                CPUMEM_TO_DMA,
873                                (void *)mtod (m, uint32_t *),
874                                (void **)&dp->rxdesc[dp->rx_ptr].addr,
875                                GRETH_MAXBUF_LEN);
876                            dp->rxPackets++;
877                    }
878                    if (dp->rx_ptr == dp->rxbufs - 1) {
879                            dp->rxdesc[dp->rx_ptr].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ | GRETH_RXD_WRAP;
880                    } else {
881                            dp->rxdesc[dp->rx_ptr].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ;
882                    }
883                    SPIN_LOCK_IRQ(&dp->devlock, flags);
884                    dp->regs->ctrl |= GRETH_CTRL_RXEN;
885                    SPIN_UNLOCK_IRQ(&dp->devlock, flags);
886                    dp->rx_ptr = (dp->rx_ptr + 1) % dp->rxbufs;
887            }
888
889        /* Always scan twice to avoid deadlock */
890        if ( first ){
891            first=0;
892            SPIN_LOCK_IRQ(&dp->devlock, flags);
893            dp->regs->ctrl |= GRETH_CTRL_RXIRQ;
894            SPIN_UNLOCK_IRQ(&dp->devlock, flags);
895            goto again;
896        }
897
898      }
899}
900
901static int
902sendpacket (struct ifnet *ifp, struct mbuf *m)
903{
904    struct greth_softc *dp = ifp->if_softc;
905    unsigned char *temp;
906    struct mbuf *n;
907    unsigned int len;
908    SPIN_IRQFLAGS(flags);
909
910    /*
911     * Is there a free descriptor available?
912     */
913    if (GRETH_MEM_LOAD(&dp->txdesc[dp->tx_ptr].ctrl) & GRETH_TXD_ENABLE){
914            /* No. */
915            return 1;
916    }
917   
918    /* Remember head of chain */
919    n = m;
920
921    len = 0;
922    temp = (unsigned char *) GRETH_MEM_LOAD(&dp->txdesc[dp->tx_ptr].addr);
923    drvmgr_translate(dp->dev, CPUMEM_FROM_DMA, (void *)temp, (void **)&temp);
924#ifdef GRETH_DEBUG
925    printf("TXD: 0x%08x : BUF: 0x%08x\n", (int) m->m_data, (int) temp);
926#endif
927    for (;;)
928    {
929#ifdef GRETH_DEBUG
930            int i;
931            printf("MBUF: 0x%08x : ", (int) m->m_data);
932            for (i=0;i<m->m_len;i++)
933                    printf("%x%x", (m->m_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff);
934            printf("\n");
935#endif
936            len += m->m_len;
937            if (len <= RBUF_SIZE)
938                    memcpy ((void *) temp, (char *) m->m_data, m->m_len);
939            temp += m->m_len;
940            if ((m = m->m_next) == NULL)
941                    break;
942    }
943
944    m_freem (n);
945
946    /* don't send long packets */
947
948    if (len <= GRETH_MAXBUF_LEN) {
949            if (dp->tx_ptr < dp->txbufs-1) {
950                    dp->txdesc[dp->tx_ptr].ctrl = GRETH_TXD_IRQ |
951                                                  GRETH_TXD_ENABLE | len;
952            } else {
953                    dp->txdesc[dp->tx_ptr].ctrl = GRETH_TXD_IRQ |
954                            GRETH_TXD_WRAP | GRETH_TXD_ENABLE | len;
955            }
956            dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs;
957            SPIN_LOCK_IRQ(&dp->devlock, flags);
958            dp->regs->ctrl = dp->regs->ctrl | GRETH_CTRL_TXEN;
959            SPIN_UNLOCK_IRQ(&dp->devlock, flags);
960    }
961
962    return 0;
963}
964
965
966static int
967sendpacket_gbit (struct ifnet *ifp, struct mbuf *m)
968{
969        struct greth_softc *dp = ifp->if_softc;
970        unsigned int len;
971       
972        unsigned int ctrl;
973        int frags;
974        struct mbuf *mtmp;
975        int int_en;
976        SPIN_IRQFLAGS(flags);
977
978        len = 0;
979#ifdef GRETH_DEBUG
980        printf("TXD: 0x%08x\n", (int) m->m_data);
981#endif
982        /* Get number of fragments too see if we have enough
983         * resources.
984         */
985        frags=1;
986        mtmp=m;
987        while(mtmp->m_next){
988            frags++;
989            mtmp = mtmp->m_next;
990        }
991
992        if ( frags > dp->max_fragsize )
993            dp->max_fragsize = frags;
994       
995        if ( frags > dp->txbufs ){
996            printf("GRETH: MBUF-chain cannot be sent. Increase descriptor count.\n");
997            return -1;
998        }
999       
1000        if ( frags > (dp->txbufs-dp->tx_cnt) ){
1001            /* Return number of fragments */
1002            return frags;
1003        }
1004       
1005       
1006        /* Enable interrupt from descriptor every tx_int_gen
1007         * descriptor. Typically every 16 descriptor. This
1008         * is only to reduce the number of interrupts during
1009         * heavy load.
1010         */
1011        dp->tx_int_gen_cur-=frags;
1012        if ( dp->tx_int_gen_cur <= 0 ){
1013            dp->tx_int_gen_cur = dp->tx_int_gen;
1014            int_en = GRETH_TXD_IRQ;
1015        }else{
1016            int_en = 0;
1017        }
1018       
1019        /* At this stage we know that enough descriptors are available */
1020        for (;;)
1021        {
1022               
1023#ifdef GRETH_DEBUG
1024            int i;
1025            printf("MBUF: 0x%08x, Len: %d : ", (int) m->m_data, m->m_len);
1026            for (i=0; i<m->m_len; i++)
1027                printf("%x%x", (m->m_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff);
1028            printf("\n");
1029#endif
1030            len += m->m_len;
1031            drvmgr_translate_check(
1032                dp->dev,
1033                CPUMEM_TO_DMA,
1034                (void *)(uint32_t *)m->m_data,
1035                (void **)&dp->txdesc[dp->tx_ptr].addr,
1036                m->m_len);
1037
1038            /* Wrap around? */
1039            if (dp->tx_ptr < dp->txbufs-1) {
1040                ctrl = GRETH_TXD_ENABLE;
1041            }else{
1042                ctrl = GRETH_TXD_ENABLE | GRETH_TXD_WRAP;
1043            }
1044
1045            /* Enable Descriptor */ 
1046            if ((m->m_next) == NULL) {
1047                dp->txdesc[dp->tx_ptr].ctrl = ctrl | int_en | m->m_len;
1048                break;
1049            }else{
1050                dp->txdesc[dp->tx_ptr].ctrl = GRETH_TXD_MORE | ctrl | int_en | m->m_len;
1051            }
1052
1053            /* Next */
1054            dp->txmbuf[dp->tx_ptr] = m;
1055            dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs;
1056            dp->tx_cnt++;
1057            m = m->m_next;
1058        }
1059        dp->txmbuf[dp->tx_ptr] = m;
1060        dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs;
1061        dp->tx_cnt++;
1062     
1063        /* Tell Hardware about newly enabled descriptor */
1064        SPIN_LOCK_IRQ(&dp->devlock, flags);
1065        dp->regs->ctrl = dp->regs->ctrl | GRETH_CTRL_TXEN;
1066        SPIN_UNLOCK_IRQ(&dp->devlock, flags);
1067
1068        return 0;
1069}
1070
1071int greth_process_tx_gbit(struct greth_softc *sc)
1072{
1073    struct ifnet *ifp = &sc->arpcom.ac_if;
1074    struct mbuf *m;
1075    SPIN_IRQFLAGS(flags);
1076    int first=1;
1077
1078    /*
1079     * Send packets till queue is empty
1080     */
1081    for (;;){
1082        /* Reap Sent packets */
1083        while((sc->tx_cnt > 0) && !(GRETH_MEM_LOAD(&sc->txdesc[sc->tx_dptr].ctrl) & GRETH_TXD_ENABLE)) {
1084            m_free(sc->txmbuf[sc->tx_dptr]);
1085            sc->tx_dptr = (sc->tx_dptr + 1) % sc->txbufs;
1086            sc->tx_cnt--;
1087        }
1088       
1089        if ( sc->next_tx_mbuf ){
1090            /* Get packet we tried but faild to transmit last time */
1091            m = sc->next_tx_mbuf;
1092            sc->next_tx_mbuf = NULL; /* Mark packet taken */
1093        }else{
1094            /*
1095             * Get the next mbuf chain to transmit from Stack.
1096             */
1097            IF_DEQUEUE (&ifp->if_snd, m);
1098            if (!m){
1099                /* Hardware has sent all schedule packets, this
1100                 * makes the stack enter at greth_start next time
1101                 * a packet is to be sent.
1102                 */
1103                ifp->if_flags &= ~IFF_OACTIVE;
1104                break;
1105            }
1106        }
1107
1108        /* Are there free descriptors available? */
1109        /* Try to send packet, if it a negative number is returned. */
1110        if ( (sc->tx_cnt >= sc->txbufs) || sendpacket_gbit(ifp, m) ){
1111            /* Not enough resources */
1112             
1113            /* Since we have taken the mbuf out of the "send chain"
1114             * we must remember to use that next time we come back.
1115             * or else we have dropped a packet.
1116             */
1117            sc->next_tx_mbuf = m;
1118           
1119            /* Not enough resources, enable interrupt for transmissions
1120             * this way we will be informed when more TX-descriptors are
1121             * available.
1122             */
1123            if ( first ){
1124                first = 0;
1125                SPIN_LOCK_IRQ(&sc->devlock, flags);
1126                ifp->if_flags |= IFF_OACTIVE;
1127                sc->regs->ctrl |= GRETH_CTRL_TXIRQ;
1128                SPIN_UNLOCK_IRQ(&sc->devlock, flags);
1129               
1130                /* We must check again to be sure that we didn't
1131                 * miss an interrupt (if a packet was sent just before
1132                 * enabling interrupts)
1133                 */
1134                continue;
1135            }
1136
1137            return -1;
1138        }else{
1139            /* Sent Ok, proceed to process more packets if available */
1140        }
1141    }
1142    return 0;
1143}
1144
1145int greth_process_tx(struct greth_softc *sc)
1146{
1147    struct ifnet *ifp = &sc->arpcom.ac_if;
1148    struct mbuf *m;
1149    SPIN_IRQFLAGS(flags);
1150    int first=1;
1151
1152    /*
1153     * Send packets till queue is empty
1154     */
1155    for (;;){
1156        if ( sc->next_tx_mbuf ){
1157            /* Get packet we tried but failed to transmit last time */
1158            m = sc->next_tx_mbuf;
1159            sc->next_tx_mbuf = NULL; /* Mark packet taken */
1160        }else{
1161            /*
1162             * Get the next mbuf chain to transmit from Stack.
1163             */
1164            IF_DEQUEUE (&ifp->if_snd, m);
1165            if (!m){
1166                /* Hardware has sent all schedule packets, this
1167                 * makes the stack enter at greth_start next time
1168                 * a packet is to be sent.
1169                 */
1170                ifp->if_flags &= ~IFF_OACTIVE;
1171                break;
1172            }
1173        }
1174
1175        /* Try to send packet, failed if it a non-zero number is returned. */
1176        if ( sendpacket(ifp, m) ){
1177            /* Not enough resources */
1178             
1179            /* Since we have taken the mbuf out of the "send chain"
1180             * we must remember to use that next time we come back.
1181             * or else we have dropped a packet.
1182             */
1183            sc->next_tx_mbuf = m;
1184           
1185            /* Not enough resources, enable interrupt for transmissions
1186             * this way we will be informed when more TX-descriptors are
1187             * available.
1188             */
1189            if ( first ){
1190                first = 0;
1191                SPIN_LOCK_IRQ(&sc->devlock, flags);
1192                ifp->if_flags |= IFF_OACTIVE;
1193                sc->regs->ctrl |= GRETH_CTRL_TXIRQ;
1194                SPIN_UNLOCK_IRQ(&sc->devlock, flags);
1195
1196                /* We must check again to be sure that we didn't
1197                 * miss an interrupt (if a packet was sent just before
1198                 * enabling interrupts)
1199                 */
1200                continue;
1201            }
1202
1203            return -1;
1204        }else{
1205            /* Sent Ok, proceed to process more packets if available */
1206        }
1207    }
1208    return 0;
1209}
1210
1211static void
1212greth_start (struct ifnet *ifp)
1213{
1214    struct greth_softc *sc = ifp->if_softc;
1215   
1216    if ( ifp->if_flags & IFF_OACTIVE )
1217            return;
1218   
1219    if ( sc->gbit_mac ){
1220        /* No use trying to handle this if we are waiting on GRETH
1221         * to send the previously scheduled packets.
1222         */
1223       
1224        greth_process_tx_gbit(sc);
1225    }else{
1226        greth_process_tx(sc);
1227    }
1228   
1229}
1230
1231/*
1232 * Initialize and start the device
1233 */
1234static void
1235greth_init (void *arg)
1236{
1237    struct greth_softc *sc = arg;
1238    struct ifnet *ifp = &sc->arpcom.ac_if;
1239    char name[4] = {'E', 'T', 'H', '0'};
1240
1241    if (sc->daemonTid == 0)
1242      {
1243          /*
1244           * Start driver tasks
1245           */
1246          name[3] += sc->minor;
1247          sc->daemonTid = rtems_bsdnet_newproc (name, 4096,
1248                                                greth_Daemon, sc);
1249
1250          /*
1251           * Set up GRETH hardware
1252           */
1253          greth_initialize_hardware (sc);
1254      }
1255
1256    /*
1257     * Setup promiscous/multi-cast MAC address filters if user enabled it
1258     */
1259    greth_mac_filter_set(sc);
1260
1261    /*
1262     * Tell the world that we're running.
1263     */
1264    ifp->if_flags |= IFF_RUNNING;
1265}
1266
1267/*
1268 * Stop the device
1269 */
1270static void
1271greth_stop (struct greth_softc *sc)
1272{
1273    struct ifnet *ifp = &sc->arpcom.ac_if;
1274    SPIN_IRQFLAGS(flags);
1275    unsigned int speed;
1276
1277    SPIN_LOCK_IRQ(&sc->devlock, flags);
1278    ifp->if_flags &= ~IFF_RUNNING;
1279
1280    speed = sc->regs->ctrl & (GRETH_CTRL_GB | GRETH_CTRL_SP | GRETH_CTRL_FULLD);
1281
1282    /* RX/TX OFF */
1283    sc->regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
1284    /* Reset ON */
1285    if (sc->greth_rst)
1286        sc->regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
1287    /* Reset OFF and restore link settings previously detected if any */
1288    sc->regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis | speed;
1289    SPIN_UNLOCK_IRQ(&sc->devlock, flags);
1290
1291    sc->next_tx_mbuf = NULL;
1292}
1293
1294
1295/*
1296 * Show interface statistics
1297 */
1298static void
1299greth_stats (struct greth_softc *sc)
1300{
1301  printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);
1302  printf ("      Rx Packets:%-8lu", sc->rxPackets);
1303  printf ("          Length:%-8lu", sc->rxLengthError);
1304  printf ("       Non-octet:%-8lu\n", sc->rxNonOctet);
1305  printf ("            Bad CRC:%-8lu", sc->rxBadCRC);
1306  printf ("         Overrun:%-8lu", sc->rxOverrun);
1307  printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);
1308  printf ("      Maximal Frags:%-8d", sc->max_fragsize);
1309  printf ("      GBIT MAC:%-8d", sc->gbit_mac);
1310}
1311
1312/*
1313 * Driver ioctl handler
1314 */
1315static int
1316greth_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data)
1317{
1318    struct greth_softc *sc = ifp->if_softc;
1319    int error = 0;
1320    struct ifreq *ifr;
1321
1322    switch (command)
1323      {
1324      case SIOCGIFADDR:
1325      case SIOCSIFADDR:
1326          ether_ioctl (ifp, command, data);
1327          break;
1328
1329      case SIOCSIFFLAGS:
1330          switch (ifp->if_flags & (IFF_UP | IFF_RUNNING))
1331            {
1332            case IFF_RUNNING:
1333                greth_stop (sc);
1334                break;
1335
1336            case IFF_UP:
1337                greth_init (sc);
1338                break;
1339
1340            case IFF_UP | IFF_RUNNING:
1341                greth_stop (sc);
1342                greth_init (sc);
1343                break;
1344       default:
1345                break;
1346            }
1347          break;
1348
1349      case SIO_RTEMS_SHOW_STATS:
1350          greth_stats (sc);
1351          break;
1352
1353          /*
1354           * Multicast commands: Enabling/disabling filtering of MAC addresses
1355           */
1356      case SIOCADDMULTI:
1357      case SIOCDELMULTI:
1358      ifr = (struct ifreq *)data;
1359      if (command == SIOCADDMULTI) {
1360        error = ether_addmulti(ifr, &sc->arpcom);
1361      } else {
1362        error = ether_delmulti(ifr, &sc->arpcom);
1363      }
1364      if (error == ENETRESET) {
1365        error = greth_mac_filter_set(sc);
1366      }
1367      break;
1368
1369      default:
1370          error = EINVAL;
1371          break;
1372      }
1373
1374    return error;
1375}
1376
1377/*
1378 * Attach an GRETH driver to the system
1379 */
1380static int
1381greth_interface_driver_attach (
1382    struct rtems_bsdnet_ifconfig *config,
1383    int attach
1384    )
1385{
1386    struct greth_softc *sc;
1387    struct ifnet *ifp;
1388    int mtu;
1389    int unitNumber;
1390    char *unitName;
1391   
1392      /* parse driver name */
1393    if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0)
1394        return 0;
1395
1396    sc = config->drv_ctrl;
1397    ifp = &sc->arpcom.ac_if;
1398#ifdef GRETH_DEBUG
1399    printf("GRETH[%d]: %s, sc %p, dev %p on %s\n", unitNumber, config->ip_address, sc, sc->dev, sc->dev->parent->dev->name);
1400#endif
1401    if (config->hardware_address)
1402      {
1403          memcpy (sc->arpcom.ac_enaddr, config->hardware_address,
1404                  ETHER_ADDR_LEN);
1405      }
1406    else
1407      {
1408          memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN);
1409      }
1410
1411    if (config->mtu)
1412        mtu = config->mtu;
1413    else
1414        mtu = ETHERMTU;
1415
1416    sc->acceptBroadcast = !config->ignore_broadcast;
1417
1418    /*
1419     * Set up network interface values
1420     */
1421    ifp->if_softc = sc;
1422    ifp->if_unit = unitNumber;
1423    ifp->if_name = unitName;
1424    ifp->if_mtu = mtu;
1425    ifp->if_init = greth_init;
1426    ifp->if_ioctl = greth_ioctl;
1427    ifp->if_start = greth_start;
1428    ifp->if_output = ether_output;
1429    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
1430    if (sc->mc_available)
1431        ifp->if_flags |= IFF_MULTICAST;
1432    if (ifp->if_snd.ifq_maxlen == 0)
1433        ifp->if_snd.ifq_maxlen = ifqmaxlen;
1434
1435    /*
1436     * Attach the interface
1437     */
1438    if_attach (ifp);
1439    ether_ifattach (ifp);
1440
1441#ifdef GRETH_DEBUG
1442    printf ("GRETH : driver has been attached\n");
1443#endif
1444    return 1;
1445}
1446
1447/******************* Driver manager interface ***********************/
1448
1449/* Driver prototypes */
1450int greth_register_io(rtems_device_major_number *m);
1451int greth_device_init(struct greth_softc *sc);
1452int network_interface_add(struct rtems_bsdnet_ifconfig *interface);
1453
1454#ifdef GRETH_INFO_AVAIL
1455static int greth_info(
1456        struct drvmgr_dev *dev,
1457        void (*print_line)(void *p, char *str),
1458        void *p, int argc, char *argv[]);
1459#define GRETH_INFO_FUNC greth_info
1460#else
1461#define GRETH_INFO_FUNC NULL
1462#endif
1463
1464int greth_init2(struct drvmgr_dev *dev);
1465int greth_init3(struct drvmgr_dev *dev);
1466
1467struct drvmgr_drv_ops greth_ops =
1468{
1469        .init   =
1470                {
1471                        NULL,
1472                        greth_init2,
1473                        greth_init3,
1474                        NULL
1475                },
1476        .remove = NULL,
1477        .info = GRETH_INFO_FUNC,
1478};
1479
1480struct amba_dev_id greth_ids[] =
1481{
1482        {VENDOR_GAISLER, GAISLER_ETHMAC},
1483        {0, 0}          /* Mark end of table */
1484};
1485
1486struct amba_drv_info greth_drv_info =
1487{
1488        {
1489                DRVMGR_OBJ_DRV,                 /* Driver */
1490                NULL,                           /* Next driver */
1491                NULL,                           /* Device list */
1492                DRIVER_AMBAPP_GAISLER_GRETH_ID, /* Driver ID */
1493                "GRETH_DRV",                    /* Driver Name */
1494                DRVMGR_BUS_TYPE_AMBAPP,         /* Bus Type */
1495                &greth_ops,
1496                NULL,                           /* Funcs */
1497                0,                              /* No devices yet */
1498                0,
1499        },
1500        &greth_ids[0]
1501};
1502
1503void greth_register_drv (void)
1504{
1505        DBG("Registering GRETH driver\n");
1506        drvmgr_drv_register(&greth_drv_info.general);
1507}
1508
1509int greth_init2(struct drvmgr_dev *dev)
1510{
1511        struct greth_softc *priv;
1512
1513        DBG("GRETH[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
1514        priv = dev->priv = malloc(sizeof(struct greth_softc));
1515        if ( !priv )
1516                return DRVMGR_NOMEM;
1517        memset(priv, 0, sizeof(*priv));
1518        priv->dev = dev;
1519
1520        /* This core will not find other cores, so we wait for init3() */
1521
1522        return DRVMGR_OK;
1523}
1524
1525int greth_init3(struct drvmgr_dev *dev)
1526{
1527    struct greth_softc *sc;
1528    struct rtems_bsdnet_ifconfig *ifp;
1529    rtems_status_code status;
1530
1531    sc = dev->priv;
1532    sprintf(sc->devName, "gr_eth%d", (dev->minor_drv+1));
1533
1534    /* Init GRETH device */
1535    if ( greth_device_init(sc) ) {
1536        printk("GRETH: Failed to init device\n");
1537        return DRVMGR_FAIL;
1538    }
1539
1540    /* Initialize Spin-lock for GRSPW Device. This is to protect
1541     * CTRL and DMACTRL registers from ISR.
1542     */
1543    SPIN_INIT(&sc->devlock, sc->devName);
1544
1545    /* Register GRETH device as an Network interface */
1546    ifp = malloc(sizeof(struct rtems_bsdnet_ifconfig));
1547    memset(ifp, 0, sizeof(*ifp));
1548
1549    ifp->name = sc->devName;
1550    ifp->drv_ctrl = sc;
1551    ifp->attach = greth_interface_driver_attach;
1552
1553    status = network_interface_add(ifp);
1554    if (status != 0) {
1555        return DRVMGR_FAIL;
1556    }
1557
1558    return DRVMGR_OK;
1559}
1560
1561int greth_device_init(struct greth_softc *sc)
1562{
1563    struct amba_dev_info *ambadev;
1564    struct ambapp_core *pnpinfo;
1565    union drvmgr_key_value *value;
1566    unsigned int speed;
1567
1568    /* Get device information from AMBA PnP information */
1569    ambadev = (struct amba_dev_info *)sc->dev->businfo;
1570    if ( ambadev == NULL ) {
1571        return -1;
1572    }
1573    pnpinfo = &ambadev->info;
1574    sc->regs = (greth_regs *)pnpinfo->apb_slv->start;
1575    sc->minor = sc->dev->minor_drv;
1576    sc->greth_rst = 1;
1577
1578    /* Remember EDCL enabled/disable state before reset */
1579    sc->edcl_dis = sc->regs->ctrl & GRETH_CTRL_ED;
1580
1581    /* Default is to inherit EDCL Disable bit from HW. User can force En/Dis */
1582    value = drvmgr_dev_key_get(sc->dev, "edclDis", DRVMGR_KT_INT);
1583    if ( value ) {
1584        /* Force EDCL mode. Has an effect later when GRETH+PHY is initialized */
1585        if (value->i > 0) {
1586            sc->edcl_dis = GRETH_CTRL_ED;
1587        } else {
1588            /* Default to avoid soft-reset the GRETH when EDCL is forced */
1589            sc->edcl_dis = 0;
1590            sc->greth_rst = 0;
1591        }
1592    }
1593
1594    /* let user control soft-reset of GRETH (for debug) */
1595    value = drvmgr_dev_key_get(sc->dev, "soft-reset", DRVMGR_KT_INT);
1596    if ( value) {
1597        sc->greth_rst = value->i ? 1 : 0;
1598    }
1599
1600    /* clear control register and reset NIC and keep current speed modes.
1601     * This should be done as quick as possible during startup, this is to
1602     * stop DMA transfers after a reboot.
1603     *
1604     * When EDCL is forced enabled reset is skipped, disabling RX/TX DMA is
1605     * is enough during debug.
1606     */
1607    speed = sc->regs->ctrl & (GRETH_CTRL_GB | GRETH_CTRL_SP | GRETH_CTRL_FULLD);
1608    sc->regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
1609    if (sc->greth_rst)
1610        sc->regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED | speed;
1611    sc->regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis | speed;
1612
1613    /* Configure driver by overriding default config with the bus resources
1614     * configured by the user
1615     */
1616    sc->txbufs = 32;
1617    sc->rxbufs = 32;
1618    sc->phyaddr = -1;
1619
1620    value = drvmgr_dev_key_get(sc->dev, "txDescs", DRVMGR_KT_INT);
1621    if ( value && (value->i <= 128) )
1622        sc->txbufs = value->i;
1623
1624    value = drvmgr_dev_key_get(sc->dev, "rxDescs", DRVMGR_KT_INT);
1625    if ( value && (value->i <= 128) )
1626        sc->rxbufs = value->i;
1627
1628    value = drvmgr_dev_key_get(sc->dev, "phyAdr", DRVMGR_KT_INT);
1629    if ( value && (value->i < 32) )
1630        sc->phyaddr = value->i;
1631
1632    value = drvmgr_dev_key_get(sc->dev, "advModes", DRVMGR_KT_INT);
1633    if ( value )
1634        sc->advmodes = value->i;
1635
1636    /* Check if multicast support is available */
1637    sc->mc_available = sc->regs->ctrl & GRETH_CTRL_MC;
1638
1639    return 0;
1640}
1641
1642#ifdef GRETH_INFO_AVAIL
1643static int greth_info(
1644        struct drvmgr_dev *dev,
1645        void (*print_line)(void *p, char *str),
1646        void *p, int argc, char *argv[])
1647{
1648        struct greth_softc *sc;
1649        char buf[64];
1650
1651        if (dev->priv == NULL)
1652                return -DRVMGR_EINVAL;
1653        sc = dev->priv;
1654
1655        sprintf(buf, "IFACE NAME:  %s", sc->devName);
1656        print_line(p, buf);
1657        sprintf(buf, "GBIT MAC:    %s", sc->gbit_mac ? "YES" : "NO");
1658        print_line(p, buf);
1659
1660        return DRVMGR_OK;
1661}
1662#endif
1663
1664#endif
Note: See TracBrowser for help on using the repository browser.