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

Last change on this file since 2fbe2ef3 was 2fbe2ef3, checked in by Daniel Hellstrom <daniel@…>, on Feb 13, 2018 at 6:47:14 AM

leon, greth: 10/100 MAC enable TX BD interrupt

Missed to enable interrupt per TX descriptor. Could lead to TX buffer
starvation.

Does not affect the GBit code.

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