2 natsemi.c - gPXE driver for the NatSemi DP8381x series.
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@etherboot.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
37 Support information and updates available at
38 http://www.scyld.com/network/netsemi.html
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 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
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>
78 /* Function Prototypes: */
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);
92 /** natsemi net device operations */
93 static struct net_device_operations natsemi_operations = {
95 .close = natsemi_close,
96 .transmit = natsemi_transmit,
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,
105 uint8_t mask = natsemi_ee_bits[bit_id];
108 eereg = inb ( np->ioaddr + EE_REG );
109 return ( eereg & mask );
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,
116 uint8_t mask = natsemi_ee_bits[bit_id];
119 eereg = inb ( np->ioaddr + EE_REG );
121 eereg |= ( data & mask );
122 outb ( eereg, np->ioaddr + EE_REG );
125 static struct bit_basher_operations natsemi_basher_ops = {
126 .read = natsemi_spi_read_bit,
127 .write = natsemi_spi_write_bit,
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.
134 static struct nvo_fragment natsemi_nvo_fragments[] = {
140 * Set up for EEPROM access
144 static void natsemi_init_eeprom ( struct natsemi_private *np ) {
146 /* Initialise three-wire bus
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 );
153 /*natsemi DP 83815 only supports at93c46
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;
166 * @ret rc Return status code
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];
178 /* Allocate net device
180 netdev = alloc_etherdev (sizeof (*np));
184 netdev_init (netdev, &natsemi_operations);
186 pci_set_drvdata (pci, netdev);
187 netdev->dev = &pci->dev;
188 memset (np, 0, sizeof (*np));
189 np->ioaddr = pci->ioaddr;
191 adjust_pci_device (pci);
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 );
198 /* decoding the MAC address read from NVS
199 * and save it in netdev->ll_addr
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;
208 if ((rc = register_netdev (netdev)) != 0)
209 goto err_register_netdev;
215 natsemi_reset (netdev);
225 static void natsemi_remove (struct pci_device *pci) {
226 struct net_device *netdev = pci_get_drvdata (pci);
228 unregister_netdev (netdev);
229 natsemi_reset (netdev);
238 * Issues a hardware reset and waits for the reset to complete.
240 static void natsemi_reset (struct net_device *netdev)
242 struct natsemi_private *np = netdev->priv;
250 natsemi_irq (netdev, 0);
253 * Resetting the chip causes some registers to be lost.
254 * Natsemi suggests NOT reloading the EEPROM while live, so instead
255 * we save the state that would have been loaded from EEPROM
256 * on a normal power-up (see the spec EEPROM map).
260 cfg = inl (np->ioaddr + ChipConfig) & CFG_RESET_SAVE;
263 wcsr = inl (np->ioaddr + WOLCmd) & WCSR_RESET_SAVE;
266 rfcr = readl (np->ioaddr + RxFilterAddr) & RFCR_RESET_SAVE;
269 for (i = 0; i < 3; i++) {
270 outl(i*2, np->ioaddr + RxFilterAddr);
271 pmatch[i] = inw(np->ioaddr + RxFilterData);
275 for (i = 0; i < 3; i++) {
276 outl(0xa+(i*2), np->ioaddr + RxFilterAddr);
277 sopass[i] = inw(np->ioaddr + RxFilterData);
280 /* now whack the chip */
281 outl(ChipReset, np->ioaddr + ChipCmd);
282 for (i=0; i<NATSEMI_HW_TIMEOUT; i++) {
283 if (! (inl (np->ioaddr + ChipCmd) & ChipReset))
287 if (i == NATSEMI_HW_TIMEOUT) {
288 DBG ("natsemi_reset: reset did not complete in %d usec.\n", i*5);
292 cfg |= inl(np->ioaddr + ChipConfig) & ~CFG_RESET_SAVE;
293 cfg &= ~(CfgExtPhy | CfgPhyDis);
294 outl (cfg, np->ioaddr + ChipConfig);
297 wcsr |= inl (np->ioaddr + WOLCmd) & ~WCSR_RESET_SAVE;
298 outl (wcsr, np->ioaddr + WOLCmd);
301 rfcr |= inl (np->ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE;
304 for (i = 0; i < 3; i++) {
305 outl (i*2, np->ioaddr + RxFilterAddr);
306 outw (pmatch[i], np->ioaddr + RxFilterData);
308 for (i = 0; i < 3; i++) {
309 outl (0xa+(i*2), np->ioaddr + RxFilterAddr);
310 outw (sopass[i], np->ioaddr + RxFilterData);
313 outl (rfcr, np->ioaddr + RxFilterAddr);
319 * @v netdev Net device
320 * @ret rc Return status code
322 static int natsemi_open (struct net_device *netdev)
324 struct natsemi_private *np = netdev->priv;
325 uint32_t tx_config, rx_config;
329 * The PME bit is initialized from the EEPROM contents.
330 * PCI cards probably have PME disabled, but motherboard
331 * implementations may have PME set to enable WakeOnLan.
332 * With PME set the chip will scan incoming packets but
333 * nothing will be written to memory.
335 outl (inl (np->ioaddr + ClkRun) & ~0x100, np->ioaddr + ClkRun);
337 /* Set MAC address in NIC
339 for (i = 0 ; i < ETH_ALEN ; i+=2) {
340 outl (i, np->ioaddr + RxFilterAddr);
341 outw (netdev->ll_addr[i] + (netdev->ll_addr[i + 1] << 8),
342 np->ioaddr + RxFilterData);
349 for (i = 0 ; i < TX_RING_SIZE ; i++) {
350 np->tx[i].link = virt_to_bus ((i + 1 < TX_RING_SIZE) ? &np->tx[i + 1] : &np->tx[0]);
351 np->tx[i].cmdsts = 0;
352 np->tx[i].bufptr = 0;
354 outl (virt_to_bus (&np->tx[0]),np->ioaddr + TxRingPtr);
356 DBG ("Natsemi Tx descriptor loaded with: %#08lx\n",
357 inl (np->ioaddr + TxRingPtr));
362 for (i = 0 ; i < NUM_RX_DESC ; i++) {
363 np->iobuf[i] = alloc_iob (RX_BUF_SIZE);
365 goto memory_alloc_err;
366 np->rx[i].link = virt_to_bus ((i + 1 < NUM_RX_DESC)
367 ? &np->rx[i + 1] : &np->rx[0]);
368 np->rx[i].cmdsts = RX_BUF_SIZE;
369 np->rx[i].bufptr = virt_to_bus (np->iobuf[i]->data);
370 DBG (" Address of iobuf [%d] = %p and iobuf->data = %p \n", i,
371 &np->iobuf[i], &np->iobuf[i]->data);
373 outl (virt_to_bus (&np->rx[0]), np->ioaddr + RxRingPtr);
375 DBG ("Natsemi Rx descriptor loaded with: %#08lx\n",
376 inl (np->ioaddr + RxRingPtr));
380 outl (RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys,
381 np->ioaddr + RxFilterAddr);
383 /* Initialize other registers.
384 * Configure the PCI bus bursts and FIFO thresholds.
385 * Configure for standard, in-spec Ethernet.
387 if (inl (np->ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */
388 DBG ("Full duplex\n");
389 tx_config = 0xD0801002 | 0xC0000000;
390 rx_config = 0x10000020 | 0x10000000;
392 DBG ("Half duplex\n");
393 tx_config = 0x10801002 & ~0xC0000000;
394 rx_config = 0x00000020 & ~0x10000000;
396 outl (tx_config, np->ioaddr + TxConfig);
397 outl (rx_config, np->ioaddr + RxConfig);
399 DBG ("Tx config register = %#08lx Rx config register = %#08lx\n",
400 inl (np->ioaddr + TxConfig),
401 inl (np->ioaddr + RxConfig));
403 /*Set the Interrupt Mask register
405 outl((RxOk|RxErr|TxOk|TxErr),np->ioaddr + IntrMask);
408 outl (RxOn, np->ioaddr + ChipCmd);
414 /* Frees any allocated buffers when memory
415 * for all buffers requested is not available
418 while (np->rx[i].cmdsts == RX_BUF_SIZE) {
419 free_iob (np->iobuf[i]);
428 * @v netdev Net device
430 static void natsemi_close (struct net_device *netdev)
432 struct natsemi_private *np = netdev->priv;
435 natsemi_reset (netdev);
437 for (i = 0; i < NUM_RX_DESC ; i++) {
438 free_iob (np->iobuf[i]);
445 * @v netdev Network device
446 * @v iobuf I/O buffer
447 * @ret rc Return status code
449 static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf)
451 struct natsemi_private *np = netdev->priv;
453 if (np->tx[np->tx_cur].cmdsts != 0) {
454 DBG ("TX overflow\n");
458 /* Used by netdev_tx_complete ()
460 np->tx_iobuf[np->tx_cur] = iobuf;
462 /* Pad and align packet has not been used because its not required
464 * iob_pad (iobuf, ETH_ZLEN);
465 * can be used to achieve it, if required
468 /* Add the packet to TX ring
470 np->tx[np->tx_cur].bufptr = virt_to_bus (iobuf->data);
471 np->tx[np->tx_cur].cmdsts = iob_len (iobuf) | OWN;
473 DBG ("TX id %d at %#08lx + %#08x\n", np->tx_cur,
474 virt_to_bus (&iobuf->data), iob_len (iobuf));
476 /* increment the circular buffer pointer to the next buffer location
478 np->tx_cur = (np->tx_cur + 1) % TX_RING_SIZE;
480 /*start the transmitter
482 outl (TxOn, np->ioaddr + ChipCmd);
488 * Poll for received packets
490 * @v netdev Network device
492 static void natsemi_poll (struct net_device *netdev)
494 struct natsemi_private *np = netdev->priv;
495 unsigned int tx_status;
496 unsigned int rx_status;
497 unsigned int intr_status;
499 struct io_buffer *rx_iob;
502 /* read the interrupt register
504 intr_status = inl (np->ioaddr + IntrStatus);
509 DBG ("natsemi_poll: intr_status = %#08x\n", intr_status);
511 /* Check status of transmitted packets
514 while (i != np->tx_cur) {
515 tx_status = np->tx[np->tx_dirty].cmdsts;
517 DBG ("tx_dirty = %d tx_cur=%d tx_status=%#08x\n",
518 np->tx_dirty, np->tx_cur, tx_status);
523 if (! (tx_status & DescPktOK)) {
524 netdev_tx_complete_err (netdev,np->tx_iobuf[np->tx_dirty],-EINVAL);
525 DBG ("Error transmitting packet, tx_status: %#08x\n",
528 netdev_tx_complete (netdev, np->tx_iobuf[np->tx_dirty]);
529 DBG ("Success transmitting packet\n");
532 np->tx[np->tx_dirty].cmdsts = 0;
533 np->tx_dirty = (np->tx_dirty + 1) % TX_RING_SIZE;
534 i = (i + 1) % TX_RING_SIZE;
537 /* Process received packets
539 rx_status = (unsigned int) np->rx[np->rx_cur].cmdsts;
540 while ((rx_status & OWN)) {
541 rx_len = (rx_status & DSIZE) - CRC_SIZE;
543 DBG ("Received packet, rx_curr = %d, rx_status = %#08x, rx_len = %d\n",
544 np->rx_cur, rx_status, rx_len);
546 if ((rx_status & (DescMore | DescPktOK | RxTooLong)) != DescPktOK) {
547 netdev_rx_err (netdev, NULL, -EINVAL);
549 DBG ("natsemi_poll: Corrupted packet received!"
550 " Status = %#08lx\n",
551 np->rx[np->rx_cur].cmdsts);
556 /* If unable allocate space for this packet,
557 * try again next poll
559 rx_iob = alloc_iob (rx_len);
562 memcpy (iob_put (rx_iob, rx_len),
563 np->iobuf[np->rx_cur]->data, rx_len);
564 /* Add this packet to the receive queue.
566 netdev_rx (netdev, rx_iob);
568 np->rx[np->rx_cur].cmdsts = RX_BUF_SIZE;
569 np->rx_cur = (np->rx_cur + 1) % NUM_RX_DESC;
570 rx_status = np->rx[np->rx_cur].cmdsts;
573 /* re-enable the potentially idle receive state machine
575 outl (RxOn, np->ioaddr + ChipCmd);
579 * Enable/disable interrupts
581 * @v netdev Network device
582 * @v enable Non-zero for enable, zero for disable
584 static void natsemi_irq (struct net_device *netdev, int enable)
586 struct natsemi_private *np = netdev->priv;
588 outl ((enable ? (RxOk | RxErr | TxOk|TxErr) : 0),
589 np->ioaddr + IntrMask);
590 outl ((enable ? 1 : 0), np->ioaddr + IntrEnable);
593 static struct pci_device_id natsemi_nics[] = {
594 PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
597 struct pci_driver natsemi_driver __pci_driver = {
599 .id_count = (sizeof (natsemi_nics) / sizeof (natsemi_nics[0])),
600 .probe = natsemi_probe,
601 .remove = natsemi_remove,