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 SavedClkRun = inl (np->ioaddr + ClkRun);
336 outl (SavedClkRun & ~0x100, np->ioaddr + ClkRun);
338 /* Set MAC address in NIC
340 for (i = 0 ; i < ETH_ALEN ; i+=2) {
341 outl (i, np->ioaddr + RxFilterAddr);
342 outw (netdev->ll_addr[i] + (netdev->ll_addr[i + 1] << 8),
343 np->ioaddr + RxFilterData);
350 for (i = 0 ; i < TX_RING_SIZE ; i++) {
351 np->tx[i].link = virt_to_bus ((i + 1 < TX_RING_SIZE) ? &np->tx[i + 1] : &np->tx[0]);
352 np->tx[i].cmdsts = 0;
353 np->tx[i].bufptr = 0;
355 outl (virt_to_bus (&np->tx[0]),np->ioaddr + TxRingPtr);
357 DBG ("Natsemi Tx descriptor loaded with: %#08lx\n",
358 inl (np->ioaddr + TxRingPtr));
363 for (i = 0 ; i < NUM_RX_DESC ; i++) {
364 np->iobuf[i] = alloc_iob (RX_BUF_SIZE);
366 goto memory_alloc_err;
367 np->rx[i].link = virt_to_bus ((i + 1 < NUM_RX_DESC)
368 ? &np->rx[i + 1] : &np->rx[0]);
369 np->rx[i].cmdsts = RX_BUF_SIZE;
370 np->rx[i].bufptr = virt_to_bus (np->iobuf[i]->data);
371 DBG (" Address of iobuf [%d] = %p and iobuf->data = %p \n", i,
372 &np->iobuf[i], &np->iobuf[i]->data);
374 outl (virt_to_bus (&np->rx[0]), np->ioaddr + RxRingPtr);
376 DBG ("Natsemi Rx descriptor loaded with: %#08lx\n",
377 inl (np->ioaddr + RxRingPtr));
381 outl (RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys,
382 np->ioaddr + RxFilterAddr);
384 /* Initialize other registers.
385 * Configure the PCI bus bursts and FIFO thresholds.
386 * Configure for standard, in-spec Ethernet.
388 if (inl (np->ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */
389 DBG ("Full duplex\n");
390 tx_config = 0xD0801002 | 0xC0000000;
391 rx_config = 0x10000020 | 0x10000000;
393 DBG ("Half duplex\n");
394 tx_config = 0x10801002 & ~0xC0000000;
395 rx_config = 0x00000020 & ~0x10000000;
397 outl (tx_config, np->ioaddr + TxConfig);
398 outl (rx_config, np->ioaddr + RxConfig);
400 DBG ("Tx config register = %#08lx Rx config register = %#08lx\n",
401 inl (np->ioaddr + TxConfig),
402 inl (np->ioaddr + RxConfig));
404 /*Set the Interrupt Mask register
406 outl((RxOk|RxErr|TxOk|TxErr),np->ioaddr + IntrMask);
409 outl (RxOn, np->ioaddr + ChipCmd);
415 /* Frees any allocated buffers when memory
416 * for all buffers requested is not available
419 while (np->rx[i].cmdsts == RX_BUF_SIZE) {
420 free_iob (np->iobuf[i]);
429 * @v netdev Net device
431 static void natsemi_close (struct net_device *netdev)
433 struct natsemi_private *np = netdev->priv;
436 natsemi_reset (netdev);
438 for (i = 0; i < NUM_RX_DESC ; i++) {
439 free_iob (np->iobuf[i]);
446 * @v netdev Network device
447 * @v iobuf I/O buffer
448 * @ret rc Return status code
450 static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf)
452 struct natsemi_private *np = netdev->priv;
454 if (np->tx[np->tx_cur].cmdsts != 0) {
455 DBG ("TX overflow\n");
459 /* Used by netdev_tx_complete ()
461 np->tx_iobuf[np->tx_cur] = iobuf;
463 /* Pad and align packet has not been used because its not required
465 * iob_pad (iobuf, ETH_ZLEN);
466 * can be used to achieve it, if required
469 /* Add the packet to TX ring
471 np->tx[np->tx_cur].bufptr = virt_to_bus (iobuf->data);
472 np->tx[np->tx_cur].cmdsts = iob_len (iobuf) | OWN;
474 DBG ("TX id %d at %#08lx + %#08x\n", np->tx_cur,
475 virt_to_bus (&iobuf->data), iob_len (iobuf));
477 /* increment the circular buffer pointer to the next buffer location
479 np->tx_cur = (np->tx_cur + 1) % TX_RING_SIZE;
481 /*start the transmitter
483 outl (TxOn, np->ioaddr + ChipCmd);
489 * Poll for received packets
491 * @v netdev Network device
493 static void natsemi_poll (struct net_device *netdev)
495 struct natsemi_private *np = netdev->priv;
496 unsigned int tx_status;
497 unsigned int rx_status;
498 unsigned int intr_status;
500 struct io_buffer *rx_iob;
503 /* read the interrupt register
505 intr_status = inl (np->ioaddr + IntrStatus);
510 DBG ("natsemi_poll: intr_status = %#08x\n", intr_status);
512 /* Check status of transmitted packets
515 while (i != np->tx_cur) {
516 tx_status = np->tx[np->tx_dirty].cmdsts;
518 DBG ("tx_dirty = %d tx_cur=%d tx_status=%#08x\n",
519 np->tx_dirty, np->tx_cur, tx_status);
524 if (! (tx_status & DescPktOK)) {
525 netdev_tx_complete_err (netdev,np->tx_iobuf[np->tx_dirty],-EINVAL);
526 DBG ("Error transmitting packet, tx_status: %#08x\n",
529 netdev_tx_complete (netdev, np->tx_iobuf[np->tx_dirty]);
530 DBG ("Success transmitting packet\n");
533 np->tx[np->tx_dirty].cmdsts = 0;
534 np->tx_dirty = (np->tx_dirty + 1) % TX_RING_SIZE;
535 i = (i + 1) % TX_RING_SIZE;
538 /* Process received packets
540 rx_status = (unsigned int) np->rx[np->rx_cur].cmdsts;
541 while ((rx_status & OWN)) {
542 rx_len = (rx_status & DSIZE) - CRC_SIZE;
544 DBG ("Received packet, rx_curr = %d, rx_status = %#08x, rx_len = %d\n",
545 np->rx_cur, rx_status, rx_len);
547 if ((rx_status & (DescMore | DescPktOK | RxTooLong)) != DescPktOK) {
548 netdev_rx_err (netdev, NULL, -EINVAL);
550 DBG ("natsemi_poll: Corrupted packet received!"
551 " Status = %#08lx\n",
552 np->rx[np->rx_cur].cmdsts);
557 /* If unable allocate space for this packet,
558 * try again next poll
560 rx_iob = alloc_iob (rx_len);
563 memcpy (iob_put (rx_iob, rx_len),
564 np->iobuf[np->rx_cur]->data, rx_len);
565 /* Add this packet to the receive queue.
567 netdev_rx (netdev, rx_iob);
569 np->rx[np->rx_cur].cmdsts = RX_BUF_SIZE;
570 np->rx_cur = (np->rx_cur + 1) % NUM_RX_DESC;
571 rx_status = np->rx[np->rx_cur].cmdsts;
574 /* re-enable the potentially idle receive state machine
576 outl (RxOn, np->ioaddr + ChipCmd);
580 * Enable/disable interrupts
582 * @v netdev Network device
583 * @v enable Non-zero for enable, zero for disable
585 static void natsemi_irq (struct net_device *netdev, int enable)
587 struct natsemi_private *np = netdev->priv;
589 outl ((enable ? (RxOk | RxErr | TxOk|TxErr) : 0),
590 np->ioaddr + IntrMask);
591 outl ((enable ? 1 : 0), np->ioaddr + IntrEnable);
594 static struct pci_device_id natsemi_nics[] = {
595 PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815"),
598 struct pci_driver natsemi_driver __pci_driver = {
600 .id_count = (sizeof (natsemi_nics) / sizeof (natsemi_nics[0])),
601 .probe = natsemi_probe,
602 .remove = natsemi_remove,