source: rtems/c/src/lib/libbsp/sparc/shared/net/greth.c @ 430949aa

5
Last change on this file since 430949aa was 430949aa, checked in by Daniel Hellstrom <daniel@…>, on 04/13/17 at 19:23:28

leon, greth: let Gbit full duplex override half

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