Replace natsemi driver with Indolent's updated one that uses the gPXE API
[gpxe.git] / src / drivers / net / natsemi.c
blobc4aa2398ad2289ea1b33db500e53dd1cb10a4abc
1 /* natsemi.c - gPXE driver for the NatSemi DP8381x series. */
3 /*
6 natsemi.c: An Etherboot driver for the NatSemi DP8381x series.
8 Copyright (C) 2001 Entity Cyber, Inc.
10 This development of this Etherboot driver was funded by
12 Sicom Systems: http://www.sicompos.com/
14 Author: Marty Connor (mdc@thinguin.org)
15 Adapted from a Linux driver which was written by Donald Becker
17 This software may be used and distributed according to the terms
18 of the GNU Public License (GPL), incorporated herein by reference.
20 Original Copyright Notice:
22 Written/copyright 1999-2001 by Donald Becker.
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.
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
37 Support information and updates available at
38 http://www.scyld.com/network/netsemi.html
40 References:
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
49 /* Revision History */
52 02 JUL 2007 Udayan Kumar 1.2 ported the driver from etherboot to gPXE API
53 Added a circular buffer for transmit and receive.
54 transmit routine will not wait for transmission to finish
55 poll routine deals with it.
57 13 Dec 2003 timlegge 1.1 Enabled Multicast Support
58 29 May 2001 mdc 1.0
59 Initial Release. Tested with Netgear FA311 and FA312 boards
65 #include <stdint.h>
66 #include <pic8259.h>
67 #include <stdlib.h>
68 #include <stdio.h>
69 #include <io.h>
70 #include <errno.h>
71 #include <timer.h>
72 #include <byteswap.h>
73 #include <gpxe/pci.h>
74 #include <gpxe/if_ether.h>
75 #include <gpxe/ethernet.h>
76 #include <gpxe/iobuf.h>
77 #include <gpxe/netdevice.h>
78 #include <gpxe/spi_bit.h>
79 #include <gpxe/threewire.h>
80 #include <gpxe/nvo.h>
82 #define TX_RING_SIZE 4
83 #define NUM_RX_DESC 4
84 #define RX_BUF_SIZE 1536
85 #define OWN 0x80000000
86 #define DSIZE 0x00000FFF
87 #define CRC_SIZE 4
89 struct natsemi_tx {
90 uint32_t link;
91 uint32_t cmdsts;
92 uint32_t bufptr;
95 struct natsemi_rx {
96 uint32_t link;
97 uint32_t cmdsts;
98 uint32_t bufptr;
101 struct natsemi_nic {
102 unsigned short ioaddr;
103 unsigned short tx_cur;
104 unsigned short tx_dirty;
105 unsigned short rx_cur;
106 struct natsemi_tx tx[TX_RING_SIZE];
107 struct natsemi_rx rx[NUM_RX_DESC];
108 /* need to add iobuf as we cannot free iobuf->data in close without this
109 * alternatively substracting sizeof(head) and sizeof(list_head) can also
110 * give the same.*/
111 struct io_buffer *iobuf[NUM_RX_DESC];
112 /*netdev_tx_complete needs pointer to the iobuf of the data so as to free
113 it from the memory.*/
114 struct io_buffer *tx_iobuf[TX_RING_SIZE];
115 struct spi_bit_basher spibit;
116 struct spi_device eeprom;
117 struct nvo_block nvo;
121 /* NATSEMI: Offsets to the device registers.
122 Unlike software-only systems, device drivers interact with complex hardware.
123 It's not useful to define symbolic names for every register bit in the
124 device.
126 enum register_offsets {
127 ChipCmd = 0x00,
128 ChipConfig = 0x04,
129 EECtrl = 0x08,
130 PCIBusCfg = 0x0C,
131 IntrStatus = 0x10,
132 IntrMask = 0x14,
133 IntrEnable = 0x18,
134 TxRingPtr = 0x20,
135 TxConfig = 0x24,
136 RxRingPtr = 0x30,
137 RxConfig = 0x34,
138 ClkRun = 0x3C,
139 WOLCmd = 0x40,
140 PauseCmd = 0x44,
141 RxFilterAddr = 0x48,
142 RxFilterData = 0x4C,
143 BootRomAddr = 0x50,
144 BootRomData = 0x54,
145 SiliconRev = 0x58,
146 StatsCtrl = 0x5C,
147 StatsData = 0x60,
148 RxPktErrs = 0x60,
149 RxMissed = 0x68,
150 RxCRCErrs = 0x64,
151 PCIPM = 0x44,
152 PhyStatus = 0xC0,
153 MIntrCtrl = 0xC4,
154 MIntrStatus = 0xC8,
156 /* These are from the spec, around page 78... on a separate table. */
157 PGSEL = 0xCC,
158 PMDCSR = 0xE4,
159 TSTDAT = 0xFC,
160 DSPCFG = 0xF4,
161 SDCFG = 0x8C,
162 BasicControl = 0x80,
163 BasicStatus = 0x84
170 /* Bit in ChipCmd. */
171 enum ChipCmdBits {
172 ChipReset = 0x100,
173 RxReset = 0x20,
174 TxReset = 0x10,
175 RxOff = 0x08,
176 RxOn = 0x04,
177 TxOff = 0x02,
178 TxOn = 0x01
182 /* Bits in the RxMode register. */
183 enum rx_mode_bits {
184 AcceptErr = 0x20,
185 AcceptRunt = 0x10,
186 AcceptBroadcast = 0xC0000000,
187 AcceptMulticast = 0x00200000,
188 AcceptAllMulticast = 0x20000000,
189 AcceptAllPhys = 0x10000000,
190 AcceptMyPhys = 0x08000000,
191 RxFilterEnable = 0x80000000
194 /* Bits in network_desc.status */
195 enum desc_status_bits {
196 DescOwn = 0x80000000,
197 DescMore = 0x40000000,
198 DescIntr = 0x20000000,
199 DescNoCRC = 0x10000000,
200 DescPktOK = 0x08000000,
201 RxTooLong = 0x00400000
204 /*Bits in Interrupt Mask register */
206 enum Intr_mask_register_bits {
207 RxOk = 0x001,
208 RxErr = 0x004,
209 TxOk = 0x040,
210 TxErr = 0x100
214 /* EEPROM access , values are devices specific*/
215 #define EE_CS 0x08 /* EEPROM chip select */
216 #define EE_SK 0x04 /* EEPROM shift clock */
217 #define EE_DI 0x01 /* Data in */
218 #define EE_DO 0x02 /* Data out */
220 /* Offsets within EEPROM (these are word offsets) */
221 #define EE_MAC 7
222 #define EE_REG EECtrl
223 static uint32_t SavedClkRun;
226 static const uint8_t nat_ee_bits[] = {
227 [SPI_BIT_SCLK] = EE_SK,
228 [SPI_BIT_MOSI] = EE_DI,
229 [SPI_BIT_MISO] = EE_DO,
230 [SPI_BIT_SS(0)] = EE_CS,
233 static int nat_spi_read_bit ( struct bit_basher *basher,
234 unsigned int bit_id ) {
235 struct natsemi_nic *nat = container_of ( basher, struct natsemi_nic,
236 spibit.basher );
237 uint8_t mask = nat_ee_bits[bit_id];
238 uint8_t eereg;
240 eereg = inb ( nat->ioaddr + EE_REG);
241 return ( eereg & mask );
244 static void nat_spi_write_bit ( struct bit_basher *basher,
245 unsigned int bit_id, unsigned long data ) {
246 struct natsemi_nic *nat = container_of ( basher, struct natsemi_nic,
247 spibit.basher );
248 uint8_t mask = nat_ee_bits[bit_id];
249 uint8_t eereg;
251 eereg = inb ( nat->ioaddr + EE_REG );
252 eereg &= ~mask;
253 eereg |= ( data & mask );
254 outb ( eereg, nat->ioaddr + EE_REG);
257 static struct bit_basher_operations nat_basher_ops = {
258 .read = nat_spi_read_bit,
259 .write = nat_spi_write_bit,
261 /** Portion of EEPROM available for non-volatile stored options
263 * We use offset 0x40 (i.e. address 0x20), length 0x40. This block is
264 * marked as VPD in the rtl8139 datasheets, so we use it only if we
265 * detect that the card is not supporting VPD.
267 static struct nvo_fragment nat_nvo_fragments[] = {
268 { 0x0c, 0x40 },
269 { 0, 0 }
273 * Set up for EEPROM access
275 * @v NAT NATSEMI NIC
277 void nat_init_eeprom ( struct natsemi_nic *nat ) {
279 // Initialise three-wire bus
280 nat->spibit.basher.op = &nat_basher_ops;
281 nat->spibit.bus.mode = SPI_MODE_THREEWIRE;
282 nat->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
283 init_spi_bit_basher ( &nat->spibit );
285 /*natsemi DP 83815 only supports at93c46 */
286 init_at93c46 ( &nat->eeprom, 16 );
287 nat->eeprom.bus = &nat->spibit.bus;
289 nat->nvo.nvs = &nat->eeprom.nvs;
290 nat->nvo.fragments = nat_nvo_fragments;
294 * Reset NIC
296 * @v NATSEMI NIC
298 * Issues a hardware reset and waits for the reset to complete.
300 static void nat_reset ( struct natsemi_nic *nat ) {
302 int i;
303 /* Reset chip */
304 outl ( ChipReset, nat->ioaddr + ChipCmd );
305 mdelay ( 10 );
306 nat->tx_dirty=0;
307 nat->tx_cur=0;
308 for(i=0;i<TX_RING_SIZE;i++)
310 nat->tx[i].link=0;
311 nat->tx[i].cmdsts=0;
312 nat->tx[i].bufptr=0;
314 nat->rx_cur = 0;
315 outl(virt_to_bus(&nat->tx[0]),nat->ioaddr+TxRingPtr);
316 outl(virt_to_bus(&nat->rx[0]), nat->ioaddr + RxRingPtr);
318 outl(TxOff|RxOff, nat->ioaddr + ChipCmd);
320 /* Restore PME enable bit */
321 outl(SavedClkRun, nat->ioaddr + ClkRun);
325 * Open NIC
327 * @v netdev Net device
328 * @ret rc Return status code
330 static int nat_open ( struct net_device *netdev ) {
331 struct natsemi_nic *nat = netdev->priv;
332 int i;
333 uint32_t tx_config,rx_config;
335 /* Disable PME:
336 * The PME bit is initialized from the EEPROM contents.
337 * PCI cards probably have PME disabled, but motherboard
338 * implementations may have PME set to enable WakeOnLan.
339 * With PME set the chip will scan incoming packets but
340 * nothing will be written to memory. */
341 SavedClkRun = inl(nat->ioaddr + ClkRun);
342 outl(SavedClkRun & ~0x100, nat->ioaddr + ClkRun);
347 uint8_t last=0;
348 uint8_t last1=0;
349 for ( i = 0 ; i < ETH_ALEN ; i+=2 )
351 outl(i,nat->ioaddr+RxFilterAddr);
352 last1=netdev->ll_addr[i]>>7;
353 netdev->ll_addr[i]=netdev->ll_addr[i]<<1|last;
354 last=(netdev->ll_addr[i+1]>>7);
355 netdev->ll_addr[i+1]=(netdev->ll_addr[i+1]<<1)+last1;
357 outw ( netdev->ll_addr[i] + (netdev->ll_addr[i+1]<<8), nat->ioaddr +RxFilterData);
362 /*Set up the Tx Ring */
363 nat->tx_cur=0;
364 nat->tx_dirty=0;
365 for (i=0;i<TX_RING_SIZE;i++)
367 nat->tx[i].link = virt_to_bus((i+1 < TX_RING_SIZE) ? &nat->tx[i+1] : &nat->tx[0]);
368 nat->tx[i].cmdsts = 0;
369 nat->tx[i].bufptr = 0;
376 /* Set up RX ring */
377 nat->rx_cur=0;
378 for (i=0;i<NUM_RX_DESC;i++)
381 nat->iobuf[i] = alloc_iob ( RX_BUF_SIZE );
382 if (!nat->iobuf[i])
383 return -ENOMEM;
384 nat->rx[i].link = virt_to_bus((i+1 < NUM_RX_DESC) ? &nat->rx[i+1] : &nat->rx[0]);
385 nat->rx[i].cmdsts = (uint32_t) RX_BUF_SIZE;
386 nat->rx[i].bufptr = virt_to_bus(nat->iobuf[i]->data);
390 /* load Receive Descriptor Register */
391 outl(virt_to_bus(&nat->rx[0]), nat->ioaddr + RxRingPtr);
392 DBG("Natsemi Rx descriptor loaded with: %X\n",(unsigned int)inl(nat->ioaddr+RxRingPtr));
394 /* setup Tx ring */
395 outl(virt_to_bus(&nat->tx[0]),nat->ioaddr+TxRingPtr);
396 DBG("Natsemi Tx descriptor loaded with: %X\n",(unsigned int)inl(nat->ioaddr+TxRingPtr));
398 /* Enables RX */
399 outl(RxFilterEnable|AcceptBroadcast|AcceptAllMulticast|AcceptMyPhys, nat->ioaddr+RxFilterAddr);
401 /* Initialize other registers. */
402 /* Configure the PCI bus bursts and FIFO thresholds. */
403 /* Configure for standard, in-spec Ethernet. */
404 if (inl(nat->ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */
405 tx_config = 0xD0801002;
406 rx_config = 0x10000020;
407 } else {
408 tx_config = 0x10801002;
409 rx_config = 0x0020;
411 outl(tx_config, nat->ioaddr + TxConfig);
412 outl(rx_config, nat->ioaddr + RxConfig);
416 /*start the receiver */
417 outl(RxOn, nat->ioaddr + ChipCmd);
419 /*enable interrupts*/
420 outl((RxOk|RxErr|TxOk|TxErr),nat->ioaddr + IntrMask);
421 outl(1,nat->ioaddr +IntrEnable);
426 return 0;
430 * Close NIC
432 * @v netdev Net device
434 static void nat_close ( struct net_device *netdev ) {
435 struct natsemi_nic *nat = netdev->priv;
436 int i;
439 /* Reset the hardware to disable everything in one go */
440 nat_reset ( nat );
442 /* Free RX ring */
443 for (i=0;i<NUM_RX_DESC;i++)
446 free_iob( nat->iobuf[i] );
448 /* disable interrupts */
449 outl(0,nat->ioaddr + IntrMask) ;
452 /**
453 * Transmit packet
455 * @v netdev Network device
456 * @v iobuf I/O buffer
457 * @ret rc Return status code
459 static int nat_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
460 struct natsemi_nic *nat = netdev->priv;
462 /* check for space in TX ring */
464 if (nat->tx[nat->tx_cur].cmdsts !=0)
466 printf ( "TX overflow\n" );
467 return -ENOBUFS;
470 /* to be used in netdev_tx_complete*/
471 nat->tx_iobuf[nat->tx_cur]=iobuf;
473 /* Pad and align packet */
474 iob_pad ( iobuf, ETH_ZLEN );
476 /* Add to TX ring */
477 DBG ( "TX id %d at %lx+%x\n", nat->tx_cur,
478 virt_to_bus ( &iobuf->data ), iob_len ( iobuf ) );
480 nat->tx[nat->tx_cur].bufptr = virt_to_bus(iobuf->data);
481 nat->tx[nat->tx_cur].cmdsts= (uint32_t) iob_len(iobuf)|OWN;
484 nat->tx_cur=(nat->tx_cur+1) % TX_RING_SIZE;
486 /*start the transmitter */
487 outl(TxOn, nat->ioaddr + ChipCmd);
489 return 0;
492 /**
493 * Poll for received packets
495 * @v netdev Network device
496 * @v rx_quota Maximum number of packets to receive
498 static void nat_poll ( struct net_device *netdev, unsigned int rx_quota ) {
499 struct natsemi_nic *nat = netdev->priv;
500 unsigned int status;
501 unsigned int rx_status;
502 unsigned int intr_status;
503 unsigned int rx_len;
504 struct io_buffer *rx_iob;
505 int i;
507 //outl(1,nat->ioaddr +IntrEnable);
508 /* read the interrupt register */
509 intr_status=inl(nat->ioaddr+IntrStatus);
510 if(!intr_status)
511 goto end;
513 /* check the status of packets given to card for transmission */
514 DBG("Intr status %X\n",intr_status);
517 i=nat->tx_dirty;
518 while(i!=nat->tx_cur)
520 status=nat->tx[nat->tx_dirty].cmdsts;
521 DBG("value of tx_dirty = %d tx_cur=%d status=%X\n",
522 nat->tx_dirty,nat->tx_cur,status);
524 /* check if current packet has been transmitted or not */
525 if(status & OWN)
526 break;
527 /* Check if any errors in transmission */
528 if (! (status & DescPktOK))
530 printf("Error in sending Packet status:%X\n",
531 (unsigned int)status);
533 else
535 DBG("Success in transmitting Packet with data\n");
536 // DBG_HD(&nat->tx[nat->tx_dirty].bufptr,130);
538 netdev_tx_complete(netdev,nat->tx_iobuf[nat->tx_dirty]);
539 /* setting cmdsts zero, indicating that it can be reused */
540 nat->tx[nat->tx_dirty].cmdsts=0;
541 nat->tx_dirty=(nat->tx_dirty +1) % TX_RING_SIZE;
542 i=(i+1) % TX_RING_SIZE;
547 rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts;
548 /* Handle received packets */
549 while (rx_quota && (rx_status & OWN))
551 rx_len= (rx_status & DSIZE) - CRC_SIZE;
553 /*check for the corrupt packet */
554 if((rx_status & (DescMore|DescPktOK|RxTooLong)) != DescPktOK)
556 printf("natsemi_poll: Corrupted packet received, "
557 "buffer status = %X ^ %X \n",rx_status,
558 (unsigned int) nat->rx[nat->rx_cur].cmdsts);
560 else
562 rx_iob = alloc_iob(rx_len);
563 if(!rx_iob)
564 /* leave packet for next call to poll*/
565 goto end;
566 memcpy(iob_put(rx_iob,rx_len),
567 bus_to_virt(nat->rx[nat->rx_cur].bufptr),rx_len);
569 DBG("received packet\n");
570 /* add to the receive queue. */
571 netdev_rx(netdev,rx_iob);
572 rx_quota--;
574 nat->rx[nat->rx_cur].cmdsts = RX_BUF_SIZE;
575 nat->rx_cur=(nat->rx_cur+1) % NUM_RX_DESC;
576 rx_status=(unsigned int)nat->rx[nat->rx_cur].cmdsts;
579 end:
581 /* re-enable the potentially idle receive state machine */
582 outl(RxOn, nat->ioaddr + ChipCmd);
583 // outl(1,nat->ioaddr +IntrEnable);
592 * Probe PCI device
594 * @v pci PCI device
595 * @v id PCI ID
596 * @ret rc Return status code
598 static int nat_probe ( struct pci_device *pci,
599 const struct pci_device_id *id __unused ) {
600 struct net_device *netdev;
601 struct natsemi_nic *nat = NULL;
602 int registered_netdev = 0;
603 int rc;
604 uint32_t advertising;
606 /* Fix up PCI device */
607 adjust_pci_device ( pci );
609 /* Allocate net device */
610 netdev = alloc_etherdev ( sizeof ( *nat ) );
611 if ( ! netdev ) {
612 rc = -ENOMEM;
613 goto err;
615 nat = netdev->priv;
616 pci_set_drvdata ( pci, netdev );
617 netdev->dev = &pci->dev;
618 memset ( nat, 0, sizeof ( *nat ) );
619 nat->ioaddr = pci->ioaddr;
621 /* getting the IRQ vector */
622 unsigned long vector_phys = IRQ_INT ( pci->irq ) * 4;
623 DBG_HDA ( vector_phys, phys_to_virt ( vector_phys ), 4 );
624 DBG_HD ( phys_to_virt ( 0xfaea5 ), 64 );
625 DBG (" PIC state %X\n", irq_enabled(pci->irq));
626 DBG (" IRQ Number %X\n",pci->irq);
630 /* Reset the NIC, set up EEPROM access and read MAC address */
631 nat_reset ( nat );
632 nat_init_eeprom ( nat );
633 nvs_read ( &nat->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN );
634 uint8_t eetest[128];
635 nvs_read ( &nat->eeprom.nvs, 0, eetest,128 );
638 /* mdio routine of etherboot-5.4.0 natsemi driver has been removed and
639 * statement to read from MII transceiver control section is used directly
642 advertising = inl(nat->ioaddr + 0x80 + (4<<2)) & 0xffff;
644 uint32_t chip_config = inl(nat->ioaddr + ChipConfig);
645 DBG("%s: Transceiver default autoneg. %s 10 %s %s duplex.\n",
646 pci->driver_name,
647 chip_config & 0x2000 ? "enabled, advertise" : "disabled, force",
648 chip_config & 0x4000 ? "0" : "",
649 chip_config & 0x8000 ? "full" : "half");
651 DBG("%s: Transceiver status %hX advertising %hX\n",pci->driver_name, (int)inl(nat->ioaddr + 0x84),(unsigned int) advertising);
657 /* Point to NIC specific routines */
658 netdev->open = nat_open;
659 netdev->close = nat_close;
660 netdev->transmit = nat_transmit;
661 netdev->poll = nat_poll;
663 /* Register network device */
664 if ( ( rc = register_netdev ( netdev ) ) != 0 )
665 goto err;
666 registered_netdev = 1;
668 /* Register non-volatile storagei
669 * uncomment lines below in final version*/
671 if ( nat->nvo.nvs ) {
672 if ( ( rc = nvo_register ( &nat->nvo ) ) != 0 )
673 goto err;
677 return 0;
679 err:
680 /* Disable NIC */
681 if ( nat )
682 nat_reset ( nat );
683 if ( registered_netdev )
684 unregister_netdev ( netdev );
685 /* Free net device */
686 netdev_put ( netdev );
687 return rc;
691 * Remove PCI device
693 * @v pci PCI device
695 static void nat_remove ( struct pci_device *pci ) {
696 struct net_device *netdev = pci_get_drvdata ( pci );
697 struct natsemi_nic *nat = netdev->priv;
699 if ( nat->nvo.nvs )
700 nvo_unregister ( &nat->nvo );
702 unregister_netdev ( netdev );
703 nat_reset ( nat );
704 netdev_put ( netdev );
707 static struct pci_device_id natsemi_nics[] = {
708 PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
712 struct pci_driver natsemi_driver __pci_driver = {
713 .ids = natsemi_nics,
714 .id_count = ( sizeof ( natsemi_nics ) / sizeof ( natsemi_nics[0] ) ),
715 .probe = nat_probe,
716 .remove = nat_remove,