c1df96fb2daedf7f16797591ef71e86478786c81
[people/indolent/gpxe.git/.git] / src / drivers / net / eepro100.c
1 /* 
2    eepro100.c - gPXE driver for the eepro100 8255x series. 
3 */
4
5 #include <stdint.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <io.h>
9 #include <errno.h>
10 #include <timer.h>
11 #include <byteswap.h>
12 #include <gpxe/pci.h>
13 #include <gpxe/if_ether.h>
14 #include <gpxe/ethernet.h>
15 #include <gpxe/iobuf.h>
16 #include <gpxe/netdevice.h>
17 #include <gpxe/spi_bit.h>
18 #include <gpxe/threewire.h>
19 #include <gpxe/nvo.h>
20
21
22 #define TX_RING_SIZE 4
23 #define NUM_RX_DESC  4
24 #define RX_BUF_SIZE 1528
25 #define CONFIG_DATA_SIZE 22
26
27 /* Elements of the dump_statistics block. This block must be lword aligned. */
28 struct speedo_stats {
29         u32 tx_good_frames;
30         u32 tx_coll16_errs;
31         u32 tx_late_colls;
32         u32 tx_underruns;
33         u32 tx_lost_carrier;
34         u32 tx_deferred;
35         u32 tx_one_colls;
36         u32 tx_multi_colls;
37         u32 tx_total_colls;
38         u32 rx_good_frames;
39         u32 rx_crc_errs;
40         u32 rx_align_errs;
41         u32 rx_resource_errs;
42         u32 rx_overrun_errs;
43         u32 rx_colls_errs;
44         u32 rx_runt_errs;
45         u32 done_marker;
46 };
47
48 struct speedo_tx {
49         volatile s16 status;
50         s16 command;
51         u32 link;          /* void * */
52         u32 tx_desc_addr;  /* (almost) Always points to the tx_buf_addr element. */
53         s32 count;         /* # of TBD (=2), Tx start thresh., etc. */
54         /* This constitutes two "TBD" entries: hdr and data */
55         u32 tx_buf_addr0;  /* void *, header of frame to be transmitted.  */
56         s32 tx_buf_size0;  /* Length of Tx hdr. */
57         u32 tx_buf_addr1;  /* void *, data to be transmitted.  */
58         s32 tx_buf_size1;  /* Length of Tx data. */
59 };
60
61 struct speedo_rx {
62         volatile s16 status;
63         s16 command;
64         u32 link;                 /* struct RxFD * */
65         u32 rx_buf_addr;          /* void * */
66         u16 count;
67         u16 size;
68         char packet[RX_BUF_SIZE];
69 };
70
71 struct speedo_private {
72         unsigned short ioaddr;
73         unsigned short tx_cur;
74         unsigned short tx_dirty;
75         unsigned short rx_cur;
76         struct speedo_tx txfd[TX_RING_SIZE];
77         struct speedo_rx rxfd[NUM_RX_DESC];
78
79         /* netdev_tx_complete needs pointer to the iobuf of the data so as to free 
80          * it from the memory.
81          */
82         struct io_buffer *tx_iobuf[TX_RING_SIZE];
83         struct speedo_stats lstats;
84         struct spi_bit_basher spibit;
85         struct spi_device eeprom;
86         struct nvo_block nvo;
87 };
88
89 enum speedo_offsets {
90   SCBStatus = 0, SCBCmd = 2,      /* Rx/Command Unit command and status. */
91   SCBPointer = 4,                 /* General purpose pointer. */
92   SCBPort = 8,                    /* Misc. commands and operands.  */
93   SCBflash = 12, SCBeeprom = 14,  /* EEPROM and flash memory control. */
94   SCBCtrlMDI = 16,                /* MDI interface control. */
95   SCBEarlyRx = 20,                /* Early receive byte count. */
96 };
97
98 enum SCBCmdBits {
99         SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
100         SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
101         SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
102         /* The rest are Rx and Tx commands. */
103         CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
104         CUCmdBase=0x0060,       /* CU Base address (set to zero) . */
105         CUDumpStats=0x0070, /* Dump then reset stats counters. */
106         RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
107         RxResumeNoResources=0x0007,
108 };
109
110 static const char i82558_config_cmd[CONFIG_DATA_SIZE] = {
111         22, 0x08, 0, 1,  0, 0, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */
112         0, 0x2E, 0,  0x60, 0x08, 0x88,
113         0x68, 0, 0x40, 0xf2, 0x84,              /* Disable FC */
114         0x31, 0x05, };
115
116 unsigned short eeprom[16];
117 /* Serial EEPROM section.
118    A "bit" grungy, but we work our way through bit-by-bit :->. */
119 /*  EEPROM_Ctrl bits. */
120 #define EE_SHIFT_CLK    0x01    /* EEPROM shift clock. */
121 #define EE_CS           0x02    /* EEPROM chip select. */
122 #define EE_DATA_WRITE   0x04    /* EEPROM chip data in. */
123 #define EE_DATA_READ    0x08    /* EEPROM chip data out. */
124 #define EE_WRITE_0      0x4802
125 #define EE_WRITE_1      0x4806
126 #define EE_ENB          (0x4800 | EE_CS)
127
128 /* The EEPROM commands include the alway-set leading bit. */
129 #define EE_READ_CMD     6
130
131
132 /* The SCB accepts the following controls for the Tx and Rx units: */
133 #define  CU_START       0x0010
134 #define  CU_RESUME      0x0020
135 #define  CU_STATSADDR   0x0040
136 #define  CU_SHOWSTATS   0x0050  /* Dump statistics counters. */
137 #define  CU_CMD_BASE    0x0060  /* Base address to add to add CU commands. */
138 #define  CU_DUMPSTATS   0x0070  /* Dump then reset stats counters. */
139
140 #define  RX_START       0x0001
141 #define  RX_RESUME      0x0002
142 #define  RX_ABORT       0x0004
143 #define  RX_ADDR_LOAD   0x0006
144 #define  RX_RESUMENR    0x0007
145 #define INT_MASK        0x0100
146 #define DRVR_INT        0x0200          /* Driver generated interrupt. */
147
148 enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
149                                          S80C24, PhyUndefined, DP83840A=10, };
150
151 /* Commands that can be put in a command list entry. */
152 enum commands {
153   CmdNOp = 0,
154   CmdIASetup = 1,
155   CmdConfigure = 2,
156   CmdMulticastList = 3,
157   CmdTx = 4,
158   CmdTDR = 5,
159   CmdDump = 6,
160   CmdDiagnose = 7,
161
162   /* And some extra flags: */
163   CmdSuspend = 0x4000,      /* Suspend after completion. */
164   CmdIntr = 0x2000,         /* Interrupt after completion. */
165   CmdTxFlex = 0x0008,       /* Use "Flexible mode" for CmdTx command. */
166 };
167
168 /* Selected elements of the Tx/RxFD.status word. */
169 enum RxFD_bits {
170         RxComplete=0x8000, RxOK=0x2000,
171         RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,
172         RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,
173         TxUnderrun=0x1000,  StatusComplete=0x8000,
174 };
175
176 static int congenb = 0;         /* Enable congestion control in the DP83840. */
177 static int txfifo = 8;          /* Tx FIFO threshold in 4 byte units, 0-15 */
178 static int rxfifo = 8;          /* Rx FIFO threshold, default 32 bytes. */
179 static int txdmacount = 0;      /* Tx DMA burst length, 0-127, default 0. */
180 static int rxdmacount = 0;      /* Rx DMA length, 0 means no preemption. */
181
182
183 /*  Function Prototypes: */
184  
185 static int speedo_open (struct net_device *netdev);
186 static int speedo_transmit (struct net_device *netdev, struct io_buffer *iobuf);
187 static void speedo_poll (struct net_device *netdev);
188 static void speedo_disable ( struct net_device *netdev); 
189
190 /** speedo net device operations */
191 static struct net_device_operations speedo_operations = {
192         .open           = speedo_open,
193         .close          = speedo_disable,
194         .transmit       = speedo_transmit,
195         .poll           = speedo_poll,
196 //      .irq            = speedo_irq,
197 };
198
199 /* How to wait for the command unit to accept a command.
200    Typically this takes 0 ticks. */
201 static inline void wait_for_cmd_done(int cmd_ioaddr)
202 {
203   int wait = 0;
204   int delayed_cmd;
205
206   do
207     if (inb(cmd_ioaddr) == 0) return;
208   while(++wait <= 100);
209   delayed_cmd = inb(cmd_ioaddr);
210   do
211     if (inb(cmd_ioaddr) == 0) break;
212   while(++wait <= 10000);
213   printf("Command %2.2x was not immediately accepted, %d ticks!\n",
214       delayed_cmd, wait);
215 }
216 /* Support function: mdio_write
217  *
218  * This probably writes to the "physical media interface chip".
219  * -- REW
220  */
221
222 static int mdio_write(struct net_device *netdev, int phy_id, int location, int value)
223 {
224         struct speedo_private *sp = netdev->priv;
225         int val, boguscnt = 64*4;         /* <64 usec. to complete, typ 27 ticks */
226
227         outl(0x04000000 | (location<<16) | (phy_id<<21) | value,
228              sp->ioaddr + SCBCtrlMDI);
229         do {
230                 udelay(16);
231
232                 val = inl(sp->ioaddr + SCBCtrlMDI);
233                 if (--boguscnt < 0) {
234                         printf(" mdio_write() timed out with val = %X.\n", val);
235                         break;
236                 }
237         } while (! (val & 0x10000000));
238         return val & 0xffff;
239 }
240
241 /* Support function: mdio_read
242  *
243  * This probably reads a register in the "physical media interface chip".
244  * -- REW
245  */
246 static int mdio_read(struct net_device *netdev,int phy_id, int location)
247 {
248         struct speedo_private *sp = netdev->priv;
249         int val, boguscnt = 64*4;               /* <64 usec. to complete, typ 27 ticks */
250         outl(0x08000000 | (location<<16) | (phy_id<<21), sp->ioaddr + SCBCtrlMDI);
251         do {
252                 udelay(16);
253
254                 val = inl(sp->ioaddr + SCBCtrlMDI);
255
256                 if (--boguscnt < 0) {
257                         printf( " mdio_read() timed out with val = %X.\n", val);
258                         break;
259                 }
260         } while (! (val & 0x10000000));
261         return val & 0xffff;
262 }
263 /* The fixes for the code were kindly provided by Dragan Stancevic
264    <visitor@valinux.com> to strictly follow Intel specifications of EEPROM
265    access timing.
266    The publicly available sheet 64486302 (sec. 3.1) specifies 1us access
267    interval for serial EEPROM.  However, it looks like that there is an
268    additional requirement dictating larger udelay's in the code below.
269    2000/05/24  SAW */
270 static int do_eeprom_cmd(struct net_device *netdev,int cmd, int cmd_len)
271 {
272         struct speedo_private *sp = netdev->priv;
273         unsigned retval = 0;
274         long ee_addr = sp->ioaddr + SCBeeprom;
275
276         outw(EE_ENB, ee_addr); udelay(2);
277         outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
278
279         /* Shift the command bits out. */
280         do {
281                 short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
282                 outw(dataval, ee_addr); udelay(2);
283                 outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
284                 retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0);
285         } while (--cmd_len >= 0);
286         outw(EE_ENB, ee_addr); udelay(2);
287
288         /* Terminate the EEPROM access. */
289         outw(EE_ENB & ~EE_CS, ee_addr);
290         return retval;
291 }
292
293 /* function: eepro100_disable
294  * resets the card. This is used to allow Etherboot or Linux
295  * to probe the card again from a "virginal" state....
296  * Arguments: none
297  *
298  * returns:   void.
299  */
300 static void speedo_disable ( struct net_device *netdev) {
301         struct speedo_private *sp = netdev->priv;
302         /* from eepro100_reset */
303         outl(0, sp->ioaddr + SCBPort);
304         /* from eepro100_disable */
305         /* See if this PartialReset solves the problem with interfering with
306            kernel operation after Etherboot hands over. - Ken 20001102 */
307         outl(2, sp->ioaddr + SCBPort);
308
309         /* The following is from the Intel e100 driver.
310          * This hopefully solves the problem with hanging hard DOS images. */
311
312         /* wait for the reset to take effect */
313         udelay(20);
314
315         /* Mask off our interrupt line -- it is unmasked after reset */
316         {
317                 u16 intr_status;
318                 /* Disable interrupts on our PCI board by setting the mask bit */
319                 outw(INT_MASK, sp->ioaddr + SCBCmd);
320                 intr_status = inw(sp->ioaddr + SCBStatus);
321                 /* ack and clear intrs */
322                 outw(intr_status, sp->ioaddr + SCBStatus);
323                 inw(sp->ioaddr + SCBStatus);
324         }
325 }
326
327
328 /**
329  * Probe PCI device
330  *
331  * @v pci       PCI device
332  * @v id        PCI ID
333  * @ret rc      Return status code
334  */
335 static int speedo_probe (struct pci_device *pci,
336                        const struct pci_device_id *id __unused) {
337         struct net_device *netdev;
338         struct speedo_private *sp = NULL;
339         int rc;
340         int read_cmd, ee_size;
341         int i, sum;
342
343         /* Allocate net device 
344          */
345         DBG("In probe routine \n");
346         netdev = alloc_etherdev (sizeof (*sp));
347         if (! netdev) 
348                 return -ENOMEM;
349
350         netdev_init (netdev, &speedo_operations);
351         sp = netdev->priv;
352         pci_set_drvdata (pci, netdev);
353         netdev->dev = &pci->dev;
354         memset (sp, 0, sizeof (*sp));
355         sp->ioaddr = pci->ioaddr;
356
357         adjust_pci_device (pci);
358
359         //natsemi_reset (netdev);
360         
361         /* read the MAC Address */
362         if ((do_eeprom_cmd(netdev,EE_READ_CMD << 24, 27) & 0xffe0000)
363                 == 0xffe0000) {
364                 ee_size = 0x100;
365                 read_cmd = EE_READ_CMD << 24;
366         } else {
367                 ee_size = 0x40;
368                 read_cmd = EE_READ_CMD << 22;
369         }
370
371         for (i = 0, sum = 0; i < ee_size; i++) {
372                 unsigned short value = do_eeprom_cmd(netdev,read_cmd | (i << 16), 27);
373                 if (i < (int)(sizeof(eeprom)/sizeof(eeprom[0])))
374                         eeprom[i] = value;
375                 sum += value;
376         }
377
378         for (i=0;i<ETH_ALEN;i++) {
379                 netdev->ll_addr[i] =  (eeprom[i/2] >> (8*(i&1))) & 0xff;
380         }
381
382
383         if ((rc = register_netdev (netdev)) != 0)
384                 goto err_register_netdev;
385
386         return 0;
387
388 err_register_netdev:
389
390         speedo_disable (netdev);
391         netdev_put (netdev);
392         return rc;
393 }
394
395 /**
396  * Open NIC
397  *
398  * @v netdev            Net device
399  * @ret rc              Return status code
400  */
401 static int speedo_open (struct net_device *netdev) { 
402         struct speedo_private *sp = netdev->priv; 
403         int i; 
404         int options = 0x00;
405         int rx_mode=0;
406         /* Setup RX ring
407          */
408         /*TODO check what is required */
409         outl(0, sp->ioaddr + SCBPointer);
410         outw(INT_MASK | RX_ADDR_LOAD, sp->ioaddr + SCBCmd);
411         wait_for_cmd_done(sp->ioaddr + SCBCmd);
412
413         outl(virt_to_bus(&sp->lstats), sp->ioaddr + SCBPointer);
414         outb(CU_STATSADDR, sp->ioaddr + SCBCmd);
415         wait_for_cmd_done(sp->ioaddr + SCBCmd);
416
417
418         sp->rx_cur = 0;
419         for (i = 0 ; i < NUM_RX_DESC ; i++) {
420                 sp->rxfd[i].status      = 0x0000;
421                 sp->rxfd[i].command     = 0x0000;
422                 sp->rxfd[i].rx_buf_addr = 0xFFFFFFFF;
423                 sp->rxfd[i].count       = 0;
424                 sp->rxfd[i].size        = RX_BUF_SIZE;
425                 sp->rxfd[i].link        = virt_to_bus(&sp->rxfd[i+1]);
426         }
427
428         sp->rxfd[NUM_RX_DESC -1].status  = 0x0000;
429         sp->rxfd[NUM_RX_DESC -1].command = 0xC000;
430         sp->rxfd[NUM_RX_DESC -1].link    = virt_to_bus(&sp->rxfd[0]);
431
432
433         outl(virt_to_bus(&sp->rxfd[0]), sp->ioaddr + SCBPointer);
434         outb(RX_START, sp->ioaddr + SCBCmd);
435         wait_for_cmd_done(sp->ioaddr + SCBCmd);
436
437         /* Setup Tx Ring 
438          */
439         /* Base = 0 */
440         outl(0, sp->ioaddr + SCBPointer);
441         outb(CU_CMD_BASE, sp->ioaddr + SCBCmd);
442         wait_for_cmd_done(sp->ioaddr + SCBCmd);
443         sp->tx_cur = 0;
444         sp->tx_dirty = 0;
445         for (i = 0 ; i < TX_RING_SIZE ; i++) {
446                 sp->txfd[i].link   = virt_to_bus ((i + 1 < TX_RING_SIZE) ? &
447                                                    sp->txfd[i + 1] : &sp->txfd[0]);
448                 sp->txfd[i].command = (CmdSuspend);
449                 sp->txfd[i].status = 0;
450                 sp->txfd[i].tx_desc_addr = virt_to_bus(&sp->txfd[i].tx_buf_addr0);
451         }
452
453         
454         /* Setting up the RX mode */
455         /* Set or clear the multicast filter for this adaptor.
456            This is very ugly with Intel chips -- we usually have to execute an
457            entire configuration command, plus process a multicast command.
458            This is complicated.  We must put a large configuration command and
459            an arbitrarily-sized multicast command in the transmit list.
460            To minimize the disruption -- the previous command might have already
461            loaded the link -- we convert the current command block, normally a Tx
462            command, into a no-op and link it to the new command.
463         */
464         
465                 if (   ((eeprom[6]>>8) & 0x3f) == DP83840
466                || ((eeprom[6]>>8) & 0x3f) == DP83840A) {
467                 int mdi_reg23 = mdio_read(netdev,eeprom[6] & 0x1f, 23) | 0x0422;
468                 if (congenb)
469                         mdi_reg23 |= 0x0100;
470                 DBG("  DP83840 specific setup, setting register 23 to %hX.\n",
471                        mdi_reg23);
472                 mdio_write(netdev,eeprom[6] & 0x1f, 23, mdi_reg23);
473         }
474         DBG ("Done DP8340 special setup.\n");
475         if (options != 0) {
476                 mdio_write(netdev,eeprom[6] & 0x1f, 0,
477                            ((options & 0x20) ? 0x2000 : 0) |    /* 100mbps? */
478                            ((options & 0x10) ? 0x0100 : 0)); /* Full duplex? */
479                 DBG ("set mdio_register.\n");
480         }
481
482         
483         sp->tx_cur++;
484         sp->tx_dirty++;
485         sp->txfd[0].status = (CmdSuspend | CmdConfigure);
486         uint8_t * config_cmd_data;
487         config_cmd_data = (void *)&sp->txfd[0].tx_desc_addr;
488         /* Construct a full CmdConfig frame. */
489         memcpy(config_cmd_data, i82558_config_cmd, CONFIG_DATA_SIZE);   
490         config_cmd_data[1]  = (txfifo << 4) | rxfifo;
491         config_cmd_data[4]  = rxdmacount;
492         config_cmd_data[5]  = txdmacount + 0x80;
493         config_cmd_data[15] = (rx_mode & 2) ? 0x49: 0x48;
494         config_cmd_data[19] = (options & 0x10) ? 0xC0 : 0x80;
495         config_cmd_data[21] = (rx_mode & 1) ? 0x0D: 0x05;
496
497         outl(virt_to_bus(&sp->txfd[0]), sp->ioaddr + SCBPointer);
498         outb(CU_START, sp->ioaddr + SCBCmd);
499         wait_for_cmd_done(sp->ioaddr + SCBCmd);
500
501         /* Read the status register once to disgard stale data */
502         mdio_read(netdev,eeprom[6] & 0x1f, 1);
503         /* Check to see if the network cable is plugged in.
504          * This allows for faster failure if there is nothing
505          * we can do.
506          */
507         if (!(mdio_read(netdev,eeprom[6] & 0x1f, 1) & (1 << 2))) {
508                 printf("Valid link not established\n");
509                 speedo_disable(netdev);
510                 return -1;
511         }
512
513
514         
515
516         return 0;
517                        
518 }
519
520
521 /** 
522  * Transmit packet
523  *
524  * @v netdev    Network device
525  * @v iobuf     I/O buffer
526  * @ret rc      Return status code
527  */
528 static int speedo_transmit (struct net_device *netdev, struct io_buffer *iobuf)
529 {
530         struct speedo_private *sp = netdev->priv;
531         unsigned short status;
532
533         status = inw(sp->ioaddr + SCBStatus);
534         /* Acknowledge all of the current interrupt sources ASAP. */
535         outw(status & 0xfc00, sp->ioaddr + SCBStatus);
536
537         if ((sp->tx_cur + 1)% TX_RING_SIZE == sp->tx_dirty) {
538                 DBG ("TX overflow\n");
539                 return -ENOBUFS;
540         }
541
542         /* Used by netdev_tx_complete ()
543          */
544         sp->tx_iobuf[sp->tx_cur] = iobuf;
545
546         /* Pad and align packet has not been used because its not required 
547          * by the hardware.
548          *      iob_pad (iobuf, ETH_ZLEN); 
549          * can be used to achieve it, if required
550          */
551
552         /* Add the packet to TX ring
553          */
554
555         sp->txfd[sp->tx_cur].status =  0;
556         sp->txfd[sp->tx_cur].command = CmdSuspend | CmdTx | CmdTxFlex;
557         sp->txfd[sp->tx_cur].count =  0x02208000;
558         sp->txfd[sp->tx_cur].tx_buf_addr0 = virt_to_bus (iobuf->data);
559         sp->txfd[sp->tx_cur].tx_buf_size0 = iob_len(iobuf);
560
561         DBG ("TX id %d at %#08lx + %#08x\n", sp->tx_cur,
562              virt_to_bus (&iobuf->data), iob_len (iobuf));
563
564
565         /* start the transmitter 
566          *
567          * Removing suspend from the command of previous packet.  
568          * As linx driver does
569          */
570         sp->txfd[((sp->tx_cur-1) < 0 ? TX_RING_SIZE -1 : sp->tx_cur -1)].command 
571                                                                 &= ~CmdSuspend; 
572         /* We want the time window between clearing suspend flag on the previous
573            command and resuming CU to be as small as possible.
574            Interrupts in between are very undesired.  --SAW */
575         outb(CUResume, sp->ioaddr + SCBCmd);
576
577         /* increment the circular buffer pointer to the next buffer location
578          */
579         sp->tx_cur = (sp->tx_cur + 1) % TX_RING_SIZE;
580
581         return 0;
582 }
583
584
585
586 /*
587  * Sometimes the receiver stops making progress.  This routine knows how to
588  * get it going again, without losing packets or being otherwise nasty like
589  * a chip reset would be.  Previously the driver had a whole sequence
590  * of if RxSuspended, if it's no buffers do one thing, if it's no resources,
591  * do another, etc.  But those things don't really matter.  Separate logic
592  * in the ISR provides for allocating buffers--the other half of operation
593  * is just making sure the receiver is active.  speedo_rx_soft_reset does that.
594  * This problem with the old, more involved algorithm is shown up under
595  * ping floods on the order of 60K packets/second on a 100Mbps fdx network.
596  */
597 static void
598 speedo_rx_soft_reset(struct net_device *netdev)
599 {
600         struct speedo_private *sp = netdev->priv;
601         int i;
602
603
604         DBG("reset\n");
605         wait_for_cmd_done(sp->ioaddr + SCBCmd);
606         /*
607          * Put the hardware into a known state.
608          */
609         outb(RX_ABORT, sp->ioaddr + SCBCmd);
610
611         for (i = 0; i < NUM_RX_DESC; i++) {
612                 sp->rxfd[i].status      = 0;
613                 sp->rxfd[i].rx_buf_addr = 0xffffffff;
614                 sp->rxfd[i].count       = 0;
615                 sp->rxfd[i].size        = RX_BUF_SIZE;
616         }
617
618         wait_for_cmd_done(sp->ioaddr + SCBCmd);
619
620         outl(virt_to_bus(&sp->rxfd[sp->rx_cur]), sp->ioaddr + SCBPointer);
621         outb(RX_START, sp->ioaddr + SCBCmd);
622 }
623
624
625
626
627
628 /** 
629  * Poll for received packets
630  *
631  * @v netdev    Network device
632  */
633 static void speedo_poll (struct net_device *netdev)
634 {
635         struct speedo_private *sp = netdev->priv;
636         uint16_t tx_status;
637         unsigned int rx_status;
638         unsigned int intr_status;
639         unsigned int rx_len;
640         struct io_buffer *rx_iob;
641         int i;
642         
643         /* read the interrupt register TODO
644          */
645         intr_status = inw (sp->ioaddr + SCBStatus);
646
647         //if (!intr_status)
648         //      goto end;
649
650         //DBG ("eepro/speedo speedo_poll: intr_status = %#08x\n", intr_status);
651
652         /* Check status of transmitted packets
653          */
654         i = sp->tx_dirty;
655         while (i != sp->tx_cur) {
656                 tx_status = sp->txfd[sp->tx_dirty].status;
657
658                 DBG ("tx_dirty = %d tx_cur=%d tx_status=%#08x\n",
659                      sp->tx_dirty, sp->tx_cur, tx_status);
660                 
661                 if (( tx_status & StatusComplete ) == 0) 
662                         break;
663
664                 netdev_tx_complete (netdev, sp->tx_iobuf[sp->tx_dirty]);
665                 DBG ("Success transmitting packet\n");
666
667                 sp->tx_dirty = (sp->tx_dirty + 1) % TX_RING_SIZE;
668                 i = (i + 1) % TX_RING_SIZE;
669         }
670         
671         /* Process received packets 
672          */
673         rx_status = sp->rxfd[sp->rx_cur].status; 
674         while (rx_status) {
675                 rx_len = sp->rxfd[sp->rx_cur].count & 0x3fff;
676
677                 DBG ("Received packet, rx_curr = %d, rx_status = %#08x, rx_len = %d\n",
678                      sp->rx_cur, rx_status, rx_len);
679                 /* If unable allocate space for this packet,
680                  *  try again next poll
681                  */
682                 rx_iob = alloc_iob (rx_len);
683                 if (! rx_iob) 
684                         break;
685                 memcpy (iob_put (rx_iob, rx_len), 
686                         sp->rxfd[sp->rx_cur].packet, rx_len);
687                 /* Add this packet to the receive queue. 
688                  */
689                 netdev_rx (netdev, rx_iob);
690                 
691                 sp->rxfd[sp->rx_cur].status = 0;
692                 sp->rxfd[sp->rx_cur].command = 0xc000;
693                 sp->rxfd[sp->rx_cur].rx_buf_addr = 0xFFFFFFFF;
694                 sp->rxfd[sp->rx_cur].count = 0;
695                 sp->rxfd[sp->rx_cur].size = RX_BUF_SIZE;
696                 sp->rxfd[(sp->rx_cur-1)% NUM_RX_DESC].command = 0;
697                 sp->rx_cur = (sp->rx_cur + 1) % NUM_RX_DESC;
698                 rx_status = sp->rxfd[sp->rx_cur].status; 
699                 /* Acknowledge all interrupts */
700                 outw(0xff00,sp->ioaddr + SCBStatus);
701
702         }
703
704         /*
705          * The chip may have suspended reception for various reasons.
706          * Check for that, and re-prime it should this be the case.
707          */
708         switch ((inw(sp->ioaddr + SCBStatus) >> 2) & 0xf) {
709                 case 0:  /* Idle */
710                         break;
711                 case 1:  /* Suspended */
712                 case 2:  /* No resources (RxFDs) */
713                 case 9:  /* Suspended with no more RBDs */
714                 case 10: /* No resources due to no RBDs */
715                 case 12: /* Ready with no RBDs */
716                         speedo_rx_soft_reset(netdev);
717                         break;
718                 default:
719                         /* reserved values */
720                         break;
721         }
722
723 }                               
724
725
726 /**
727  * Remove PCI device
728  *
729  * @v pci       PCI device
730  */
731 static void speedo_remove (struct pci_device *pci) {
732         struct net_device *netdev = pci_get_drvdata (pci);
733
734         unregister_netdev (netdev);
735         speedo_disable (netdev);
736         netdev_put (netdev);
737 }
738
739
740 static struct pci_device_id speedo_nics[] = {
741 PCI_ROM(0x8086, 0x1029, "id1029",        "Intel EtherExpressPro100 ID1029"),
742 PCI_ROM(0x8086, 0x1030, "id1030",        "Intel EtherExpressPro100 ID1030"),
743 PCI_ROM(0x8086, 0x1031, "82801cam",      "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
744 PCI_ROM(0x8086, 0x1032, "eepro100-1032", "Intel PRO/100 VE Network Connection"),
745 PCI_ROM(0x8086, 0x1033, "eepro100-1033", "Intel PRO/100 VM Network Connection"),
746 PCI_ROM(0x8086, 0x1034, "eepro100-1034", "Intel PRO/100 VM Network Connection"),
747 PCI_ROM(0x8086, 0x1035, "eepro100-1035", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
748 PCI_ROM(0x8086, 0x1036, "eepro100-1036", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
749 PCI_ROM(0x8086, 0x1037, "eepro100-1037", "Intel 82801CAM (ICH3) Chipset Ethernet Controller"),
750 PCI_ROM(0x8086, 0x1038, "id1038",        "Intel PRO/100 VM Network Connection"),
751 PCI_ROM(0x8086, 0x1039, "82562et",       "Intel PRO100 VE 82562ET"),
752 PCI_ROM(0x8086, 0x103a, "id103a",        "Intel Corporation 82559 InBusiness 10/100"),
753 PCI_ROM(0x8086, 0x103b, "82562etb",      "Intel PRO100 VE 82562ETB"),
754 PCI_ROM(0x8086, 0x103c, "eepro100-103c", "Intel PRO/100 VM Network Connection"),
755 PCI_ROM(0x8086, 0x103d, "eepro100-103d", "Intel PRO/100 VE Network Connection"),
756 PCI_ROM(0x8086, 0x103e, "eepro100-103e", "Intel PRO/100 VM Network Connection"),
757 PCI_ROM(0x8086, 0x1051, "prove",       "Intel PRO/100 VE Network Connection"),
758 PCI_ROM(0x8086, 0x1059, "82551qm",       "Intel PRO/100 M Mobile Connection"),
759 PCI_ROM(0x8086, 0x1209, "82559er",       "Intel EtherExpressPro100 82559ER"),
760 PCI_ROM(0x8086, 0x1227, "82865",         "Intel 82865 EtherExpress PRO/100A"),
761 PCI_ROM(0x8086, 0x1228, "82556",         "Intel 82556 EtherExpress PRO/100 Smart"),
762 PCI_ROM(0x8086, 0x1229, "eepro100",      "Intel EtherExpressPro100"),
763 PCI_ROM(0x8086, 0x2449, "82562em",       "Intel EtherExpressPro100 82562EM"),
764 PCI_ROM(0x8086, 0x2459, "82562-1",       "Intel 82562 based Fast Ethernet Connection"),
765 PCI_ROM(0x8086, 0x245d, "82562-2",       "Intel 82562 based Fast Ethernet Connection"),
766 PCI_ROM(0x8086, 0x1050, "82562ez",       "Intel 82562EZ Network Connection"),
767 PCI_ROM(0x8086, 0x1051, "eepro100-1051", "Intel 82801EB/ER (ICH5/ICH5R) Chipset Ethernet Controller"),
768 PCI_ROM(0x8086, 0x5200, "eepro100-5200", "Intel EtherExpress PRO/100 Intelligent Server"),
769 PCI_ROM(0x8086, 0x5201, "eepro100-5201", "Intel EtherExpress PRO/100 Intelligent Server"),
770 };
771
772 struct pci_driver epro100_driver __pci_driver = {
773         .ids = speedo_nics,
774         .id_count = (sizeof (speedo_nics) / sizeof (speedo_nics[0])),
775         .probe = speedo_probe,
776         .remove = speedo_remove,
777 };