00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include <const.h>
00013 #include <errno.h>
00014 #include <stdlib.h>
00015 #include <string.h>
00016
00017 #include <arch/i386.h>
00018 #include <arch/interrupt.h>
00019 #include <arch/mem.h>
00020 #include <arch/paging.h>
00021
00022 #include <kernel/clock.h>
00023 #include <kernel/dma.h>
00024 #include <kernel/kmalloc.h>
00025 #include <kernel/pci.h>
00026 #include <kernel/semaphore.h>
00027 #include <kernel/video.h>
00028
00029 #include <net/arp.h>
00030 #include <net/eth.h>
00031 #include <net/ip.h>
00032 #include <net/network.h>
00033 #include <net/rtl8139.h>
00034
00035
00036 enum RTL8139_registers
00037 {
00038 MAC0=0,
00039 MAR0=8,
00040 TxStatus0=0x10,
00041 TxAddr0=0x20,
00042
00043 RxBuf=0x30,
00044 RxEarlyCnt=0x34,
00045 RxEarlyStatus=0x36,
00046
00047 ChipCmd=0x37,
00048 RxBufPtr=0x38,
00049 RxBufAddr=0x3A,
00050
00051 IntrMask=0x3C,
00052 IntrStatus=0x3E,
00053 TxConfig=0x40,
00054 RxConfig=0x44,
00055
00056 Timer=0x48,
00057 RxMissed=0x4C,
00058
00059 Cfg9346=0x50,
00060 Config0=0x51,
00061 Config1=0x52,
00062
00063 TimerIntrReg=0x54,
00064 MediaStatus=0x58,
00065 Config3=0x59,
00066 HltClk=0x5B,
00067 MultiIntr=0x5C,
00068 RevisionID=0x5E,
00069 TxSummary=0x60,
00070
00071 MII_BMCR=0x62,
00072 MII_BMSR=0x64,
00073
00074 NWayAdvert=0x66,
00075 NWayLPAR=0x68,
00076 NWayExpansion=0x6A,
00077
00078 DisconnectCnt=0x6C,
00079 FalseCarrierCnt=0x6E,
00080 NWayTestReg=0x70,
00081
00082 RxCnt=0x72,
00083 CSCR=0x74,
00084
00085 PhyParm1=0x78,
00086 TwisterParm=0x7c,
00087 PhyParm2=0x80,
00088
00089
00090
00091 };
00092
00093 enum ChipCmdBits
00094 {
00095 CmdReset=0x10,
00096 CmdRxEnb=0x08,
00097 CmdTxEnb=0x04,
00098 RxBufEmpty=0x01,
00099 };
00100
00101
00102 enum IntrStatusBits
00103 {
00104 PCIErr=0x8000,
00105 PCSTimeout=0x4000,
00106 CableLenChange= 0x2000,
00107 RxFIFOOver=0x40,
00108 RxUnderrun=0x20,
00109 RxOverflow=0x10,
00110 TxErr=0x08,
00111 TxOK=0x04,
00112 RxErr=0x02,
00113 RxOK=0x01,
00114 IntrDefault = RxOK | TxOK,
00115 };
00116
00117
00118 enum TxStatusBits
00119 {
00120 TxHostOwns=0x2000,
00121 TxUnderrun=0x4000,
00122 TxStatOK=0x8000,
00123 TxOutOfWindow=0x20000000,
00124 TxAborted=0x40000000,
00125 TxCarrierLost=0x80000000,
00126 };
00127
00128
00129 enum RxStatusBits
00130 {
00131 RxMulticast=0x8000,
00132 RxPhysical=0x4000,
00133 RxBroadcast=0x2000,
00134 RxBadSymbol=0x0020,
00135 RxRunt=0x0010,
00136 RxTooLong=0x0008,
00137 RxCRCErr=0x0004,
00138 RxBadAlign=0x0002,
00139 RxStatusOK=0x0001,
00140 };
00141
00142
00143 enum MediaStatusBits
00144 {
00145 MSRTxFlowEnable=0x80,
00146 MSRRxFlowEnable=0x40,
00147 MSRSpeed10=0x08,
00148 MSRLinkFail=0x04,
00149 MSRRxPauseFlag=0x02,
00150 MSRTxPauseFlag=0x01,
00151 };
00152
00153 enum MIIBMCRBits
00154 {
00155 BMCRReset=0x8000,
00156 BMCRSpeed100=0x2000,
00157 BMCRNWayEnable=0x1000,
00158 BMCRRestartNWay=0x0200,
00159 BMCRDuplex=0x0100,
00160 };
00161
00162 enum CSCRBits
00163 {
00164 CSCR_LinkOKBit=0x0400,
00165 CSCR_LinkChangeBit=0x0800,
00166 CSCR_LinkStatusBits=0x0f000,
00167 CSCR_LinkDownOffCmd=0x003c0,
00168 CSCR_LinkDownCmd=0x0f3c0,
00169 };
00170
00171
00172 enum rx_mode_bits
00173 {
00174 RxCfgWrap=0x80,
00175 AcceptErr=0x20,
00176 AcceptRunt=0x10,
00177 AcceptBroadcast=0x08,
00178 AcceptMulticast=0x04,
00179 AcceptMyPhys=0x02,
00180 AcceptAllPhys=0x01,
00181 };
00182
00183
00184 rtl8139_t *rtl=NULL;
00185
00186
00187
00188
00189
00190
00191 void rtl8139_close(rtl8139_t **rtl)
00192 {
00193
00194 out16((*rtl)->iobase + IntrMask, 0);
00195
00196 out((*rtl)->iobase + ChipCmd, 0);
00197
00198
00199 out((*rtl)->iobase + Cfg9346, 0xC0);
00200 out((*rtl)->iobase + Config1, 0x03);
00201
00202 out((*rtl)->iobase + HltClk, 'H');
00203
00204 if ( (*rtl) != NULL )
00205 {
00206
00207 disable_IRQ((*rtl)->irq);
00208
00209
00210 dma_phys_free((*rtl)->rx_phys, RX_BUF_LEN);
00211 dma_phys_free((*rtl)->tx_phys, TX_BUF_SIZE*NUM_TX_DESC);
00212
00213
00214 kfree((*rtl));
00215 *rtl = NULL;
00216 }
00217 }
00218
00219
00220
00221
00222
00223 static unsigned rtl8139_read_eeprom(rtl8139_t *rtl, unsigned location)
00224 {
00225 int i;
00226 unsigned int retval = 0;
00227 long ee_addr = rtl->iobase + Cfg9346;
00228 int read_cmd = location | EE_READ_CMD;
00229
00230 out(ee_addr, EE_ENB & ~EE_CS);
00231 out(ee_addr, EE_ENB);
00232
00233
00234 for (i = 10; i >= 0; i--)
00235 {
00236 int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
00237 out(ee_addr, EE_ENB | dataval);
00238 eeprom_delay();
00239 out(ee_addr, EE_ENB | dataval | EE_SHIFT_CLK);
00240 eeprom_delay();
00241 }
00242
00243 out(ee_addr, EE_ENB);
00244 eeprom_delay();
00245
00246 for (i = 16; i > 0; i--)
00247 {
00248 out(ee_addr, EE_ENB | EE_SHIFT_CLK);
00249 eeprom_delay();
00250 retval = (retval << 1) | ((in(ee_addr) & EE_DATA_READ) ? 1 : 0);
00251 out(ee_addr, EE_ENB);
00252 eeprom_delay();
00253 }
00254
00255
00256 out(ee_addr, ~EE_CS);
00257 return(retval);
00258 }
00259
00260
00261
00262
00263
00264
00265 void rtl8139_promisc(rtl8139_t *rtl, bool on)
00266 {
00267 uint8_t rxc;
00268 dword IF = GET_IF();
00269
00270 disable();
00271 rxc = in(rtl->iobase + RxConfig);
00272 if ( on )
00273 out(rtl->iobase + RxConfig, rxc | AcceptAllPhys);
00274 else
00275 out(rtl->iobase + RxConfig, rxc & (~AcceptAllPhys));
00276 rtl->promisc = on;
00277 SET_IF(IF);
00278 }
00279
00280
00281
00282 void rtl8139_reset(rtl8139_t *rtl)
00283 {
00284 unsigned i;
00285 timeout_t elapsed;
00286 dword IF = GET_IF();
00287
00288
00289 out(rtl->iobase + ChipCmd, CmdReset);
00290
00291
00292 rtl->cur_rx = 0;
00293 rtl->cur_tx = 0;
00294
00295
00296 enable();
00297 set_timeout(&elapsed, 10);
00298 while ( (in(rtl->iobase + ChipCmd) & CmdReset) != 0 )
00299 if ( is_timeout(&elapsed) ) break;
00300 SET_IF(IF);
00301
00302
00303 for (i=0; i<_countof(rtl->station_address); i++)
00304 out(rtl->iobase + MAC0 + i, rtl->station_address[i]);
00305
00306
00307 out(rtl->iobase + ChipCmd, CmdRxEnb | CmdTxEnb);
00308
00309 out32(rtl->iobase + RxConfig,
00310 (RX_FIFO_THRESH<<13) | (RX_BUF_LEN_IDX<<11) | (RX_DMA_BURST<<8));
00311 out32(rtl->iobase + TxConfig, (TX_DMA_BURST<<8) | 0x03000000);
00312
00313
00314 out32(rtl->iobase + RxBuf, rtl->rx_phys);
00315
00316
00317 for (i = 0; i < NUM_TX_DESC; i++)
00318 out32(rtl->iobase + TxAddr0 + (i * 4), rtl->tx_phys + (TX_BUF_SIZE*i));
00319
00320
00321 out32(rtl->iobase + RxMissed, 0);
00322
00323
00324 if ( rtl->promisc )
00325 out(rtl->iobase + RxConfig, AcceptBroadcast | AcceptMyPhys | AcceptAllPhys);
00326 else
00327 out(rtl->iobase + RxConfig, AcceptBroadcast | AcceptMyPhys);
00328
00329
00330
00331
00332
00333
00334
00335 out(rtl->iobase + ChipCmd, CmdRxEnb | CmdTxEnb);
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 out16(rtl->iobase + IntrMask, IntrDefault);
00347 }
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 int rtl8139_init(bool promisc)
00359 {
00360 pci_cfg_t cfg;
00361 unsigned i;
00362 dword IF = GET_IF();
00363
00364
00365 cfg.base_class = 0x02;
00366 cfg.sub_class = 0x00;
00367 cfg.interface = 0x00;
00368
00369 if ( !pci_find_cfg(&cfg, TRUE) )
00370 {
00371 return(-ENXIO);
00372 }
00373
00374
00375 if ( rtl != NULL )
00376 {
00377 rtl8139_close(&rtl);
00378 }
00379
00380
00381 rtl = kmalloc(sizeof(rtl8139_t));
00382 if ( !rtl )
00383 return(-ENOMEM);
00384
00385 memset(rtl, 0, sizeof(rtl8139_t));
00386
00387
00388 for (i=0; i<6; i++)
00389 if ( (rtl->iobase=cfg.base[i]) != 0 ) break;
00390
00391
00392 if ( rtl->iobase == 0 )
00393 {
00394 kfree(rtl);
00395 return(-EIO);
00396 }
00397
00398
00399 disable();
00400 rtl->irq = cfg.irq;
00401 install_irq_handler( rtl->irq, (void *)&rtl8139_handler );
00402
00403
00404 out(rtl->iobase + Config1, 0x00);
00405
00406
00407 if (rtl8139_read_eeprom(rtl, 0) != 0xFFFF)
00408 {
00409
00410 unsigned short *ap = (unsigned short*)rtl->station_address;
00411 for (i = 0; i < 3; i++)
00412 *ap++ = rtl8139_read_eeprom(rtl, i + 7);
00413 }
00414 else
00415 {
00416
00417 unsigned char *ap = (unsigned char*)rtl->station_address;
00418 for (i = 0; i < 6; i++)
00419 *ap++ = in(rtl->iobase + MAC0 + i);
00420 }
00421
00422
00423 rtl->speed10 = (in(rtl->iobase + MediaStatus) & MSRSpeed10) != 0;
00424 rtl->fullduplex = (in16(rtl->iobase + MII_BMCR) & BMCRDuplex) != 0;
00425
00426
00427 rtl->promisc = promisc;
00428
00429
00430 if ( !(rtl->rx_ring) )
00431 {
00432 rtl->rx_phys = (addr_t)dma_phys_alloc(RX_BUF_LEN);
00433 rtl->rx_ring = PHYSICAL( (uint8_t *)(rtl->rx_phys) );
00434 }
00435 if ( !(rtl->tx_ring) )
00436 {
00437 rtl->tx_phys = (addr_t)dma_phys_alloc(TX_BUF_SIZE*NUM_TX_DESC);
00438 rtl->tx_ring = PHYSICAL( (uint8_t *)(rtl->tx_phys) );
00439 }
00440
00441
00442 INIT_MUTEX(&rtl->mutex);
00443
00444
00445 rtl8139_reset(rtl);
00446
00447
00448 SET_IF(IF);
00449 return(0);
00450 }
00451
00452
00453
00454
00455 uint8_t *get_eth_mac_addr()
00456 {
00457 if (rtl)
00458 return(rtl->station_address);
00459 else
00460 return(NULL);
00461 }
00462
00463
00464
00465
00466
00467
00468 rtl8139_t *get_rtl8139_device()
00469 {
00470 return( rtl );
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 int send_rtl8139_packet(rtl8139_t *rtl, const void *data, size_t len)
00482 {
00483
00484 if ( !rtl ) return(-1);
00485
00486
00487
00488 len = MIN(len, TX_BUF_SIZE);
00489
00490
00491 DOWN(&rtl->mutex);
00492
00493
00494 if ( in32(rtl->iobase + TxStatus0 + (rtl->cur_tx * 4)) & TxHostOwns )
00495 {
00496
00497
00498
00499 memcpy(rtl->tx_ring + (TX_BUF_SIZE*rtl->cur_tx), data, len);
00500
00501
00502
00503 while (len < ETH_MIN_LEN)
00504 (rtl->tx_ring + (TX_BUF_SIZE*rtl->cur_tx))[len++] = '\0';
00505
00506
00507
00508
00509 out32(rtl->iobase + TxAddr0 + rtl->cur_tx * 4,
00510 rtl->tx_phys + (TX_BUF_SIZE * rtl->cur_tx));
00511 out32(rtl->iobase + TxStatus0 + rtl->cur_tx * 4,
00512 ((TX_FIFO_THRESH<<11) & 0x003F0000) | len);
00513
00514
00515 rtl->cur_tx = (rtl->cur_tx + 1) % NUM_TX_DESC;
00516
00517
00518 UP(&rtl->mutex);
00519
00520
00521 return(len);
00522 }
00523
00524 UP(&rtl->mutex);
00525
00526
00527 return(-1);
00528 }
00529
00530
00531
00532 void rtl8139_handle_tx(rtl8139_t *rtl)
00533 {
00534 unsigned int i, status;
00535
00536 for(i=0; i<NUM_TX_DESC; i++)
00537 {
00538
00539
00540 status = in32(rtl->iobase + TxStatus0 + (i * 4));
00541 #ifdef DEBUG
00542 kprintf("\n\rbuffer %u status %#010x", i, status);
00543 #endif
00544 }
00545 }
00546
00547
00548
00549 void rtl8139_handle_rx(rtl8139_t *rtl)
00550 {
00551 uint32_t ring_offs, rx_size, rx_status;
00552 rxpacket_t *packet;
00553
00554 while ((in(rtl->iobase + ChipCmd) & RxBufEmpty) == 0)
00555 {
00556 ring_offs = rtl->cur_rx % RX_BUF_LEN;
00557
00558
00559
00560 rx_status = *(uint32_t *)(rtl->rx_ring + ring_offs);
00561 rx_size = rx_status >> 16;
00562 rx_status &= 0xFFFF;
00563
00564 if (
00565 (rx_status & (RxBadSymbol | RxRunt | RxTooLong | RxCRCErr | RxBadAlign)) ||
00566 (rx_size < ETH_MIN_LEN) ||
00567 (rx_size > ETH_FRAME_LEN + 4)
00568 )
00569 {
00570 #ifdef DEBUG
00571 kprintf("\n\rRX error! status=%#010x rx_size=%#010x\n\r", rx_status, rx_size);
00572 #endif
00573 rtl8139_reset(rtl);
00574 return;
00575 }
00576
00577
00578 packet = kmalloc(sizeof(rxpacket_t) - 1 + rx_size - 4);
00579 if (packet == NULL)
00580 return;
00581
00582
00583 packet->length = rx_size - 4;
00584
00585
00586 if (ring_offs + 4 + rx_size - 4 > RX_BUF_LEN)
00587 {
00588 int semi_count = RX_BUF_LEN - ring_offs - 4;
00589
00590 memcpy(packet->data, rtl->rx_ring + ring_offs + 4, semi_count);
00591 memcpy(packet->data + semi_count, rtl->rx_ring, rx_size - 4 - semi_count);
00592 #ifdef DEBUG
00593 kprintf("\n\rRX packet (%u+%u bytes)", semi_count, rx_size - 4 - semi_count);
00594 #endif
00595 }
00596 else
00597 {
00598 memcpy(packet->data, rtl->rx_ring + ring_offs + 4, packet->length);
00599 #ifdef DEBUG
00600 kprintf("\n\rRX packet (%u bytes)", rx_size-4);
00601 #endif
00602 }
00603 #if 0
00604
00605 kprintf("\n\r");
00606 for (i=0; i<packet->length; i++)
00607 kprintf("%02X ", packet->data[i]);
00608 #endif
00609 rtl->cur_rx = (rtl->cur_rx + rx_size + 4 + 3) & ~3;
00610 out16(rtl->iobase + RxBufPtr, rtl->cur_rx - 16);
00611
00612
00613 to_eth_layer((ethernet_t *)packet->data, packet->length);
00614
00615
00616 kfree(packet);
00617 }
00618 return;
00619 }
00620
00621
00622
00623
00624
00625
00626 void rtl8139_handler()
00627 {
00628 uint16_t status;
00629
00630 out16(rtl->iobase + IntrMask, 0);
00631
00632 status = in16(rtl->iobase + IntrStatus);
00633
00634 out16(rtl->iobase + IntrStatus, status & ~(RxFIFOOver | RxOverflow | RxOK));
00635
00636 if (status & (RxOK | RxErr))
00637 rtl8139_handle_rx(rtl);
00638 else
00639 if (status & (TxOK | TxErr))
00640 rtl8139_handle_tx(rtl);
00641
00642 else
00643 kprintf("\n\rRTL8139: unknown interrupt: isr = %#010x\n", status);
00644
00645
00646
00647 out16(rtl->iobase + IntrStatus, status & (RxFIFOOver | RxOverflow | RxOK));
00648 out16(rtl->iobase + IntrMask, IntrDefault);
00649 }
00650
00651
00652
00653
00654 void rtl8139_dump_info(rtl8139_t *rtl)
00655 {
00656 in_addr_t ip, netmask, ip_bcast;
00657
00658 if ( !rtl )
00659 {
00660
00661 kprintf("\n\rUsage: ifconfig [up|down]");
00662 kprintf("\n\rRTL8139: ethernet card not configured!\n\r");
00663 return;
00664 }
00665
00666
00667 kprintf("\n\rRTL8139: card configured @ I/O base=%04X IRQ=%u", rtl->iobase, rtl->irq);
00668
00669 kprintf("\n\rRTL8139: MAC address %02x:%02x:%02x:%02x:%02x:%02x",
00670 rtl->station_address[0], rtl->station_address[1], rtl->station_address[2],
00671 rtl->station_address[3], rtl->station_address[4], rtl->station_address[5]
00672 );
00673
00674 kprintf("\n\rRTL8139: %sMbps %s-duplex",
00675 rtl->speed10 ? "10" : "100",
00676 rtl->fullduplex ? "full" : "half"
00677 );
00678
00679 kprintf("\n\rRTL8139: promiscuous mode %s", (rtl->promisc) ? "ENABLED" : "DISABLED");
00680
00681 kprintf("\n\rRTL8139: rx_ring=%p<->%p, tx_ring=%p<->%p",
00682 rtl->rx_ring, rtl->rx_ring + RX_BUF_LEN,
00683 rtl->tx_ring, rtl->tx_ring + PAGE_ALIGN_UP(TX_BUF_SIZE*NUM_TX_DESC)
00684 );
00685
00686 kprintf("\n\rRTL8139: OK, ethernet card is ready!");
00687
00688 ip = ntohl( get_host_ip() );
00689 netmask = ntohl( get_host_netmask() );
00690 ip_bcast = (~netmask) | (ip & netmask);
00691 kprintf("\n\n\rhost ip=%u.%u.%u.%u netmask=%u.%u.%u.%u broadcast=%u.%u.%u.%u\n\r",
00692 IP_A(ip), IP_B(ip), IP_C(ip), IP_D(ip),
00693 IP_A(netmask), IP_B(netmask), IP_C(netmask), IP_D(netmask),
00694 IP_A(ip_bcast), IP_B(ip_bcast), IP_C(ip_bcast), IP_D(ip_bcast)
00695 );
00696 }