source: rtems/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wm.c @ ee732739

4.104.114.84.95
Last change on this file since ee732739 was ee732739, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 13, 2007 at 2:26:24 PM

2007-09-07 Kate Feng <feng1@…>

  • ChangeLog?, Makefile.am, README, README.booting, README.irq, preinstall.am, GT64260/MVME5500I2C.c, include/bsp.h, irq/irq.c, irq/irq.h, irq/irq_init.c, pci/detect_host_bridge.c, pci/pci.c, pci/pci_interface.c, pci/pcifinddevice.c, start/preload.S, startup/bspclean.c, startup/bspstart.c, startup/pgtbl_activate.c, startup/reboot.c, vectors/bspException.h, vectors/exceptionhandler.c: Merge my improvements in this BSP including a new network driver for the 1GHz NIC.
  • network/if_100MHz/GT64260eth.c, network/if_100MHz/GT64260eth.h, network/if_100MHz/GT64260ethreg.h, network/if_100MHz/Makefile.am, network/if_1GHz/Makefile.am, network/if_1GHz/POSSIBLEBUG, network/if_1GHz/if_wm.c, network/if_1GHz/if_wmreg.h, network/if_1GHz/pci_map.c, network/if_1GHz/pcireg.h: New files.
  • Property mode set to 100644
File size: 43.0 KB
Line 
1/*
2 * Copyright (c) 2004,2005 RTEMS/Mvme5500 port by S. Kate Feng <feng1@bnl.gov>
3 *      Brookhaven National Laboratory, All rights reserved
4 *
5 * Acknowledgements:
6 * netBSD : Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
7 *          Jason R. Thorpe for Wasabi Systems, Inc.
8 * Intel : NDA document
9 *
10 * Some notes from the author, S. Kate Feng :
11 *
12 * 1) The error reporting routine i82544EI_error() employs two pointers
13 *    for the error report buffer. One for the ISR and another one for
14 *    the error report.
15 * 2) Enable the hardware Auto-Negotiation state machine.
16 * 3) Set Big Endian mode in the WMREG_CTRL so that we do not need htole32
17 *    because PPC is big endian mode.
18 *    However, the data packet structure defined in if_wmreg.h
19 *    should be redefined for the big endian mode.
20 * 4) To ensure the cache coherence, the MOTLoad had the PCI
21 *    snoop control registers (0x1f00) set to "snoop to WB region" for
22 *    the entire 512MB of memory.
23 * 5) MOTLoad default :
24 *    little endian mode, cache line size is 32 bytes, no checksum control,
25 *    hardware auto-neg. state machine disabled. PCI control "snoop
26 *    to WB region", MII mode (PHY) instead of TBI mode.
27 * 6) We currently only use 32-bit (instead of 64-bit) DMA addressing.
28 * 7) Support for checksum offloading and TCP segmentation offload will
29 *    be available for releasing in 2008, upon request, if I still believe.
30 *   
31 */
32
33#define BYTE_ORDER BIG_ENDIAN
34
35#define INET
36
37#include <rtems.h>
38#include <rtems/bspIo.h>      /* printk */
39#include <stdio.h>            /* printf for statistics */
40#include <string.h>
41
42#include <libcpu/io.h>        /* inp & friends */
43#include <libcpu/spr.h>       /* registers.h is included here */
44#include <bsp.h>
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/mbuf.h>
49
50#include <rtems/rtems_bsdnet.h>
51#include <rtems/rtems_bsdnet_internal.h>
52#include <rtems/error.h>          
53#include <errno.h>
54
55#include <rtems/rtems/types.h>
56#include <rtems/score/cpu.h>
57
58#include <sys/queue.h>
59
60#include <sys/ioctl.h>
61#include <sys/socket.h>
62#include <sys/sockio.h>             /* SIOCADDMULTI, SIOC...     */
63#include <net/if.h>
64#include <net/if_dl.h>
65#include <netinet/in.h>
66#include <netinet/if_ether.h>
67
68#ifdef INET
69#include <netinet/in_var.h>
70#endif
71
72#include <bsp/irq.h>
73#include <bsp/pci.h>
74#include <bsp/pcireg.h>
75#include <bsp/if_wmreg.h>
76#define WMREG_RADV      0x282c  /* Receive Interrupt Absolute Delay Timer */
77
78/*#define CKSUM_OFFLOAD*/
79
80#define ETHERTYPE_FLOWCONTROL   0x8808  /* 802.3x flow control packet */
81
82#define i82544EI_TASK_NAME "IGHZ"
83#define SOFTC_ALIGN        4095
84
85#define INTR_ERR_SIZE        16
86
87/*#define WM_DEBUG*/
88#ifdef WM_DEBUG
89#define WM_DEBUG_LINK           0x01
90#define WM_DEBUG_TX             0x02
91#define WM_DEBUG_RX             0x04
92#define WM_DEBUG_GMII           0x08
93int     wm_debug = WM_DEBUG_TX|WM_DEBUG_RX|WM_DEBUG_LINK;
94
95#define DPRINTF(x, y)   if (wm_debug & (x)) printk y
96#else
97#define DPRINTF(x, y)   /* nothing */
98#endif /* WM_DEBUG */
99
100/* RTEMS event to kill the daemon */
101#define KILL_EVENT              RTEMS_EVENT_1
102/* RTEMS event to (re)start the transmitter */
103#define START_TRANSMIT_EVENT    RTEMS_EVENT_2
104/* RTEMS events used by the ISR */
105#define RX_EVENT                RTEMS_EVENT_3
106#define TX_EVENT                RTEMS_EVENT_4
107#define ERR_EVENT               RTEMS_EVENT_5
108#define INIT_EVENT              RTEMS_EVENT_6
109 
110#define ALL_EVENTS (KILL_EVENT|START_TRANSMIT_EVENT|RX_EVENT|TX_EVENT|ERR_EVENT|INIT_EVENT)
111
112
113#define NTXDESC                 128
114#define NTXDESC_MASK            (NTXDESC - 1)
115#define WM_NEXTTX(x)            (((x) + 1) & NTXDESC_MASK)
116
117#define NRXDESC                 64
118#define NRXDESC_MASK            (NRXDESC - 1)
119#define WM_NEXTRX(x)            (((x) + 1) & NRXDESC_MASK)
120#define WM_PREVRX(x)            (((x) - 1) & NRXDESC_MASK)
121
122#define WM_CDOFF(x)     offsetof(struct wm_control_data, x)
123#define WM_CDTXOFF(x)   WM_CDOFF(sc_txdescs[(x)])
124#define WM_CDRXOFF(x)   WM_CDOFF(sc_rxdescs[(x)])
125
126#define TXQ_HiLmt_OFF 64
127
128static uint32_t TxDescCmd;
129
130/*
131 * Software state per device.
132 */
133struct wm_softc {
134        wiseman_txdesc_t sc_txdescs[NTXDESC]; /* transmit descriptor memory */
135        wiseman_rxdesc_t sc_rxdescs[NRXDESC]; /* receive descriptor memory */
136        struct mbuf *txs_mbuf[NTXDESC];        /* transmit buffer memory */
137        struct mbuf *rxs_mbuf[NRXDESC];        /* receive buffer memory */
138        struct wm_softc *next_module;
139        volatile unsigned int intr_errsts[INTR_ERR_SIZE]; /* intr_status */
140        unsigned int intr_err_ptr1;     /* ptr used in i82544EI_error() */
141        unsigned int intr_err_ptr2;     /* ptr used in ISR */
142        int txs_firstdesc;              /* first descriptor in packet */
143        int txs_lastdesc;               /* last descriptor in packet */
144        int txs_ndesc;                  /* # of descriptors used */
145        unsigned sc_membase;            /* Memory space base address */
146        unsigned sc_memsize;            /* Memory space size */
147
148        char    dv_xname[16];           /* external name (name + unit) */
149        void *sc_sdhook;                /* shutdown hook */
150        struct arpcom arpcom;           /* rtems if structure, contains ifnet */
151        int sc_flags;                   /* flags; see below */
152        int sc_bus_speed;               /* PCI/PCIX bus speed */
153        int sc_flowflags;               /* 802.3x flow control flags */
154
155        void *sc_ih;                    /* interrupt cookie */
156
157        int sc_ee_addrbits;             /* EEPROM address bits */
158        rtems_id        daemonTid;
159        rtems_id        daemonSync;     /* synchronization with the daemon */
160
161        int      txq_next;              /* next Tx descriptor ready for transmitting */
162        uint32_t txq_nactive;           /* number of active TX descriptors */
163        uint32_t txq_fi;                /* next free Tx descriptor */
164        uint32_t txq_free;              /* number of free Tx jobs */
165        uint32_t sc_txctx_ipcs;         /* cached Tx IP cksum ctx */
166        uint32_t sc_txctx_tucs;         /* cached Tx TCP/UDP cksum ctx */
167
168        int     sc_rxptr;               /* next ready Rx descriptor/queue ent */
169        int     sc_rxdiscard;
170        int     sc_rxlen;
171        uint32_t sc_ctrl;               /* prototype CTRL register */
172#if 0
173        uint32_t sc_ctrl_ext;           /* prototype CTRL_EXT register */
174#endif
175        uint32_t sc_icr;                /* prototype interrupt bits */
176        uint32_t sc_tctl;               /* prototype TCTL register */
177        uint32_t sc_rctl;               /* prototype RCTL register */
178        uint32_t sc_tipg;               /* prototype TIPG register */
179        uint32_t sc_fcrtl;              /* prototype FCRTL register */
180
181        int sc_mchash_type;             /* multicast filter offset */
182
183        /* statistics */
184        struct {
185          volatile unsigned long     rxInterrupts;
186          volatile unsigned long     txInterrupts;
187          unsigned long     txMultiBuffPacket;
188          unsigned long     txMultiMaxLen;
189          unsigned long     txSinglMaxLen;
190          unsigned long     txMultiMaxLoop;
191          unsigned long     txBuffMaxLen;
192          unsigned long     linkInterrupts;
193          unsigned long     length_errors;
194          unsigned long     frame_errors;
195          unsigned long     crc_errors;
196          unsigned long     rxOvrRunInterrupts; /* Rx overrun interrupt */
197          unsigned long     rxSeqErr;
198          unsigned long     rxC_ordered;
199          unsigned long     ghostInterrupts;
200          unsigned long     linkStatusChng;
201        } stats;
202};
203
204/* <skf> our memory address seen from the PCI bus should be 1:1 */
205#define htole32(x)  le32toh(x)
206#define le32toh(x)  CPU_swap_u32((unsigned int) x)
207#define le16toh(x)  CPU_swap_u16(x)
208
209/* sc_flags */
210#define WM_F_HAS_MII            0x01    /* has MII */
211/* 82544 EI does not perform EEPROM handshake, EEPROM interface is not SPI */
212#define WM_F_EEPROM_HANDSHAKE   0x02    /* requires EEPROM handshake */
213#define WM_F_EEPROM_SPI         0x04    /* EEPROM is SPI */
214#define WM_F_IOH_VALID          0x10    /* I/O handle is valid */
215#define WM_F_BUS64              0x20    /* bus is 64-bit */
216#define WM_F_PCIX               0x40    /* bus is PCI-X */
217
218#define CSR_READ(sc,reg) in_le32((volatile unsigned *)(sc->sc_membase+reg))
219#define CSR_WRITE(sc,reg,val) out_le32((volatile unsigned *)(sc->sc_membase+reg), val)
220
221#define WM_CDTXADDR(sc) ( (uint32_t) &sc->sc_txdescs[0] )
222#define WM_CDRXADDR(sc) ( (uint32_t) &sc->sc_rxdescs[0] )
223
224static struct wm_softc *root_i82544EI_dev = NULL;
225
226static void i82544EI_ifstart(struct ifnet *ifp);
227static int  wm_ioctl(struct ifnet *ifp, u_long cmd,uint32_t data);
228static void i82544EI_ifinit(void *arg);
229static void wm_stop(struct ifnet *ifp, int disable);
230
231static void wm_rxdrain(struct wm_softc *sc);
232static int  wm_add_rxbuf(struct wm_softc *sc, int idx);
233static int  wm_read_eeprom(struct wm_softc *sc,int word,int wordcnt, uint16_t *data);
234static void i82544EI_daemon(void *arg);
235static void wm_set_filter(struct wm_softc *sc);
236
237static void i82544EI_isr();
238static void i82544EI_sendpacket(struct wm_softc *sc, struct mbuf *m);
239extern int  pci_mem_find(), pci_io_find(), pci_get_capability();
240extern char * ether_sprintf1();
241
242static void i82544EI_irq_on(const rtems_irq_connect_data *irq)
243{
244  struct wm_softc *sc;
245  unsigned int irqMask=  ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 | ICR_RXO | ICR_RXT0 | ICR_RXCFG;
246 
247  for (sc= root_i82544EI_dev; sc; sc= sc-> next_module) {
248    CSR_WRITE(sc,WMREG_IMS,(CSR_READ(sc,WMREG_IMS)| irqMask) );
249    return;
250  }
251}
252
253static void i82544EI_irq_off(const rtems_irq_connect_data *irq)
254{
255  struct wm_softc *sc;
256  unsigned int irqMask=  ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXDMT0 | ICR_RXO | ICR_RXT0 |ICR_RXCFG ;
257
258  for (sc= root_i82544EI_dev; sc; sc= sc-> next_module) {
259    CSR_WRITE(sc,WMREG_IMS, (CSR_READ(sc,WMREG_IMS) & ~irqMask) );
260    return;
261  }
262}
263static int ifwm_macaddr(char *hwaddr)
264{
265  hwaddr[0] = 0x00;
266  hwaddr[1] = 0x01;
267  hwaddr[2] = 0xaf;
268  hwaddr[3] = 0x0b;
269  hwaddr[4] = 0xb4;
270  hwaddr[5] = 0x75;
271
272  return 0;
273}
274
275static int i82544EI_irq_is_on(const rtems_irq_connect_data *irq)
276{
277  return(CSR_READ(root_i82544EI_dev,WMREG_ICR) & root_i82544EI_dev->sc_icr);
278}
279
280static rtems_irq_connect_data i82544IrqData={
281        BSP_GPP_82544_IRQ,
282        (rtems_irq_hdl) i82544EI_isr,
283        (rtems_irq_enable) i82544EI_irq_on,
284        (rtems_irq_disable) i82544EI_irq_off,
285        (rtems_irq_is_enabled) i82544EI_irq_is_on, 
286};
287
288int rtems_i82544EI_driver_attach(struct rtems_bsdnet_ifconfig *config, int attach)
289{
290  struct wm_softc *sc;
291  struct ifnet *ifp;
292  uint8_t enaddr[ETHER_ADDR_LEN];
293  uint16_t myea[ETHER_ADDR_LEN / 2], cfg1, cfg2, swdpin;
294  unsigned reg, preg;
295  int b,d,f; /* PCI bus/device/function */
296  int unit, pmreg;
297  void     *softc_mem;
298  char     *name;
299
300  unit = rtems_bsdnet_parse_driver_name(config, &name);
301  if (unit < 0) return 0;
302 
303  printk("\nEthernet driver name %s unit %d \n",name, unit);
304  printk("Copyright (c) 2004,2005 S. Kate Feng <feng1@bnl.gov> (RTEMS/mvme5500 port)\n");
305
306  /* Make sure certain elements e.g. descriptor lists are aligned.*/ 
307  softc_mem = rtems_bsdnet_malloc(sizeof(*sc) + SOFTC_ALIGN, M_FREE, M_NOWAIT);
308
309  /* Check for the very unlikely case of no memory. */
310  if (softc_mem == NULL)
311     rtems_panic("i82544EI: OUT OF MEMORY");
312
313  sc = (void *)(((long)softc_mem + SOFTC_ALIGN) & ~SOFTC_ALIGN);
314  memset(sc, 0, sizeof(*sc));
315
316  sprintf(sc->dv_xname, "%s%d", name, unit);
317
318  if (pci_find_device(PCI_VENDOR_ID_INTEL,PCI_DEVICE_INTEL_82544EI_COPPER,
319                        unit-1,&b, &d, &f))
320    rtems_panic("i82544EI device ID not found\n");
321
322#if WM_DEBUG
323  printk("82544EI:b%d, d%d, f%d\n", b, d,f);
324#endif
325
326  /* Memory-mapped acccess is required for normal operation.*/
327  if ( pci_mem_find(b,d,f,PCI_MAPREG_START, &sc->sc_membase, &sc->sc_memsize))
328     rtems_panic("i82544EI: unable to map memory space\n");
329
330#ifdef WM_DEBUG
331  printk("Memory base addr 0x%x\n", sc->sc_membase);
332  printk("txdesc[0] addr:0x%x, rxdesc[0] addr:0x%x, sizeof sc %d\n",&sc->sc_txdescs[0], &sc->sc_rxdescs[0], sizeof(*sc));     
333#endif
334
335
336  sc->sc_ctrl |=CSR_READ(sc,WMREG_CTRL); 
337  /*
338   * Determine a few things about the bus we're connected to.
339   */
340  reg = CSR_READ(sc,WMREG_STATUS); 
341  if (reg & STATUS_BUS64) sc->sc_flags |= WM_F_BUS64;
342  sc->sc_bus_speed = (reg & STATUS_PCI66) ? 66 : 33;
343#ifdef WM_DEBUG
344  printk("%s%d: %d-bit %dMHz PCI bus\n",name, unit,
345         (sc->sc_flags & WM_F_BUS64) ? 64 : 32, sc->sc_bus_speed);
346#endif
347
348  /*
349   * Setup some information about the EEPROM.
350   */
351
352  sc->sc_ee_addrbits = 6;
353
354#ifdef WM_DEBUG
355  printk("%s%d: %u word (%d address bits) MicroWire EEPROM\n",
356            name, unit, 1U << sc->sc_ee_addrbits,
357            sc->sc_ee_addrbits);
358#endif
359
360  /*
361   * Read the Ethernet address from the EEPROM.
362   */
363  if (wm_read_eeprom(sc, EEPROM_OFF_MACADDR,
364            sizeof(myea) / sizeof(myea[0]), myea)) 
365     rtems_panic("i82544ei 1GHZ ethernet: unable to read Ethernet address");
366
367  enaddr[0] = myea[0] & 0xff;
368  enaddr[1] = myea[0] >> 8;
369  enaddr[2] = myea[1] & 0xff;
370  enaddr[3] = myea[1] >> 8;
371  enaddr[4] = myea[2] & 0xff;
372  enaddr[5] = myea[2] >> 8;
373
374
375  memcpy(sc->arpcom.ac_enaddr, enaddr, ETHER_ADDR_LEN);
376#ifdef WM_DEBUG
377  printk("%s: Ethernet address %s\n", sc->dv_xname,
378            ether_sprintf1(enaddr));
379#endif
380
381  /*
382   * Read the config info from the EEPROM, and set up various
383   * bits in the control registers based on their contents.
384   */
385  if (wm_read_eeprom(sc, EEPROM_OFF_CFG1, 1, &cfg1)) {
386     printk("%s: unable to read CFG1 from EEPROM\n",sc->dv_xname);
387     return(0);
388  }
389  if (wm_read_eeprom(sc, EEPROM_OFF_CFG2, 1, &cfg2)) {
390     printk("%s: unable to read CFG2 from EEPROM\n",sc->dv_xname);
391     return(0);
392  }
393  if (wm_read_eeprom(sc, EEPROM_OFF_SWDPIN, 1, &swdpin)) {
394     printk("%s: unable to read SWDPIN from EEPROM\n",sc->dv_xname);
395     return(0);
396  }
397
398  if (cfg1 & EEPROM_CFG1_ILOS) sc->sc_ctrl |= CTRL_ILOS;
399  sc->sc_ctrl|=((swdpin >> EEPROM_SWDPIN_SWDPIO_SHIFT) & 0xf) <<
400                CTRL_SWDPIO_SHIFT;
401  sc->sc_ctrl |= ((swdpin >> EEPROM_SWDPIN_SWDPIN_SHIFT) & 0xf) <<
402                CTRL_SWDPINS_SHIFT;
403
404  CSR_WRITE(sc,WMREG_CTRL, sc->sc_ctrl);
405#if 0
406  CSR_WRITE(sc,WMREG_CTRL_EXT, sc->sc_ctrl_ext);
407#endif
408
409  ifp = &sc->arpcom.ac_if;
410  /* set this interface's name and unit */
411  ifp->if_unit = unit;
412  ifp->if_name = name;
413  ifp->if_softc = sc;
414  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
415  ifp->if_mtu = config->mtu ? config->mtu : ETHERMTU;
416  ifp->if_ioctl = wm_ioctl;
417  ifp->if_start = i82544EI_ifstart;
418  /*  ifp->if_watchdog = wm_watchdog;*/
419  ifp->if_init = i82544EI_ifinit;
420  if (ifp->if_snd.ifq_maxlen == 0)
421      ifp->if_snd.ifq_maxlen = ifqmaxlen;
422
423  ifp->if_output = ether_output;
424
425  /* create the synchronization semaphore */
426  if (RTEMS_SUCCESSFUL != rtems_semaphore_create(
427     rtems_build_name('I','G','H','Z'),0,0,0,&sc->daemonSync))
428     rtems_panic("i82544EI: semaphore creation failed");
429
430  sc->next_module = root_i82544EI_dev;
431  root_i82544EI_dev = sc;
432
433  /* Attach the interface. */
434  if_attach(ifp);
435  ether_ifattach(ifp);
436#ifdef WM_DEBUG
437  printk("82544EI: Ethernet driver has been attached (handle 0x%08x,ifp 0x%08x)\n",sc, ifp);
438#endif
439
440  return(1);
441}
442
443/*
444 * i82544EI_ifstart:            [ifnet interface function]
445 *
446 *      Start packet transmission on the interface.
447 */
448static void
449i82544EI_ifstart(struct ifnet *ifp)
450{
451  struct wm_softc *sc = ifp->if_softc;
452
453#ifdef WM_DEBUG
454  printk("i82544EI_ifstart(");
455#endif
456
457  if ((ifp->if_flags & IFF_RUNNING) == 0) {
458#ifdef WM_DEBUG
459     printk("IFF_RUNNING==0\n");
460#endif         
461     return;
462  }
463
464  ifp->if_flags |= IFF_OACTIVE;
465  rtems_event_send (sc->daemonTid, START_TRANSMIT_EVENT);
466#ifdef WM_DEBUG
467  printk(")\n");
468#endif
469}
470
471static void i82544EI_stats(struct wm_softc *sc)
472{
473  struct ifnet *ifp = &sc->arpcom.ac_if;
474
475  printf("       Rx Interrupts:%-8u\n", sc->stats.rxInterrupts);
476  printf("     Receive Packets:%-8u\n", CSR_READ(sc,WMREG_GPRC));
477  printf("     Receive Overrun:%-8u\n", sc->stats.rxOvrRunInterrupts);
478  printf("     Receive  errors:%-8u\n", CSR_READ(sc,WMREG_RXERRC));
479  printf("   Rx sequence error:%-8u\n", sc->stats.rxSeqErr);
480  printf("      Rx /C/ ordered:%-8u\n", sc->stats.rxC_ordered);
481  printf("    Rx Length Errors:%-8u\n", CSR_READ(sc,WMREG_RLEC));
482  printf("       Tx Interrupts:%-8u\n", sc->stats.txInterrupts);
483#if 0
484  printf("Multi-BuffTx Packets:%-8u\n", sc->stats.txMultiBuffPacket);
485  printf("Multi-BuffTx max len:%-8u\n", sc->stats.txMultiMaxLen);
486  printf("SingleBuffTx max len:%-8u\n", sc->stats.txSinglMaxLen);
487  printf("Multi-BuffTx maxloop:%-8u\n", sc->stats.txMultiMaxLoop);
488  printf("Tx buffer max len   :%-8u\n", sc->stats.txBuffMaxLen);
489#endif
490  printf("   Transmitt Packets:%-8u\n", CSR_READ(sc,WMREG_GPTC));
491  printf("   Transmitt  errors:%-8u\n", ifp->if_oerrors);
492  printf("         Active Txqs:%-8u\n", sc->txq_nactive); 
493  printf("          collisions:%-8u\n", CSR_READ(sc,WMREG_COLC));
494  printf("          Crc Errors:%-8u\n", CSR_READ(sc,WMREG_CRCERRS));
495  printf("  Link Status Change:%-8u\n", sc->stats.linkStatusChng);
496}
497
498/*
499 * wm_ioctl:            [ifnet interface function]
500 *
501 *      Handle control requests from the operator.
502 */
503static int wm_ioctl(struct ifnet *ifp, u_long cmd,uint32_t data)
504{
505  struct wm_softc *sc = ifp->if_softc;
506  int error;
507
508  switch (cmd) {
509    default:
510      error = ether_ioctl(ifp, cmd, data);
511      if (error == ENETRESET) {
512          /*
513           * Multicast list has changed; set the hardware filter
514           * accordingly.
515           */
516          wm_set_filter(sc);
517          error = 0;
518      }
519      break;
520    case SIO_RTEMS_SHOW_STATS:
521      i82544EI_stats(sc);
522      break;
523  }
524
525  /* Try to get more packets going.*/
526  i82544EI_ifstart(ifp);
527  return (error);
528}
529
530/*
531 * wm_isr:
532 *
533 *      Interrupt service routine.
534 */
535static void i82544EI_isr()
536{
537  volatile struct wm_softc *sc = root_i82544EI_dev;
538  uint32_t icr;
539  rtems_event_set  events=0;
540
541  /* Reading the WMREG_ICR clears the interrupt bits */
542  icr = CSR_READ(sc,WMREG_ICR);
543
544  if ( icr & (ICR_RXDMT0|ICR_RXT0)) {
545     sc->stats.rxInterrupts++;
546     events |= RX_EVENT;
547  }
548
549  if (icr & ICR_TXDW) {
550     sc->stats.txInterrupts++;
551     events |= TX_EVENT;
552  }
553  /* <SKF> Rx overrun : no available receive buffer
554   * or PCI receive bandwidth inadequate.
555   */
556  if (icr & ICR_RXO) {
557     sc->stats.rxOvrRunInterrupts++;
558     events |= INIT_EVENT;
559  }
560  if (icr & ICR_RXSEQ) /* framing error */ {
561     sc->intr_errsts[sc->intr_err_ptr2++]=icr;
562     sc->intr_err_ptr2 %=INTR_ERR_SIZE; /* Till Straumann */
563     events |= ERR_EVENT;
564     sc->stats.rxSeqErr++;
565  }
566  if ( !icr) sc->stats.ghostInterrupts++;
567
568  if (icr & ICR_LSC) sc->stats.linkStatusChng++;
569  if (icr & ICR_RXCFG) sc->stats.rxC_ordered++;
570
571  rtems_event_send(sc->daemonTid, events);
572}
573
574/*
575 * i82544EI_sendpacket:
576 *
577 *      Helper; handle transmit interrupts.
578 */
579static void i82544EI_sendpacket(struct wm_softc *sc, struct mbuf *m)
580{
581
582#ifdef WM_DEBUG_TX
583  printk("sendpacket(");
584#endif
585
586  if ( !(m->m_next)) { /* single buffer packet */
587    sc->txs_mbuf[sc->txq_next]= m;
588    /* Note: we currently only use 32-bit DMA addresses. */
589    sc->sc_txdescs[sc->txq_next].wtx_addr.wa_low = htole32(mtod(m, void*));
590    sc->sc_txdescs[sc->txq_next].wtx_cmdlen =htole32(TxDescCmd | m->m_len);
591    sc->txs_lastdesc= sc->txq_next;
592    sc->txq_next = WM_NEXTTX(sc->txq_next);
593    sc->txq_nactive++;
594    sc->txq_free--;
595  }
596  else /* multiple mbufs in this packet */
597  { 
598    struct mbuf *mtp, *mdest;
599    volatile unsigned char *pt;
600    int len, y, loop=0;
601
602#ifdef WM_DEBUG_TX
603    printk("multi mbufs ");
604#endif
605    mtp = m;
606    while ( mtp) { 
607      MGETHDR(mdest, M_WAIT, MT_DATA);
608      MCLGET(mdest, M_WAIT);
609      pt = (volatile unsigned char *)mdest->m_data;
610      for ( len=0;mtp;mtp=mtp->m_next) {
611        loop++;
612        /* Each descriptor gets a 2k (MCLBYTES) buffer, although
613         * the length of each descriptor can be up to 16288 bytes.
614         * For packets which fill more than one buffer ( >2k), we
615         * chain them together.
616         * <Kate Feng> : This effective for packets > 2K
617         * The other way is effective for packets < 2K
618         */
619        if ( ((y=(len+mtp->m_len)) > sizeof(union mcluster))) {
620          printk(">2048, use next descriptor\n");
621          break; 
622        }
623        memcpy((void *)pt,(char *)mtp->m_data, mtp->m_len);
624        pt += mtp->m_len;
625        len += mtp->m_len;
626#if 0
627        sc->stats.txSinglMaxLen= MAX(mtp->m_len, sc->stats.txSinglMaxLen);
628#endif
629      } /* end for loop */
630      mdest->m_len=len;
631      sc->txs_mbuf[sc->txq_next] = mdest;
632      /* Note: we currently only use 32-bit DMA addresses. */
633      sc->sc_txdescs[sc->txq_next].wtx_addr.wa_low = htole32(mtod(mdest, void*));
634      sc->sc_txdescs[sc->txq_next].wtx_cmdlen = htole32(TxDescCmd|mdest->m_len);
635      sc->txs_lastdesc = sc->txq_next;
636      sc->txq_next = WM_NEXTTX(sc->txq_next);
637      sc->txq_nactive ++;
638      if (sc->txq_free) 
639         sc->txq_free--;
640      else
641         rtems_panic("i8254EI : no more free descriptors");
642#if 0
643      sc->stats.txMultiMaxLen= MAX(mdest->m_len, sc->stats.txMultiMaxLen);
644      sc->stats.txMultiBuffPacket++;
645#endif
646    } /* end for while */
647    /* free old mbuf chain */
648#if 0
649    sc->stats.txMultiMaxLoop=MAX(loop, sc->stats.txMultiMaxLoop);
650#endif
651    m_freem(m); 
652    m=0;
653  }  /* end  multiple mbufs */
654   
655  DPRINTF(WM_DEBUG_TX,("%s: TX: desc %d: cmdlen 0x%08x\n", sc->dv_xname,
656         sc->txs_lastdesc, le32toh(sc->sc_txdescs[sc->txs_lastdesc].wtx_cmdlen)));
657  DPRINTF(WM_DEBUG_TX,("status 0x%08x\n",sc->sc_txdescs[sc->txq_fi].wtx_fields.wtxu_status));
658
659  memBar();
660
661  /* This is the location where software writes the first NEW descriptor */
662  CSR_WRITE(sc,WMREG_TDT, sc->txq_next);
663
664  DPRINTF(WM_DEBUG_TX,("%s: addr 0x%08x, TX: TDH %d, TDT %d\n",sc->dv_xname,
665  le32toh(sc->sc_txdescs[sc->txs_lastdesc].wtx_addr.wa_low), CSR_READ(sc,WMREG_TDH),
666          CSR_READ(sc,WMREG_TDT)));
667
668  DPRINTF(WM_DEBUG_TX,("%s: TX: finished transmitting packet, job %d\n",
669                    sc->dv_xname, sc->txq_next));
670
671}
672
673static void i82544EI_txq_free(struct wm_softc *sc, uint8_t status)
674{
675  struct ifnet *ifp = &sc->arpcom.ac_if;
676
677  /* We might use the statistics registers instead of variables
678   * to keep tack of the network statistics
679   */ 
680
681  /* statistics */
682  ifp->if_opackets++;
683
684  if (status & (WTX_ST_EC|WTX_ST_LC)) {
685       ifp->if_oerrors++;
686
687     if (status & WTX_ST_LC) 
688        printf("%s: late collision\n", sc->dv_xname);
689     else if (status & WTX_ST_EC) {
690        ifp->if_collisions += 16;
691         printf("%s: excessive collisions\n", sc->dv_xname);
692     }
693  }
694  /* Free the original mbuf chain */
695  m_freem(sc->txs_mbuf[sc->txq_fi]);
696  sc->txs_mbuf[sc->txq_fi] = 0;
697  sc->sc_txdescs[sc->txq_fi].wtx_fields.wtxu_status=0;
698
699  sc->txq_free ++;
700  sc->txq_fi = WM_NEXTTX(sc->txq_fi);
701  --sc->txq_nactive;
702}
703
704static void i82544EI_txq_done(struct wm_softc *sc)
705{
706  uint8_t status;
707
708  /*
709   * Go through the Tx list and free mbufs for those
710   * frames which have been transmitted.
711   */
712  while ( sc->txq_nactive > 0) {
713    status = sc->sc_txdescs[sc->txq_fi].wtx_fields.wtxu_status;
714    if ((status & WTX_ST_DD) == 0) break;
715    i82544EI_txq_free(sc, status);
716    DPRINTF(WM_DEBUG_TX,("%s: TX: job %d done\n",
717                    sc->dv_xname, sc->txq_fi));
718  }
719}
720
721static void wm_init_rxdesc(struct wm_softc *sc, int x) 
722{                       
723  wiseman_rxdesc_t *__rxd = &(sc)->sc_rxdescs[(x)];             
724  struct mbuf *m;
725
726  m = sc->rxs_mbuf[x];
727               
728  __rxd->wrx_addr.wa_low=htole32(mtod(m, void*)); 
729  __rxd->wrx_addr.wa_high = 0;                                 
730  __rxd->wrx_len = 0;                                             
731  __rxd->wrx_cksum = 0;                                           
732  __rxd->wrx_status = 0;                                               
733  __rxd->wrx_errors = 0;                                         
734  __rxd->wrx_special = 0;                                         
735  /* Receive Descriptor Tail: add Rx desc. to H/W free list */   
736  CSR_WRITE(sc,WMREG_RDT, (x));                                         
737} 
738
739static void i82544EI_rx(struct wm_softc *sc)
740{
741  struct ifnet *ifp = &sc->arpcom.ac_if;
742  struct mbuf *m;
743  int i, len;
744  uint8_t status, errors;
745  struct ether_header *eh;
746
747#ifdef WM_DEBUG
748  printk("i82544EI_rx()\n");
749#endif
750
751  for (i = sc->sc_rxptr;; i = WM_NEXTRX(i)) {
752    DPRINTF(WM_DEBUG_RX, ("%s: RX: checking descriptor %d\n",
753                    sc->dv_xname, i));
754
755    status = sc->sc_rxdescs[i].wrx_status;
756    errors = sc->sc_rxdescs[i].wrx_errors;
757    len = le16toh(sc->sc_rxdescs[i].wrx_len);
758    m = sc->rxs_mbuf[i];
759
760    if ((status & WRX_ST_DD) == 0)  break; /* descriptor not done */
761
762    if (sc->sc_rxdiscard) {
763       printk("RX: discarding contents of descriptor %d\n", i);
764       wm_init_rxdesc(sc, i);
765       if (status & WRX_ST_EOP) {
766          /* Reset our state. */
767          printk("RX: resetting rxdiscard -> 0\n");
768          sc->sc_rxdiscard = 0;
769       }
770       continue;
771    }
772
773    /*
774     * If an error occurred, update stats and drop the packet.
775     */
776    if (errors &(WRX_ER_CE|WRX_ER_SE|WRX_ER_SEQ|WRX_ER_CXE|WRX_ER_RXE)) {
777       ifp->if_ierrors++;
778       if (errors & WRX_ER_SE)
779          printk("%s: symbol error\n",sc->dv_xname);
780       else if (errors & WRX_ER_SEQ)
781          printk("%s: receive sequence error\n",sc->dv_xname);
782            else if (errors & WRX_ER_CE)
783                 printk("%s: CRC error\n",sc->dv_xname);
784       m_freem(m);
785       goto give_it_back;
786    }
787
788    /*
789     * No errors.  Receive the packet.
790     *
791     * Note, we have configured the chip to include the
792     * CRC with every packet.
793     */
794    m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header);
795
796    DPRINTF(WM_DEBUG_RX,("%s: RX: buffer at %p len %d\n",
797                    sc->dv_xname, m->m_data, len));
798
799
800    eh = mtod (m, struct ether_header *);
801    m->m_data += sizeof(struct ether_header);
802    ether_input (ifp, eh, m);
803    /* Pass it on. */
804    ifp->if_ipackets++;
805   
806    give_it_back:
807    /* Add a new receive buffer to the ring.*/
808    if (wm_add_rxbuf(sc, i) != 0) {
809       /*
810        * Failed, throw away what we've done so
811        * far, and discard the rest of the packet.
812        */
813       printk("Failed in wm_add_rxbuf(), drop packet\n");
814       ifp->if_ierrors++;
815       wm_init_rxdesc(sc, i);
816       if ((status & WRX_ST_EOP) == 0)
817          sc->sc_rxdiscard = 1;
818       m_freem(m);
819    }
820  } /* end for */
821
822  /* Update the receive pointer. */
823  sc->sc_rxptr = i;
824  DPRINTF(WM_DEBUG_RX, ("%s: RX: rxptr -> %d\n", sc->dv_xname, i));
825}
826
827static int i82544EI_init_hw(struct wm_softc *sc)
828{
829  struct ifnet *ifp = &sc->arpcom.ac_if;
830  int i,error;
831  uint8_t cksumfields;
832
833  /* Cancel any pending I/O. */
834  wm_stop(ifp, 0);
835
836  /* Initialize the error buffer ring */
837  sc->intr_err_ptr1=0;
838  sc->intr_err_ptr2=0;
839  for (i=0; i< INTR_ERR_SIZE; i++) sc->intr_errsts[i]=0;
840
841  /* Initialize the transmit descriptor ring. */
842  memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
843  sc->txq_free = NTXDESC;
844  sc->txq_next = 0;
845  sc->txs_lastdesc = 0;
846  sc->txq_next = 0;
847  sc->txq_free = NTXDESC;
848  sc->txq_nactive = 0;
849
850  sc->sc_txctx_ipcs = 0xffffffff;
851  sc->sc_txctx_tucs = 0xffffffff;
852
853  CSR_WRITE(sc,WMREG_TBDAH, 0);
854  CSR_WRITE(sc,WMREG_TBDAL, WM_CDTXADDR(sc));
855#ifdef WM_DEBUG
856  printk("TBDAL 0x%x, TDLEN %d\n", WM_CDTXADDR(sc), sizeof(sc->sc_txdescs));
857#endif
858  CSR_WRITE(sc,WMREG_TDLEN, sizeof(sc->sc_txdescs));
859  CSR_WRITE(sc,WMREG_TDH, 0);
860  CSR_WRITE(sc,WMREG_TDT, 0);
861  CSR_WRITE(sc,WMREG_TIDV, 64 ); 
862  CSR_WRITE(sc,WMREG_TADV, 128);
863
864  CSR_WRITE(sc,WMREG_TXDCTL, TXDCTL_PTHRESH(0) |
865                    TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0));
866  CSR_WRITE(sc,WMREG_RXDCTL, RXDCTL_PTHRESH(0) |
867                    RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1) | RXDCTL_GRAN );
868
869  CSR_WRITE(sc,WMREG_TQSA_LO, 0);
870  CSR_WRITE(sc,WMREG_TQSA_HI, 0);
871
872  /*
873   * Set up checksum offload parameters for
874   * this packet.
875   */
876#ifdef CKSUM_OFFLOAD
877  if (m0->m_pkthdr.csum_flags &
878     (M_CSUM_IPv4|M_CSUM_TCPv4|M_CSUM_UDPv4)) {
879     if (wm_tx_cksum(sc, txs, &TxDescCmd,&cksumfields) != 0) {
880         /* Error message already displayed. */
881         continue;
882     }
883  } else {
884#endif
885     TxDescCmd = 0;
886     cksumfields = 0;
887#ifdef CKSUM_OFFLOAD
888  }
889#endif
890
891  TxDescCmd |= WTX_CMD_EOP|WTX_CMD_IFCS|WTX_CMD_RS; 
892
893  /* Initialize the transmit job descriptors. */
894  for (i = 0; i < NTXDESC; i++) {
895      sc->txs_mbuf[i] = 0;
896      sc->sc_txdescs[i].wtx_fields.wtxu_options=cksumfields;
897      sc->sc_txdescs[i].wtx_addr.wa_high = 0;
898      sc->sc_txdescs[i].wtx_addr.wa_low = 0;
899      sc->sc_txdescs[i].wtx_cmdlen = htole32(TxDescCmd); 
900  }
901
902  /*
903   * Initialize the receive descriptor and receive job
904   * descriptor rings.
905   */
906  memset(sc->sc_rxdescs, 0, sizeof(sc->sc_rxdescs));
907  CSR_WRITE(sc,WMREG_RDBAH, 0);
908  CSR_WRITE(sc,WMREG_RDBAL, WM_CDRXADDR(sc));
909  CSR_WRITE(sc,WMREG_RDLEN, sizeof(sc->sc_rxdescs));
910  CSR_WRITE(sc,WMREG_RDH, 0);
911  CSR_WRITE(sc,WMREG_RDT, 0);
912  CSR_WRITE(sc,WMREG_RDTR, 0 |RDTR_FPD); 
913  CSR_WRITE(sc, WMREG_RADV, 256);
914
915  for (i = 0; i < NRXDESC; i++) {
916      if (sc->rxs_mbuf[i] == NULL) {
917         if ((error = wm_add_rxbuf(sc, i)) != 0) {
918            printk("%s%d: unable to allocate or map rx buffer"
919            "%d, error = %d\n",ifp->if_name,ifp->if_unit, i, error);
920            /*
921             * XXX Should attempt to run with fewer receive
922             * XXX buffers instead of just failing.
923             */
924            wm_rxdrain(sc);
925            return(error);
926          }
927      } else {
928        printk("sc->rxs_mbuf[%d] not NULL.\n", i);
929        wm_init_rxdesc(sc, i);
930      }
931  }
932  sc->sc_rxptr = 0;
933  sc->sc_rxdiscard = 0;
934
935  /*
936   * Clear out the VLAN table -- we don't use it (yet).
937   */
938  CSR_WRITE(sc,WMREG_VET, 0);
939  for (i = 0; i < WM_VLAN_TABSIZE; i++)
940       CSR_WRITE(sc,WMREG_VFTA + (i << 2), 0);
941
942  /*
943   * Set up flow-control parameters.
944   *
945   * XXX Values could probably stand some tuning.
946   */
947  CSR_WRITE(sc,WMREG_FCAL, FCAL_CONST);/*safe,even though MOTLOAD 0x00c28001 */
948  CSR_WRITE(sc,WMREG_FCAH, FCAH_CONST);/*safe,even though MOTLOAD 0x00000100 */
949  CSR_WRITE(sc,WMREG_FCT, ETHERTYPE_FLOWCONTROL);/*safe,even though MOTLoad 0x8808 */
950
951
952  /* safe,even though MOTLoad default all 0 */
953  sc->sc_fcrtl = FCRTL_DFLT;
954
955  CSR_WRITE(sc,WMREG_FCRTH, FCRTH_DFLT);
956  CSR_WRITE(sc,WMREG_FCRTL, sc->sc_fcrtl);
957  CSR_WRITE(sc,WMREG_FCTTV, FCTTV_DFLT);
958
959  sc->sc_ctrl &= ~CTRL_VME;
960  /*sc->sc_ctrl |= CTRL_TFCE | CTRL_RFCE;*/
961  /* enable Big Endian Mode for the powerPC
962  sc->sc_ctrl |= CTRL_BEM;*/
963
964  /* Write the control registers. */
965  CSR_WRITE(sc,WMREG_CTRL, sc->sc_ctrl);
966#if 0
967  CSR_WRITE(sc,WMREG_CTRL_EXT, sc->sc_ctrl_ext);
968#endif
969
970  /* MOTLoad : WMREG_RXCSUM (0x5000)= 0, no Rx checksum offloading */ 
971
972  /*
973   * Set up the interrupt registers.
974   */
975  CSR_WRITE(sc,WMREG_IMC, 0xffffffffU);
976  /* Reading the WMREG_ICR clears the interrupt bits */
977  CSR_READ(sc,WMREG_ICR);
978
979  /*  printf("WMREG_IMS 0x%x\n", CSR_READ(sc,WMREG_IMS));*/
980
981  sc->sc_icr = ICR_TXDW | ICR_LSC | ICR_RXSEQ | ICR_RXCFG | ICR_RXDMT0 | ICR_RXO | ICR_RXT0;
982
983  CSR_WRITE(sc,WMREG_IMS, sc->sc_icr);
984
985  /* Set up the inter-packet gap. */
986  CSR_WRITE(sc,WMREG_TIPG, sc->sc_tipg);
987
988#if 0 /* XXXJRT */
989  /* Set the VLAN ethernetype. */
990  CSR_WRITE(sc,WMREG_VET, ETHERTYPE_VLAN);
991#endif
992
993  /*
994   * Set up the transmit control register; we start out with
995   * a collision distance suitable for FDX, but update it when
996   * we resolve the media type.
997   */
998  sc->sc_tctl = TCTL_EN | TCTL_PSP | TCTL_CT(TX_COLLISION_THRESHOLD) |
999            TCTL_COLD(TX_COLLISION_DISTANCE_FDX) | TCTL_RTLC; /*transmitter enable*/
1000
1001  /*
1002   * Set up the receive control register; we actually program
1003   * the register when we set the receive filter.  Use multicast
1004   * address offset type 0.
1005   *
1006   * Only the i82544 has the ability to strip the incoming
1007   * CRC, so we don't enable that feature. (TODO)
1008   */
1009  sc->sc_mchash_type = 0;
1010  sc->sc_rctl = RCTL_EN | RCTL_LBM_NONE | RCTL_RDMTS_1_2 | RCTL_LPE |
1011            RCTL_DPF | RCTL_MO(sc->sc_mchash_type);
1012
1013  /* (MCLBYTES == 2048) */
1014  sc->sc_rctl |= RCTL_2k;
1015
1016#ifdef WM_DEBUG
1017  printk("RDBAL 0x%x,RDLEN %d, RDT %d\n",CSR_READ(sc,WMREG_RDBAL),CSR_READ(sc,WMREG_RDLEN), CSR_READ(sc,WMREG_RDT));
1018#endif
1019
1020  /* Set the receive filter. */
1021  wm_set_filter(sc);
1022
1023  CSR_WRITE(sc,WMREG_TCTL, sc->sc_tctl);
1024
1025  /* Map and establish our interrupt. */
1026  if (!BSP_install_rtems_irq_handler(&i82544IrqData))
1027     rtems_panic("1GHZ ethernet: unable to install ISR");
1028
1029  return(0);
1030}
1031
1032/*
1033 * i82544EI_ifinit:             [ifnet interface function]
1034 *
1035 *      Initialize the interface.
1036 */
1037static void i82544EI_ifinit(void *arg)
1038{
1039  struct wm_softc *sc = (struct wm_softc*)arg;
1040
1041#ifdef WM_DEBUG
1042  printk("i82544EI_ifinit(): daemon ID: 0x%08x)\n", sc->daemonTid);
1043#endif
1044  if (sc->daemonTid) {
1045#ifdef WM_DEBUG
1046     printk("i82544EI: daemon already up, doing nothing\n");
1047#endif
1048     return;
1049  }
1050  i82544EI_init_hw(sc);
1051
1052  sc->daemonTid = rtems_bsdnet_newproc(i82544EI_TASK_NAME,4096,i82544EI_daemon,arg);
1053
1054  /* ...all done! */
1055  sc->arpcom.ac_if.if_flags |= IFF_RUNNING; 
1056
1057#ifdef WM_DEBUG
1058  printk(")");
1059#endif
1060}
1061
1062/*
1063 * wm_txdrain:
1064 *
1065 *      Drain the transmit queue.
1066 */
1067static void wm_txdrain(struct wm_softc *sc)
1068{
1069  int i;
1070
1071  /* Release any queued transmit buffers. */
1072  for (i = 0; i <  NTXDESC; i++) {
1073      if (sc->txs_mbuf[i] != NULL) {
1074          m_freem(sc->txs_mbuf[i]);
1075          sc->txs_mbuf[i] = NULL;
1076      }
1077  }
1078}
1079
1080/*
1081 * wm_rxdrain:
1082 *
1083 *      Drain the receive queue.
1084 */
1085static void wm_rxdrain(struct wm_softc *sc)
1086{
1087  int i;
1088
1089  for (i = 0; i < NRXDESC; i++) {
1090      if (sc->rxs_mbuf[i] != NULL) {
1091          m_freem(sc->rxs_mbuf[i]);
1092          sc->rxs_mbuf[i] = NULL;
1093      }
1094  }
1095}
1096
1097static void i82544EI_tx_stop(struct wm_softc *sc)
1098{
1099  wm_txdrain(sc);
1100}
1101
1102static void i82544EI_rx_stop(struct wm_softc *sc)
1103{
1104  wm_rxdrain(sc);
1105}
1106
1107static void i82544EI_stop_hw(struct wm_softc *sc)
1108{
1109#ifdef WM_DEBUG
1110  printk("i82544EI_stop_hw(");
1111#endif
1112
1113  /* remove our interrupt handler which will also
1114  * disable interrupts at the MPIC and the device
1115  * itself
1116  */
1117  if (!BSP_remove_rtems_irq_handler(&i82544IrqData))
1118     rtems_panic("i82544EI: unable to remove IRQ handler!");
1119
1120  CSR_WRITE(sc,WMREG_IMS, 0);
1121
1122  sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
1123  i82544EI_tx_stop(sc);
1124  i82544EI_rx_stop(sc);
1125#ifdef WM_DEBUG
1126  printk(")");
1127#endif
1128}
1129
1130/*
1131 * wm_stop:             [ifnet interface function]
1132 *
1133 *      Stop transmission on the interface.
1134 */
1135static void wm_stop(struct ifnet *ifp, int disable)
1136{
1137  struct wm_softc *sc = ifp->if_softc;
1138
1139#ifdef WM_DEBUG
1140  printk("wm_stop(");
1141#endif 
1142  /* Stop the transmit and receive processes. */
1143  CSR_WRITE(sc,WMREG_TCTL, 0);
1144  CSR_WRITE(sc,WMREG_RCTL, 0);
1145
1146  wm_txdrain(sc);
1147  wm_rxdrain(sc);
1148
1149  /* Mark the interface as down  */
1150  ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1151#ifdef WM_DEBUG
1152  printk(")\n");
1153#endif 
1154}
1155
1156/*
1157 * wm_eeprom_sendbits:
1158 *
1159 *      Send a series of bits to the EEPROM.
1160 */
1161static void wm_eeprom_sendbits(struct wm_softc *sc, uint32_t bits, int nbits)
1162{
1163  uint32_t reg;
1164  int x;
1165
1166  reg = CSR_READ(sc,WMREG_EECD);
1167
1168  for (x = nbits; x > 0; x--) {
1169      if (bits & (1U << (x - 1)))
1170         reg |= EECD_DI;
1171      else
1172         reg &= ~EECD_DI;
1173      CSR_WRITE(sc,WMREG_EECD, reg);
1174      rtems_bsp_delay(2);
1175      CSR_WRITE(sc,WMREG_EECD, reg | EECD_SK);
1176      rtems_bsp_delay(2);
1177      CSR_WRITE(sc,WMREG_EECD, reg);
1178      rtems_bsp_delay(2);
1179  }
1180}
1181
1182/*
1183 * wm_eeprom_recvbits:
1184 *
1185 *      Receive a series of bits from the EEPROM.
1186 */
1187static void wm_eeprom_recvbits(struct wm_softc *sc, uint32_t *valp, int nbits)
1188{
1189  uint32_t reg, val;
1190  int x;
1191
1192  reg = CSR_READ(sc,WMREG_EECD) & ~EECD_DI;
1193
1194  val = 0;
1195  for (x = nbits; x > 0; x--) {
1196      CSR_WRITE(sc,WMREG_EECD, reg | EECD_SK);
1197      rtems_bsp_delay(2);
1198      if (CSR_READ(sc,WMREG_EECD) & EECD_DO)
1199         val |= (1U << (x - 1));
1200      CSR_WRITE(sc,WMREG_EECD, reg);
1201      rtems_bsp_delay(2);
1202  }
1203  *valp = val;
1204}
1205
1206/*
1207 * wm_read_eeprom_uwire:
1208 *
1209 * Read a word from the EEPROM using the MicroWire protocol.
1210 *
1211 * (The 82544EI Gigabit Ethernet Controller is compatible with
1212 * most MicroWire interface, serial EEPROM devices.)
1213 */
1214static int wm_read_eeprom_uwire(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
1215{
1216  uint32_t reg, val;
1217  int i;
1218
1219  for (i = 0; i < wordcnt; i++) {
1220      /* Clear SK and DI. */
1221      reg = CSR_READ(sc,WMREG_EECD) & ~(EECD_SK | EECD_DI);
1222      CSR_WRITE(sc,WMREG_EECD, reg);
1223
1224      /* Set CHIP SELECT. */
1225      reg |= EECD_CS;
1226      CSR_WRITE(sc,WMREG_EECD, reg);
1227      rtems_bsp_delay(2);
1228
1229      /* Shift in the READ command. */
1230      wm_eeprom_sendbits(sc, UWIRE_OPC_READ, 3);
1231
1232      /* Shift in address. */
1233      wm_eeprom_sendbits(sc, word + i, sc->sc_ee_addrbits);
1234
1235      /* Shift out the data. */
1236      wm_eeprom_recvbits(sc, &val, 16);
1237      data[i] = val & 0xffff;
1238
1239      /* Clear CHIP SELECT. */
1240      reg = CSR_READ(sc,WMREG_EECD) & ~EECD_CS;
1241      CSR_WRITE(sc,WMREG_EECD, reg);
1242      rtems_bsp_delay(2);
1243  }
1244  return (0);
1245}
1246
1247/*
1248 * wm_acquire_eeprom:
1249 *
1250 *      Perform the EEPROM handshake required on some chips.
1251 */
1252static int wm_acquire_eeprom(struct wm_softc *sc)
1253{
1254  uint32_t reg;
1255  int x;
1256
1257  reg = CSR_READ(sc,WMREG_EECD);
1258
1259  /* Request EEPROM access. */
1260  reg |= EECD_EE_REQ;
1261  CSR_WRITE(sc,WMREG_EECD, reg);
1262
1263  /* ..and wait for it to be granted. */
1264  for (x = 0; x < 100; x++) {
1265      reg = CSR_READ(sc,WMREG_EECD);
1266      if (reg & EECD_EE_GNT) break;
1267      rtems_bsp_delay(500);
1268  }
1269  if ((reg & EECD_EE_GNT) == 0) {
1270      printk("Could not acquire EEPROM GNT x= %d\n", x);
1271      reg &= ~EECD_EE_REQ;
1272      CSR_WRITE(sc,WMREG_EECD, reg);
1273      return (1);
1274  }
1275
1276  return (0);
1277}
1278
1279/*
1280 * wm_read_eeprom:
1281 *
1282 * Read data from the serial EEPROM.
1283 * 82544EI does not Perform the EEPROM handshake
1284 */
1285static int wm_read_eeprom(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
1286{
1287#if 0
1288  /* base on the datasheet, this does not seem to be applicable */
1289  if (wm_acquire_eeprom(sc))
1290     return(1);
1291#endif
1292  return(wm_read_eeprom_uwire(sc, word, wordcnt, data));
1293}
1294
1295/*
1296 * wm_add_rxbuf:
1297 *
1298 *      Add a receive buffer to the indiciated descriptor.
1299 */
1300static int wm_add_rxbuf(struct wm_softc *sc, int idx)
1301{
1302  struct mbuf *m;
1303
1304  MGETHDR(m, M_WAIT, MT_DATA);
1305  if (m == NULL) return (ENOBUFS);
1306  MCLGET(m, M_WAIT);
1307  if ((m->m_flags & M_EXT) == 0) {
1308     m_freem(m);
1309     return (ENOBUFS);
1310  }
1311  m->m_pkthdr.rcvif =  &sc->arpcom.ac_if;
1312  sc->rxs_mbuf[idx] = m;
1313  /*  m->m_len = m->m_pkthdr.len = m->m_ext.ext_size;*/
1314  wm_init_rxdesc(sc, idx);
1315#if 0
1316  printk("sc->rxs_mbuf[%d]= 0x%x, mbuf @ 0x%x\n",
1317    idx, sc->rxs_mbuf[idx], le32toh(sc->sc_rxdescs[idx].wrx_addr.wa_low));
1318#endif
1319  return(0);
1320}
1321
1322/*
1323 * wm_set_ral:
1324 *
1325 *      Set an entery in the receive address list.
1326 */
1327static void
1328wm_set_ral(struct wm_softc *sc, const uint8_t *enaddr, int idx)
1329{
1330  uint32_t ral_lo, ral_hi;
1331
1332  if (enaddr != NULL) {
1333     ral_lo = enaddr[0]|(enaddr[1] << 8)|(enaddr[2] << 16)|(enaddr[3] << 24);
1334     ral_hi = enaddr[4] | (enaddr[5] << 8);
1335     ral_hi |= RAL_AV;
1336  } else {
1337     ral_lo = 0;
1338     ral_hi = 0;
1339  }
1340
1341  CSR_WRITE(sc,WMREG_RAL_LO(WMREG_CORDOVA_RAL_BASE, idx),ral_lo);
1342  CSR_WRITE(sc,WMREG_RAL_HI(WMREG_CORDOVA_RAL_BASE, idx),ral_hi);
1343}
1344
1345/*
1346 * wm_mchash:
1347 *
1348 *      Compute the hash of the multicast address for the 4096-bit
1349 *      multicast filter.
1350 */
1351static uint32_t
1352wm_mchash(struct wm_softc *sc, const uint8_t *enaddr)
1353{
1354  static const int lo_shift[4] = { 4, 3, 2, 0 };
1355  static const int hi_shift[4] = { 4, 5, 6, 8 };
1356  uint32_t hash;
1357
1358  hash = (enaddr[4] >> lo_shift[sc->sc_mchash_type]) |
1359            (((uint16_t) enaddr[5]) << hi_shift[sc->sc_mchash_type]);
1360
1361  return (hash & 0xfff);
1362}
1363
1364/*
1365 * wm_set_filter: Set up the receive filter.
1366 */
1367static void wm_set_filter(struct wm_softc *sc)
1368{
1369  struct ifnet *ifp = &sc->arpcom.ac_if;
1370  struct ether_multi *enm;
1371  struct ether_multistep step;
1372  uint32_t mta_reg;
1373  uint32_t hash, reg, bit;
1374  int i;
1375
1376#ifdef WM_DEBUG
1377  printk("wm_set_filter(");
1378#endif 
1379  mta_reg = WMREG_CORDOVA_MTA;
1380  sc->sc_rctl &= ~(RCTL_BAM | RCTL_UPE | RCTL_MPE);
1381
1382  /*  if (ifp->if_flags & IFF_BROADCAST)*/
1383     sc->sc_rctl |= RCTL_BAM;
1384  if (ifp->if_flags & IFF_PROMISC) {
1385     sc->sc_rctl |= RCTL_UPE;
1386     goto allmulti;
1387  }
1388
1389  /*
1390   * Set the station address in the first RAL slot, and
1391   * clear the remaining slots.
1392   */
1393  wm_set_ral(sc, sc->arpcom.ac_enaddr, 0);
1394  for (i = 1; i < WM_RAL_TABSIZE; i++)
1395      wm_set_ral(sc, NULL, i);
1396
1397  /* Clear out the multicast table. */
1398  for (i = 0; i < WM_MC_TABSIZE; i++)
1399      CSR_WRITE(sc,mta_reg + (i << 2), 0);
1400
1401  ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
1402  while (enm != NULL) {
1403        if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
1404            /*
1405             * We must listen to a range of multicast addresses.
1406             * For now, just accept all multicasts, rather than
1407             * trying to set only those filter bits needed to match
1408             * the range.  (At this time, the only use of address
1409             * ranges is for IP multicast routing, for which the
1410             * range is big enough to require all bits set.)
1411             */
1412            goto allmulti;
1413         }
1414
1415         hash = wm_mchash(sc, enm->enm_addrlo);
1416
1417         reg = (hash >> 5) & 0x7f;
1418         bit = hash & 0x1f;
1419
1420         hash = CSR_READ(sc,mta_reg + (reg << 2));
1421         hash |= 1U << bit;
1422
1423         /* XXX Hardware bug?? */
1424         if ((reg & 0xe) == 1) {
1425            bit = CSR_READ(sc,mta_reg + ((reg - 1) << 2));
1426            CSR_WRITE(sc,mta_reg + (reg << 2), hash);
1427            CSR_WRITE(sc,mta_reg + ((reg - 1) << 2), bit);
1428         } else
1429            CSR_WRITE(sc,mta_reg + (reg << 2), hash);
1430
1431         ETHER_NEXT_MULTI(step, enm);
1432  }
1433
1434  ifp->if_flags &= ~IFF_ALLMULTI;
1435  goto setit;
1436
1437 allmulti:
1438  ifp->if_flags |= IFF_ALLMULTI;
1439  sc->sc_rctl |= RCTL_MPE;
1440
1441 setit:
1442  CSR_WRITE(sc,WMREG_RCTL, sc->sc_rctl);
1443
1444#ifdef WM_DEBUG
1445  printk("RCTL 0x%x)\n", CSR_READ(sc,WMREG_RCTL));
1446#endif 
1447}
1448
1449static void i82544EI_error(struct wm_softc *sc)
1450{
1451  struct ifnet          *ifp = &sc->arpcom.ac_if;
1452  unsigned long         intr_status= sc->intr_errsts[sc->intr_err_ptr1++];
1453
1454  /* read and reset the status; because this is written
1455   * by the ISR, we must disable interrupts here
1456   */
1457  sc->intr_err_ptr1 %=INTR_ERR_SIZE; /* Till Straumann */
1458  if (intr_status) {
1459    printk("Error %s%d:", ifp->if_name, ifp->if_unit);
1460    if (intr_status & ICR_RXSEQ) {
1461       printk("Rxq framing error (ICR= %x), if_ierrors %d\n",
1462              intr_status, ifp->if_ierrors);
1463    }
1464  }
1465  else 
1466    printk("%s%d: Ghost interrupt ?\n",ifp->if_name,ifp->if_unit);
1467}
1468
1469void i82544EI_printStats()
1470{
1471  i82544EI_stats(root_i82544EI_dev);
1472}
1473
1474/* The daemon does all of the work; RX, TX and cleaning up buffers/descriptors */
1475static void i82544EI_daemon(void *arg)
1476{
1477  struct wm_softc *sc = (struct wm_softc*)arg;
1478  rtems_event_set       events;
1479  struct mbuf   *m=0;
1480  struct ifnet  *ifp=&sc->arpcom.ac_if;
1481  int i;
1482
1483#ifdef WM_DEBUG
1484  printk("i82544EI_daemon()\n");
1485#endif
1486
1487  /* NOTE: our creator possibly holds the bsdnet_semaphore.
1488   *       since that has PRIORITY_INVERSION enabled, our
1489   *       subsequent call to bsdnet_event_receive() will
1490   *       _not_ release it. It's still in posession of our
1491   *       owner.
1492   *       This is different from how killing this task
1493   *       is handled.
1494   */
1495
1496  for (;;) {
1497     /* sleep until there's work to be done */
1498     /* Note: bsdnet_event_receive() acquires
1499      *       the global bsdnet semaphore for
1500      *       mutual exclusion.
1501      */
1502     rtems_bsdnet_event_receive(ALL_EVENTS,
1503                                RTEMS_WAIT | RTEMS_EVENT_ANY,
1504                                RTEMS_NO_TIMEOUT,
1505                                &events);
1506     if (KILL_EVENT & events)  break;
1507
1508     if (events & RX_EVENT)  i82544EI_rx(sc);
1509
1510     /* clean up and try sending packets */
1511     do { 
1512        i82544EI_txq_done(sc);
1513
1514        while (sc->txq_free>0) {
1515           if (sc->txq_free>TXQ_HiLmt_OFF) {
1516              IF_DEQUEUE(&ifp->if_snd,m);
1517              if (m==0) break;
1518              i82544EI_sendpacket(sc, m); 
1519           }
1520           else {
1521              i82544EI_txq_done(sc);
1522              break;
1523           }
1524           if (events & RX_EVENT)  i82544EI_rx(sc);
1525        }
1526         /* we leave this loop
1527          *  - either because there's no free buffer
1528          *    (m=0 initializer && !sc->txq_free)
1529          *  - or there's nothing to send (IF_DEQUEUE
1530          *    returned 0
1531          */
1532     } while (m && sc->txq_free);
1533
1534     ifp->if_flags &= ~IFF_OACTIVE;
1535
1536     /* Log errors and other uncommon events. */
1537     if (events & ERR_EVENT) i82544EI_error(sc); 
1538     /* Rx overrun */
1539     if ( events & INIT_EVENT) {
1540        printk("Warnning, Rx overrun.  Make sure the old mbuf was free\n");
1541        i82544EI_ifinit(arg);
1542     }
1543
1544  } /* end for(;;) { rtems_bsdnet_event_receive() .....*/
1545
1546  printf("out of daemon\n");
1547  ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);
1548
1549  /* shut down the hardware */
1550  i82544EI_stop_hw(sc);
1551  /* flush the output queue */
1552  for (;;) {
1553      IF_DEQUEUE(&ifp->if_snd,m);
1554      if (!m) break;
1555      m_freem(m);
1556  }
1557  /* as of 'rtems_bsdnet_event_receive()' we own the
1558   * networking semaphore
1559   */
1560  rtems_bsdnet_semaphore_release();
1561  rtems_semaphore_release(sc->daemonSync);
1562
1563  /* Note that I dont use sc->daemonTid here -
1564   * theoretically, that variable could already
1565   * hold a newly created TID
1566   */
1567  rtems_task_delete(RTEMS_SELF);
1568}
Note: See TracBrowser for help on using the repository browser.