00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 FILE_LICENCE ( GPL_ANY );
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #include <stdint.h>
00064 #include <stdlib.h>
00065 #include <stdio.h>
00066 #include <string.h>
00067 #include <gpxe/io.h>
00068 #include <errno.h>
00069 #include <byteswap.h>
00070 #include <unistd.h>
00071 #include <gpxe/pci.h>
00072 #include <gpxe/if_ether.h>
00073 #include <gpxe/ethernet.h>
00074 #include <gpxe/iobuf.h>
00075 #include <gpxe/netdevice.h>
00076 #include <gpxe/spi_bit.h>
00077 #include <gpxe/threewire.h>
00078 #include <gpxe/nvo.h>
00079 #include "natsemi.h"
00080
00081
00082
00083 static int natsemi_spi_read_bit ( struct bit_basher *, unsigned int );
00084 static void natsemi_spi_write_bit ( struct bit_basher *,unsigned int, unsigned long );
00085 static void natsemi_init_eeprom ( struct natsemi_private * );
00086 static int natsemi_probe (struct pci_device *pci, const struct pci_device_id *id);
00087 static void natsemi_reset (struct net_device *netdev);
00088 static int natsemi_open (struct net_device *netdev);
00089 static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf);
00090 static void natsemi_poll (struct net_device *netdev);
00091 static void natsemi_close (struct net_device *netdev);
00092 static void natsemi_irq (struct net_device *netdev, int enable);
00093 static void natsemi_remove (struct pci_device *pci);
00094
00095
00096 static struct net_device_operations natsemi_operations = {
00097 .open = natsemi_open,
00098 .close = natsemi_close,
00099 .transmit = natsemi_transmit,
00100 .poll = natsemi_poll,
00101 .irq = natsemi_irq,
00102 };
00103
00104 static int natsemi_spi_read_bit ( struct bit_basher *basher,
00105 unsigned int bit_id ) {
00106 struct natsemi_private *np = container_of ( basher, struct natsemi_private,
00107 spibit.basher );
00108 uint8_t mask = natsemi_ee_bits[bit_id];
00109 uint8_t eereg;
00110
00111 eereg = inb ( np->ioaddr + EE_REG );
00112 return ( eereg & mask );
00113 }
00114
00115 static void natsemi_spi_write_bit ( struct bit_basher *basher,
00116 unsigned int bit_id, unsigned long data ) {
00117 struct natsemi_private *np = container_of ( basher, struct natsemi_private,
00118 spibit.basher );
00119 uint8_t mask = natsemi_ee_bits[bit_id];
00120 uint8_t eereg;
00121
00122 eereg = inb ( np->ioaddr + EE_REG );
00123 eereg &= ~mask;
00124 eereg |= ( data & mask );
00125 outb ( eereg, np->ioaddr + EE_REG );
00126 }
00127
00128 static struct bit_basher_operations natsemi_basher_ops = {
00129 .read = natsemi_spi_read_bit,
00130 .write = natsemi_spi_write_bit,
00131 };
00132
00133
00134
00135
00136
00137 static struct nvo_fragment natsemi_nvo_fragments[] = {
00138 { 0x0c, 0x68 },
00139 { 0, 0 }
00140 };
00141
00142
00143
00144
00145
00146
00147 static void natsemi_init_eeprom ( struct natsemi_private *np ) {
00148
00149
00150
00151 np->spibit.basher.op = &natsemi_basher_ops;
00152 np->spibit.bus.mode = SPI_MODE_THREEWIRE;
00153 np->spibit.endianness = SPI_BIT_LITTLE_ENDIAN;
00154 init_spi_bit_basher ( &np->spibit );
00155
00156
00157
00158 init_at93c46 ( &np->eeprom, 16 );
00159 np->eeprom.bus = &np->spibit.bus;
00160 np->nvo.nvs = &np->eeprom.nvs;
00161 np->nvo.fragments = natsemi_nvo_fragments;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171 static int natsemi_probe (struct pci_device *pci,
00172 const struct pci_device_id *id __unused) {
00173 struct net_device *netdev;
00174 struct natsemi_private *np = NULL;
00175 uint8_t ll_addr_encoded[MAX_LL_ADDR_LEN];
00176 uint8_t last=0,last1=0;
00177 uint8_t prev_bytes[2];
00178 int i;
00179 int rc;
00180
00181
00182
00183 netdev = alloc_etherdev (sizeof (*np));
00184 if (! netdev)
00185 return -ENOMEM;
00186
00187 netdev_init (netdev, &natsemi_operations);
00188 np = netdev->priv;
00189 pci_set_drvdata (pci, netdev);
00190 netdev->dev = &pci->dev;
00191 memset (np, 0, sizeof (*np));
00192 np->ioaddr = pci->ioaddr;
00193
00194 adjust_pci_device (pci);
00195
00196 natsemi_reset (netdev);
00197 natsemi_init_eeprom ( np );
00198 nvs_read ( &np->eeprom.nvs, EE_MAC-1, prev_bytes, 1 );
00199 nvs_read ( &np->eeprom.nvs, EE_MAC, ll_addr_encoded, ETH_ALEN );
00200
00201
00202
00203
00204 last = prev_bytes[1] >> 7;
00205 for ( i = 0 ; i < ETH_ALEN ; i++ ) {
00206 last1 = ll_addr_encoded[i] >> 7;
00207 netdev->hw_addr[i] = ll_addr_encoded[i] << 1 | last;
00208 last = last1;
00209 }
00210
00211
00212 netdev_link_up ( netdev );
00213
00214 if ((rc = register_netdev (netdev)) != 0)
00215 goto err_register_netdev;
00216
00217 return 0;
00218
00219 err_register_netdev:
00220
00221 natsemi_reset (netdev);
00222 netdev_put (netdev);
00223 return rc;
00224 }
00225
00226
00227
00228
00229
00230
00231 static void natsemi_remove (struct pci_device *pci) {
00232 struct net_device *netdev = pci_get_drvdata (pci);
00233
00234 unregister_netdev (netdev);
00235 natsemi_reset (netdev);
00236 netdev_nullify ( netdev );
00237 netdev_put (netdev);
00238 }
00239
00240
00241
00242
00243
00244
00245
00246
00247 static void natsemi_reset (struct net_device *netdev)
00248 {
00249 struct natsemi_private *np = netdev->priv;
00250 int i;
00251 u32 cfg;
00252 u32 wcsr;
00253 u32 rfcr;
00254 u16 pmatch[3];
00255 u16 sopass[3];
00256
00257 natsemi_irq (netdev, 0);
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 cfg = inl (np->ioaddr + ChipConfig) & CFG_RESET_SAVE;
00268
00269
00270 wcsr = inl (np->ioaddr + WOLCmd) & WCSR_RESET_SAVE;
00271
00272
00273 rfcr = inl (np->ioaddr + RxFilterAddr) & RFCR_RESET_SAVE;
00274
00275
00276 for (i = 0; i < 3; i++) {
00277 outl(i*2, np->ioaddr + RxFilterAddr);
00278 pmatch[i] = inw(np->ioaddr + RxFilterData);
00279 }
00280
00281
00282 for (i = 0; i < 3; i++) {
00283 outl(0xa+(i*2), np->ioaddr + RxFilterAddr);
00284 sopass[i] = inw(np->ioaddr + RxFilterData);
00285 }
00286
00287
00288 outl(ChipReset, np->ioaddr + ChipCmd);
00289 for (i=0; i<NATSEMI_HW_TIMEOUT; i++) {
00290 if (! (inl (np->ioaddr + ChipCmd) & ChipReset))
00291 break;
00292 udelay(5);
00293 }
00294 if (i == NATSEMI_HW_TIMEOUT) {
00295 DBG ("natsemi_reset: reset did not complete in %d usec.\n", i*5);
00296 }
00297
00298
00299 cfg |= inl(np->ioaddr + ChipConfig) & ~CFG_RESET_SAVE;
00300 cfg &= ~(CfgExtPhy | CfgPhyDis);
00301 outl (cfg, np->ioaddr + ChipConfig);
00302
00303
00304 wcsr |= inl (np->ioaddr + WOLCmd) & ~WCSR_RESET_SAVE;
00305 outl (wcsr, np->ioaddr + WOLCmd);
00306
00307
00308 rfcr |= inl (np->ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE;
00309
00310
00311 for (i = 0; i < 3; i++) {
00312 outl (i*2, np->ioaddr + RxFilterAddr);
00313 outw (pmatch[i], np->ioaddr + RxFilterData);
00314 }
00315 for (i = 0; i < 3; i++) {
00316 outl (0xa+(i*2), np->ioaddr + RxFilterAddr);
00317 outw (sopass[i], np->ioaddr + RxFilterData);
00318 }
00319
00320 outl (rfcr, np->ioaddr + RxFilterAddr);
00321 }
00322
00323
00324
00325
00326
00327
00328
00329 static int natsemi_open (struct net_device *netdev)
00330 {
00331 struct natsemi_private *np = netdev->priv;
00332 uint32_t tx_config, rx_config;
00333 int i;
00334
00335
00336
00337
00338
00339
00340
00341
00342 outl (inl (np->ioaddr + ClkRun) & ~0x100, np->ioaddr + ClkRun);
00343
00344
00345
00346 for (i = 0 ; i < ETH_ALEN ; i+=2) {
00347 outl (i, np->ioaddr + RxFilterAddr);
00348 outw (netdev->ll_addr[i] + (netdev->ll_addr[i + 1] << 8),
00349 np->ioaddr + RxFilterData);
00350 }
00351
00352
00353
00354 np->tx_cur = 0;
00355 np->tx_dirty = 0;
00356 for (i = 0 ; i < TX_RING_SIZE ; i++) {
00357 np->tx[i].link = virt_to_bus ((i + 1 < TX_RING_SIZE) ? &np->tx[i + 1] : &np->tx[0]);
00358 np->tx[i].cmdsts = 0;
00359 np->tx[i].bufptr = 0;
00360 }
00361 outl (virt_to_bus (&np->tx[0]),np->ioaddr + TxRingPtr);
00362
00363 DBG ("Natsemi Tx descriptor loaded with: %#08x\n",
00364 inl (np->ioaddr + TxRingPtr));
00365
00366
00367
00368 np->rx_cur = 0;
00369 for (i = 0 ; i < NUM_RX_DESC ; i++) {
00370 np->iobuf[i] = alloc_iob (RX_BUF_SIZE);
00371 if (! np->iobuf[i])
00372 goto memory_alloc_err;
00373 np->rx[i].link = virt_to_bus ((i + 1 < NUM_RX_DESC)
00374 ? &np->rx[i + 1] : &np->rx[0]);
00375 np->rx[i].cmdsts = RX_BUF_SIZE;
00376 np->rx[i].bufptr = virt_to_bus (np->iobuf[i]->data);
00377 DBG (" Address of iobuf [%d] = %p and iobuf->data = %p \n", i,
00378 &np->iobuf[i], &np->iobuf[i]->data);
00379 }
00380 outl (virt_to_bus (&np->rx[0]), np->ioaddr + RxRingPtr);
00381
00382 DBG ("Natsemi Rx descriptor loaded with: %#08x\n",
00383 inl (np->ioaddr + RxRingPtr));
00384
00385
00386
00387 outl (RxFilterEnable | AcceptBroadcast | AcceptAllMulticast | AcceptMyPhys,
00388 np->ioaddr + RxFilterAddr);
00389
00390
00391
00392
00393
00394 if (inl (np->ioaddr + ChipConfig) & 0x20000000) {
00395 DBG ("Full duplex\n");
00396 tx_config = 0xD0801002 | 0xC0000000;
00397 rx_config = 0x10000020 | 0x10000000;
00398 } else {
00399 DBG ("Half duplex\n");
00400 tx_config = 0x10801002 & ~0xC0000000;
00401 rx_config = 0x00000020 & ~0x10000000;
00402 }
00403 outl (tx_config, np->ioaddr + TxConfig);
00404 outl (rx_config, np->ioaddr + RxConfig);
00405
00406 DBG ("Tx config register = %#08x Rx config register = %#08x\n",
00407 inl (np->ioaddr + TxConfig),
00408 inl (np->ioaddr + RxConfig));
00409
00410
00411
00412 outl((RxOk|RxErr|TxOk|TxErr),np->ioaddr + IntrMask);
00413
00414
00415 outl (RxOn, np->ioaddr + ChipCmd);
00416
00417 return 0;
00418
00419 memory_alloc_err:
00420
00421
00422
00423
00424 i = 0;
00425 while (np->rx[i].cmdsts == RX_BUF_SIZE) {
00426 free_iob (np->iobuf[i]);
00427 i++;
00428 }
00429 return -ENOMEM;
00430 }
00431
00432
00433
00434
00435
00436
00437 static void natsemi_close (struct net_device *netdev)
00438 {
00439 struct natsemi_private *np = netdev->priv;
00440 int i;
00441
00442 natsemi_reset (netdev);
00443
00444 for (i = 0; i < NUM_RX_DESC ; i++) {
00445 free_iob (np->iobuf[i]);
00446 }
00447 }
00448
00449
00450
00451
00452
00453
00454
00455
00456 static int natsemi_transmit (struct net_device *netdev, struct io_buffer *iobuf)
00457 {
00458 struct natsemi_private *np = netdev->priv;
00459
00460 if (np->tx[np->tx_cur].cmdsts != 0) {
00461 DBG ("TX overflow\n");
00462 return -ENOBUFS;
00463 }
00464
00465
00466
00467 np->tx_iobuf[np->tx_cur] = iobuf;
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 np->tx[np->tx_cur].bufptr = virt_to_bus (iobuf->data);
00478 np->tx[np->tx_cur].cmdsts = iob_len (iobuf) | OWN;
00479
00480 DBG ("TX id %d at %#08lx + %#08zx\n", np->tx_cur,
00481 virt_to_bus (&iobuf->data), iob_len (iobuf));
00482
00483
00484
00485 np->tx_cur = (np->tx_cur + 1) % TX_RING_SIZE;
00486
00487
00488
00489 outl (TxOn, np->ioaddr + ChipCmd);
00490
00491 return 0;
00492 }
00493
00494
00495
00496
00497
00498
00499 static void natsemi_poll (struct net_device *netdev)
00500 {
00501 struct natsemi_private *np = netdev->priv;
00502 unsigned int tx_status;
00503 unsigned int rx_status;
00504 unsigned int intr_status;
00505 unsigned int rx_len;
00506 struct io_buffer *rx_iob;
00507 int i;
00508
00509
00510
00511 intr_status = inl (np->ioaddr + IntrStatus);
00512
00513 if (!intr_status)
00514 goto end;
00515
00516 DBG ("natsemi_poll: intr_status = %#08x\n", intr_status);
00517
00518
00519
00520 i = np->tx_dirty;
00521 while (i != np->tx_cur) {
00522 tx_status = np->tx[np->tx_dirty].cmdsts;
00523
00524 DBG ("tx_dirty = %d tx_cur=%d tx_status=%#08x\n",
00525 np->tx_dirty, np->tx_cur, tx_status);
00526
00527 if (tx_status & OWN)
00528 break;
00529
00530 if (! (tx_status & DescPktOK)) {
00531 netdev_tx_complete_err (netdev,np->tx_iobuf[np->tx_dirty],-EINVAL);
00532 DBG ("Error transmitting packet, tx_status: %#08x\n",
00533 tx_status);
00534 } else {
00535 netdev_tx_complete (netdev, np->tx_iobuf[np->tx_dirty]);
00536 DBG ("Success transmitting packet\n");
00537 }
00538
00539 np->tx[np->tx_dirty].cmdsts = 0;
00540 np->tx_dirty = (np->tx_dirty + 1) % TX_RING_SIZE;
00541 i = (i + 1) % TX_RING_SIZE;
00542 }
00543
00544
00545
00546 rx_status = (unsigned int) np->rx[np->rx_cur].cmdsts;
00547 while ((rx_status & OWN)) {
00548 rx_len = (rx_status & DSIZE) - CRC_SIZE;
00549
00550 DBG ("Received packet, rx_curr = %d, rx_status = %#08x, rx_len = %d\n",
00551 np->rx_cur, rx_status, rx_len);
00552
00553 if ((rx_status & (DescMore | DescPktOK | RxTooLong)) != DescPktOK) {
00554 netdev_rx_err (netdev, NULL, -EINVAL);
00555
00556 DBG ("natsemi_poll: Corrupted packet received!"
00557 " Status = %#08x\n",
00558 np->rx[np->rx_cur].cmdsts);
00559
00560 } else {
00561
00562
00563
00564
00565
00566 rx_iob = alloc_iob (rx_len);
00567 if (! rx_iob)
00568 goto end;
00569 memcpy (iob_put (rx_iob, rx_len),
00570 np->iobuf[np->rx_cur]->data, rx_len);
00571
00572
00573 netdev_rx (netdev, rx_iob);
00574 }
00575 np->rx[np->rx_cur].cmdsts = RX_BUF_SIZE;
00576 np->rx_cur = (np->rx_cur + 1) % NUM_RX_DESC;
00577 rx_status = np->rx[np->rx_cur].cmdsts;
00578 }
00579 end:
00580
00581
00582 outl (RxOn, np->ioaddr + ChipCmd);
00583 }
00584
00585
00586
00587
00588
00589
00590
00591 static void natsemi_irq (struct net_device *netdev, int enable)
00592 {
00593 struct natsemi_private *np = netdev->priv;
00594
00595 outl ((enable ? (RxOk | RxErr | TxOk|TxErr) : 0),
00596 np->ioaddr + IntrMask);
00597 outl ((enable ? 1 : 0), np->ioaddr + IntrEnable);
00598 }
00599
00600 static struct pci_device_id natsemi_nics[] = {
00601 PCI_ROM(0x100b, 0x0020, "dp83815", "DP83815", 0),
00602 };
00603
00604 struct pci_driver natsemi_driver __pci_driver = {
00605 .ids = natsemi_nics,
00606 .id_count = (sizeof (natsemi_nics) / sizeof (natsemi_nics[0])),
00607 .probe = natsemi_probe,
00608 .remove = natsemi_remove,
00609 };