bfe1452baffad8baeb4e0fa3ee09b960480fe04d
[people/mcb30/gpxe.git] / src / drivers / net / natsemi.c
1 /* 
2    natsemi.c - gPXE driver for the NatSemi DP8381x series. 
3  
4    Based on:
5
6    natsemi.c: An Etherboot driver for the NatSemi DP8381x series.
7
8    Copyright (C) 2001 Entity Cyber, Inc.
9    
10    This development of this Etherboot driver was funded by 
11    
12       Sicom Systems: http://www.sicompos.com/
13    
14    Author: Marty Connor <mdc@etherboot.org>
15    Adapted from a Linux driver which was written by Donald Becker
16    
17    This software may be used and distributed according to the terms
18    of the GNU Public License (GPL), incorporated herein by reference.
19    
20    Original Copyright Notice:
21    
22    Written/copyright 1999-2001 by Donald Becker.
23    
24    This software may be used and distributed according to the terms of
25    the GNU General Public License (GPL), incorporated herein by reference.
26    Drivers based on or derived from this code fall under the GPL and must
27    retain the authorship, copyright and license notice.  This file is not
28    a complete program and may only be used when the entire operating
29    system is licensed under the GPL.  License for under other terms may be
30    available.  Contact the original author for details.
31    
32    The original author may be reached as becker@scyld.com, or at
33    Scyld Computing Corporation
34    410 Severn Ave., Suite 210
35    Annapolis MD 21403
36    
37    Support information and updates available at
38    http://www.scyld.com/network/netsemi.html
39    
40    References:
41    
42    http://www.scyld.com/expert/100mbps.html
43    http://www.scyld.com/expert/NWay.html
44    Datasheet is available from:
45    http://www.national.com/pf/DP/DP83815.html
46
47 */
48
49 /* Revision History */
50
51 /*
52   02 Jul 2007  Udayan Kumar      1.2 ported the driver from etherboot to gPXE API.
53                                      Fully rewritten,adapting the old driver.
54                                      Added a circular buffer for transmit and receive.
55                                      transmit routine will not wait for transmission to finish.
56                                      poll routine deals with it.
57   13 Dec 2003  Tim Legge         1.1 Enabled Multicast Support
58   29 May 2001  Marty Connor      1.0 Initial Release. Tested with Netgear FA311 and FA312 boards
59 */
60
61 #include <stdint.h>
62 #include <stdlib.h>
63 #include <stdio.h>
64 #include <gpxe/io.h>
65 #include <errno.h>
66 #include <byteswap.h>
67 #include <unistd.h>
68 #include <gpxe/pci.h>
69 #include <gpxe/if_ether.h>
70 #include <gpxe/ethernet.h>
71 #include <gpxe/iobuf.h>
72 #include <gpxe/netdevice.h>
73 #include <gpxe/spi_bit.h>
74 #include <gpxe/threewire.h>
75 #include <gpxe/nvo.h>
76 #include "natsemi.h"
77
78 /*  Function Prototypes: */
79  
80 static int natsemi_spi_read_bit ( struct bit_basher *, unsigned int );
81 static void natsemi_spi_write_bit ( struct bit_basher *,unsigned int, unsigned long ); 
82 static void natsemi_init_eeprom ( struct natsemi_private * ); 
83 static int natsemi_probe (struct pci_device *pci, const struct pci_device_id *id);
84 static void natsemi_reset (struct net_device *netdev);
85 static int natsemi_open (struct net_device *netdev);
86 static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf);
87 static void natsemi_poll (struct net_device *netdev);
88 static void natsemi_close (struct net_device *netdev);
89 static void natsemi_irq (struct net_device *netdev, int enable);
90 static void natsemi_remove (struct pci_device *pci);
91
92 /** natsemi net device operations */
93 static struct net_device_operations natsemi_operations = {
94         .open           = natsemi_open,
95         .close          = natsemi_close,
96         .transmit       = natsemi_transmit,
97         .poll           = natsemi_poll,
98         .irq            = natsemi_irq,
99 };
100
101 static int natsemi_spi_read_bit ( struct bit_basher *basher,
102                               unsigned int bit_id ) {
103         struct natsemi_private *np = container_of ( basher, struct natsemi_private,
104                                                  spibit.basher );
105         uint8_t mask = natsemi_ee_bits[bit_id];
106         uint8_t eereg;
107
108         eereg = inb ( np->ioaddr + EE_REG );
109         return ( eereg & mask );
110 }
111
112 static void natsemi_spi_write_bit ( struct bit_basher *basher,
113                                 unsigned int bit_id, unsigned long data ) {
114         struct natsemi_private *np = container_of ( basher, struct natsemi_private,
115                                                  spibit.basher );
116         uint8_t mask = natsemi_ee_bits[bit_id];
117         uint8_t eereg;
118
119         eereg = inb ( np->ioaddr + EE_REG );
120         eereg &= ~mask;
121         eereg |= ( data & mask );
122         outb ( eereg, np->ioaddr + EE_REG );
123 }
124
125 static struct bit_basher_operations natsemi_basher_ops = {
126         .read = natsemi_spi_read_bit,
127         .write = natsemi_spi_write_bit,
128 };
129
130 /* It looks that this portion of EEPROM can be used for 
131  * non-volatile stored options. Data sheet does not talk about this region.
132  * Currently it is not working. But with some efforts it can.
133  */
134 static struct nvo_fragment natsemi_nvo_fragments[] = {
135         { 0x0c, 0x68 },
136         { 0, 0 }
137 };
138
139 /*
140  * Set up for EEPROM access
141  *
142  * @v NAT               NATSEMI NIC
143  */
144 static void natsemi_init_eeprom ( struct natsemi_private *np ) {
145
146         /* Initialise three-wire bus 
147          */
148         np->spibit.basher.op = &natsemi_basher_ops;
149         np->spibit.bus.mode = SPI_MODE_THREEWIRE;
150         np->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
151         init_spi_bit_basher ( &np->spibit );
152
153         /*natsemi DP 83815 only supports at93c46
154          */
155         init_at93c46 ( &np->eeprom, 16 );
156         np->eeprom.bus = &np->spibit.bus;
157         np->nvo.nvs = &np->eeprom.nvs;
158         np->nvo.fragments = natsemi_nvo_fragments;
159 }
160
161 /**
162  * Probe PCI device
163  *
164  * @v pci       PCI device
165  * @v id        PCI ID
166  * @ret rc      Return status code
167  */
168 static int natsemi_probe (struct pci_device *pci,
169                        const struct pci_device_id *id __unused) {
170         struct net_device *netdev;
171         struct natsemi_private *np = NULL;
172         uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN];
173         uint8_t last=0,last1=0;
174         uint8_t prev_bytes[2];
175         int i;
176         int rc;
177
178         /* Allocate net device 
179          */
180         netdev = alloc_etherdev (sizeof (*np));
181         if (! netdev) 
182                 return -ENOMEM;
183
184         netdev_init (netdev, &natsemi_operations);
185         np = netdev->priv;
186         pci_set_drvdata (pci, netdev);
187         netdev->dev = &pci->dev;
188         memset (np, 0, sizeof (*np));
189         np->ioaddr = pci->ioaddr;
190
191         adjust_pci_device (pci);
192
193         natsemi_reset (netdev);
194         natsemi_init_eeprom ( np );
195         nvs_read ( &np->eeprom.nvs, EE_MAC-1, prev_bytes, 1 );
196         nvs_read ( &np->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
197
198         /* decoding the MAC address read from NVS 
199          * and save it in netdev->ll_addr
200          */
201         last = prev_bytes[1] >> 7;
202         for ( i = 0 ; i < ETH_ALEN ; i++ ) {
203                 last1 = ll_addr_encoded[i] >> 7;
204                 netdev->ll_addr[i] = ll_addr_encoded[i] << 1 | last;
205                 last = last1;
206         }
207
208         /* Mark as link up; we don't yet handle link state */
209         netdev_link_up ( netdev );
210
211         if ((rc = register_netdev (netdev)) != 0)
212                 goto err_register_netdev;
213
214         return 0;
215
216 err_register_netdev:
217
218         natsemi_reset (netdev);
219         netdev_put (netdev);
220         return rc;
221 }
222
223 /**
224  * Remove PCI device
225  *
226  * @v pci       PCI device
227  */
228 static void natsemi_remove (struct pci_device *pci) {
229         struct net_device *netdev = pci_get_drvdata (pci);
230  
231         unregister_netdev (netdev);
232         natsemi_reset (netdev);
233         netdev_nullify ( netdev );
234         netdev_put (netdev);
235 }
236
237 /**
238  * Reset NIC
239  *
240  * @v           NATSEMI NIC
241  *
242  * Issues a hardware reset and waits for the reset to complete.
243  */
244 static void natsemi_reset (struct net_device *netdev) 
245 {
246         struct natsemi_private *np = netdev->priv;
247         int i;
248         u32 cfg;
249         u32 wcsr;
250         u32 rfcr;
251         u16 pmatch[3];
252         u16 sopass[3];
253
254         natsemi_irq (netdev, 0);
255
256         /*
257          * Resetting the chip causes some registers to be lost.
258          * Natsemi suggests NOT reloading the EEPROM while live, so instead
259          * we save the state that would have been loaded from EEPROM
260          * on a normal power-up (see the spec EEPROM map).
261          */
262
263         /* CFG */
264         cfg = inl (np->ioaddr + ChipConfig) & CFG_RESET_SAVE;
265
266         /* WCSR */
267         wcsr = inl (np->ioaddr + WOLCmd) & WCSR_RESET_SAVE;
268
269         /* RFCR */
270         rfcr = readl (np->ioaddr + RxFilterAddr) & RFCR_RESET_SAVE;
271
272         /* PMATCH */
273         for (i = 0; i < 3; i++) {
274                 outl(i*2, np->ioaddr + RxFilterAddr);
275                 pmatch[i] = inw(np->ioaddr + RxFilterData);
276         }
277
278         /* SOPAS */
279         for (i = 0; i < 3; i++) {
280                 outl(0xa+(i*2), np->ioaddr + RxFilterAddr);
281                 sopass[i] = inw(np->ioaddr + RxFilterData);
282         }
283
284         /* now whack the chip */
285         outl(ChipReset, np->ioaddr + ChipCmd);
286         for (i=0; i<NATSEMI_HW_TIMEOUT; i++) {
287                 if (! (inl (np->ioaddr + ChipCmd) & ChipReset))
288                        break;
289                 udelay(5);
290         }
291         if (i == NATSEMI_HW_TIMEOUT) {
292                 DBG ("natsemi_reset: reset did not complete in %d usec.\n", i*5);
293         }
294
295         /* restore CFG */
296         cfg |= inl(np->ioaddr + ChipConfig) & ~CFG_RESET_SAVE;
297         cfg &= ~(CfgExtPhy | CfgPhyDis);
298         outl (cfg, np->ioaddr + ChipConfig);
299
300         /* restore WCSR */
301         wcsr |= inl (np->ioaddr + WOLCmd) & ~WCSR_RESET_SAVE;
302         outl (wcsr, np->ioaddr + WOLCmd);
303
304         /* read RFCR */
305         rfcr |= inl (np->ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE;
306
307         /* restore PMATCH */
308         for (i = 0; i < 3; i++) {
309                 outl (i*2, np->ioaddr + RxFilterAddr);
310                 outw (pmatch[i], np->ioaddr + RxFilterData);
311         }
312         for (i = 0; i < 3; i++) {
313                 outl (0xa+(i*2), np->ioaddr + RxFilterAddr);
314                 outw (sopass[i], np->ioaddr + RxFilterData);
315         }
316         /* restore RFCR */
317         outl (rfcr, np->ioaddr + RxFilterAddr);
318 }
319
320 /**
321  * Open NIC
322  *
323  * @v netdev            Net device
324  * @ret rc              Return status code
325  */
326 static int natsemi_open (struct net_device *netdev)
327 {
328         struct natsemi_private *np = netdev->priv;
329         uint32_t tx_config, rx_config;
330         int i;
331         
332         /* Disable PME:
333          * The PME bit is initialized from the EEPROM contents.
334          * PCI cards probably have PME disabled, but motherboard
335          * implementations may have PME set to enable WakeOnLan. 
336          * With PME set the chip will scan incoming packets but
337          * nothing will be written to memory. 
338          */
339         outl (inl (np->ioaddr + ClkRun) & ~0x100, np->ioaddr + ClkRun);
340
341         /* Set MAC address in NIC
342          */
343         for (i = 0 ; i < ETH_ALEN ; i+=2) {
344                 outl (i, np->ioaddr + RxFilterAddr);
345                 outw (netdev->ll_addr[i] + (netdev->ll_addr[i + 1] << 8),
346                        np->ioaddr + RxFilterData);
347         }
348
349         /* Setup Tx Ring 
350          */
351         np->tx_cur = 0;
352         np->tx_dirty = 0;
353         for (i = 0 ; i < TX_RING_SIZE ; i++) {
354                 np->tx[i].link   = virt_to_bus ((i + 1 < TX_RING_SIZE) ? &np->tx[i + 1] : &np->tx[0]);
355                 np->tx[i].cmdsts = 0;
356                 np->tx[i].bufptr = 0;
357         }
358         outl (virt_to_bus (&np->tx[0]),np->ioaddr + TxRingPtr);
359
360         DBG ("Natsemi Tx descriptor loaded with: %#08lx\n",
361              inl (np->ioaddr + TxRingPtr));
362
363         /* Setup RX ring
364          */
365         np->rx_cur = 0;
366         for (i = 0 ; i < NUM_RX_DESC ; i++) {
367                 np->iobuf[i] = alloc_iob (RX_BUF_SIZE);
368                 if (! np->iobuf[i])
369                         goto memory_alloc_err;
370                 np->rx[i].link   = virt_to_bus ((i + 1 < NUM_RX_DESC) 
371                                                 ? &np->rx[i + 1] : &np->rx[0]);
372                 np->rx[i].cmdsts = RX_BUF_SIZE;
373                 np->rx[i].bufptr = virt_to_bus (np->iobuf[i]->data);
374                 DBG (" Address of iobuf [%d] = %p and iobuf->data = %p \n", i, 
375                       &np->iobuf[i],  &np->iobuf[i]->data);
376         }
377         outl (virt_to_bus (&np->rx[0]), np->ioaddr + RxRingPtr);
378
379         DBG ("Natsemi Rx descriptor loaded with: %#08lx\n",
380               inl (np->ioaddr + RxRingPtr));            
381
382         /* Setup RX Filter 
383          */
384         outl (RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys,
385               np->ioaddr + RxFilterAddr);
386
387         /* Initialize other registers. 
388          * Configure the PCI bus bursts and FIFO thresholds. 
389          * Configure for standard, in-spec Ethernet. 
390          */
391         if (inl (np->ioaddr + ChipConfig) & 0x20000000) {       /* Full duplex */
392                 DBG ("Full duplex\n");
393                 tx_config = 0xD0801002 |  0xC0000000;
394                 rx_config = 0x10000020 |  0x10000000;
395         } else {
396                 DBG ("Half duplex\n");
397                 tx_config = 0x10801002 & ~0xC0000000;
398                 rx_config = 0x00000020 & ~0x10000000;
399         }
400         outl (tx_config, np->ioaddr + TxConfig);
401         outl (rx_config, np->ioaddr + RxConfig);
402
403         DBG ("Tx config register = %#08lx Rx config register = %#08lx\n", 
404                inl (np->ioaddr + TxConfig),
405                inl (np->ioaddr + RxConfig));
406
407         /*Set the Interrupt Mask register
408          */
409         outl((RxOk|RxErr|TxOk|TxErr),np->ioaddr + IntrMask);
410         /*start the receiver 
411          */
412         outl (RxOn, np->ioaddr + ChipCmd);
413         
414         return 0;
415                        
416 memory_alloc_err:
417
418         /* Frees any allocated buffers when memory
419          * for all buffers requested is not available
420          */
421         i = 0;
422         while (np->rx[i].cmdsts == RX_BUF_SIZE) {
423                 free_iob (np->iobuf[i]);
424                 i++;
425         }
426         return -ENOMEM; 
427 }
428
429 /**
430  * Close NIC
431  *
432  * @v netdev            Net device
433  */
434 static void natsemi_close (struct net_device *netdev) 
435 {
436         struct natsemi_private *np = netdev->priv;
437         int i;
438
439         natsemi_reset (netdev);
440
441         for (i = 0; i < NUM_RX_DESC ; i++) {
442                 free_iob (np->iobuf[i]);
443         }
444 }
445
446 /** 
447  * Transmit packet
448  *
449  * @v netdev    Network device
450  * @v iobuf     I/O buffer
451  * @ret rc      Return status code
452  */
453 static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf)
454 {
455         struct natsemi_private *np = netdev->priv;
456
457         if (np->tx[np->tx_cur].cmdsts != 0) {
458                 DBG ("TX overflow\n");
459                 return -ENOBUFS;
460         }
461
462         /* Used by netdev_tx_complete ()
463          */
464         np->tx_iobuf[np->tx_cur] = iobuf;
465
466         /* Pad and align packet has not been used because its not required 
467          * by the hardware.
468          *      iob_pad (iobuf, ETH_ZLEN); 
469          * can be used to achieve it, if required
470          */
471
472         /* Add the packet to TX ring
473          */
474         np->tx[np->tx_cur].bufptr = virt_to_bus (iobuf->data);
475         np->tx[np->tx_cur].cmdsts = iob_len (iobuf) | OWN;
476
477         DBG ("TX id %d at %#08lx + %#08zx\n", np->tx_cur,
478              virt_to_bus (&iobuf->data), iob_len (iobuf));
479
480         /* increment the circular buffer pointer to the next buffer location
481          */
482         np->tx_cur = (np->tx_cur + 1) % TX_RING_SIZE;
483
484         /*start the transmitter 
485          */
486         outl (TxOn, np->ioaddr + ChipCmd);
487
488         return 0;
489 }
490
491 /** 
492  * Poll for received packets
493  *
494  * @v netdev    Network device
495  */
496 static void natsemi_poll (struct net_device *netdev)
497 {
498         struct natsemi_private *np = netdev->priv;
499         unsigned int tx_status;
500         unsigned int rx_status;
501         unsigned int intr_status;
502         unsigned int rx_len;
503         struct io_buffer *rx_iob;
504         int i;
505         
506         /* read the interrupt register
507          */
508         intr_status = inl (np->ioaddr + IntrStatus);
509
510         if (!intr_status)
511                 goto end;
512
513         DBG ("natsemi_poll: intr_status = %#08x\n", intr_status);
514
515         /* Check status of transmitted packets
516          */
517         i = np->tx_dirty;
518         while (i != np->tx_cur) {
519                 tx_status = np->tx[np->tx_dirty].cmdsts;
520
521                 DBG ("tx_dirty = %d tx_cur=%d tx_status=%#08x\n",
522                      np->tx_dirty, np->tx_cur, tx_status);
523                 
524                 if (tx_status & OWN) 
525                         break;
526
527                 if (! (tx_status & DescPktOK)) {
528                         netdev_tx_complete_err (netdev,np->tx_iobuf[np->tx_dirty],-EINVAL);
529                         DBG ("Error transmitting packet, tx_status: %#08x\n",
530                              tx_status);
531                 } else {
532                         netdev_tx_complete (netdev, np->tx_iobuf[np->tx_dirty]);
533                         DBG ("Success transmitting packet\n");
534                 }
535
536                 np->tx[np->tx_dirty].cmdsts = 0;
537                 np->tx_dirty = (np->tx_dirty + 1) % TX_RING_SIZE;
538                 i = (i + 1) % TX_RING_SIZE;
539         }
540         
541         /* Process received packets 
542          */
543         rx_status = (unsigned int) np->rx[np->rx_cur].cmdsts; 
544         while ((rx_status & OWN)) {
545                 rx_len = (rx_status & DSIZE) - CRC_SIZE;
546
547                 DBG ("Received packet, rx_curr = %d, rx_status = %#08x, rx_len = %d\n",
548                      np->rx_cur, rx_status, rx_len);
549                 
550                 if ((rx_status & (DescMore | DescPktOK | RxTooLong)) != DescPktOK) {
551                         netdev_rx_err (netdev, NULL, -EINVAL);
552
553                         DBG ("natsemi_poll: Corrupted packet received!"
554                              " Status = %#08lx\n",
555                               np->rx[np->rx_cur].cmdsts);
556
557                 } else  {
558
559
560                         /* If unable allocate space for this packet,
561                          *  try again next poll
562                          */
563                         rx_iob = alloc_iob (rx_len);
564                         if (! rx_iob) 
565                                 goto end;
566                         memcpy (iob_put (rx_iob, rx_len), 
567                                 np->iobuf[np->rx_cur]->data, rx_len);
568                         /* Add this packet to the receive queue. 
569                          */
570                         netdev_rx (netdev, rx_iob);
571                 }
572                 np->rx[np->rx_cur].cmdsts = RX_BUF_SIZE;
573                 np->rx_cur = (np->rx_cur + 1) % NUM_RX_DESC;
574                 rx_status = np->rx[np->rx_cur].cmdsts; 
575         }
576 end:
577         /* re-enable the potentially idle receive state machine 
578          */
579         outl (RxOn, np->ioaddr + ChipCmd);      
580 }                               
581
582 /**
583  * Enable/disable interrupts
584  *
585  * @v netdev    Network device
586  * @v enable    Non-zero for enable, zero for disable
587  */
588 static void natsemi_irq (struct net_device *netdev, int enable)
589 {
590         struct natsemi_private *np = netdev->priv;
591
592         outl ((enable ? (RxOk | RxErr | TxOk|TxErr) : 0),
593               np->ioaddr + IntrMask); 
594         outl ((enable ? 1 : 0), np->ioaddr + IntrEnable);
595 }
596
597 static struct pci_device_id natsemi_nics[] = {
598         PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
599 };
600
601 struct pci_driver natsemi_driver __pci_driver = {
602         .ids = natsemi_nics,
603         .id_count = (sizeof (natsemi_nics) / sizeof (natsemi_nics[0])),
604         .probe = natsemi_probe,
605         .remove = natsemi_remove,
606 };