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