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

5
Last change on this file since c05d7a9d was c05d7a9d, checked in by Sebastian Huber <sebastian.huber@…>, on 12/21/18 at 20:43:27

bsps/sparc: Fix warnings

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