source: rtems/c/src/lib/libbsp/sparc/shared/net/greth.c @ 8ac070a

5
Last change on this file since 8ac070a was 8ac070a, checked in by Daniel Hellstrom <daniel@…>, on 04/24/17 at 14:36:16

leon, greth: 10/100 modes should be assigned in fastest priority

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