source: rtems/bsps/shared/grlib/net/greth.c @ 053b17ce

Last change on this file since 053b17ce was 053b17ce, checked in by Daniel Hellstrom <daniel@…>, on 04/26/19 at 13:18:11

leon,greth: added support for variable sized descriptor table sizes

The descriptor table size is equal to its alignment and set when
configuring the HW IP through VHDL generics. This SW patch simply
probes the HW how large the RX/TX descriptor tables are and adjusts
accordingly.

The number of descriptors actual used are controlled by other
settings (rxDescs and txDescs) controlled by the user.

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