#include <const.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <arch/i386.h>
#include <arch/interrupt.h>
#include <arch/mem.h>
#include <arch/paging.h>
#include <kernel/clock.h>
#include <kernel/dma.h>
#include <kernel/kmalloc.h>
#include <kernel/pci.h>
#include <kernel/semaphore.h>
#include <kernel/video.h>
#include <net/arp.h>
#include <net/eth.h>
#include <net/ip.h>
#include <net/network.h>
#include <net/rtl8139.h>
Go to the source code of this file.
Enumerations | |||||||
enum | RTL8139_registers { MAC0 = 0, MAR0 = 8, TxStatus0 = 0x10, TxAddr0 = 0x20, RxBuf = 0x30, RxEarlyCnt = 0x34, RxEarlyStatus = 0x36, ChipCmd = 0x37, RxBufPtr = 0x38, RxBufAddr = 0x3A, IntrMask = 0x3C, IntrStatus = 0x3E, TxConfig = 0x40, RxConfig = 0x44, Timer = 0x48, RxMissed = 0x4C, Cfg9346 = 0x50, Config0 = 0x51, Config1 = 0x52, TimerIntrReg = 0x54, MediaStatus = 0x58, Config3 = 0x59, HltClk = 0x5B, MultiIntr = 0x5C, RevisionID = 0x5E, TxSummary = 0x60, MII_BMCR = 0x62, MII_BMSR = 0x64, NWayAdvert = 0x66, NWayLPAR = 0x68, NWayExpansion = 0x6A, DisconnectCnt = 0x6C, FalseCarrierCnt = 0x6E, NWayTestReg = 0x70, RxCnt = 0x72, CSCR = 0x74, PhyParm1 = 0x78, TwisterParm = 0x7c, PhyParm2 = 0x80 } | ||||||
Symbolic RTL8139 offsets to registers. More... | |||||||
enum | ChipCmdBits { CmdReset = 0x10, CmdRxEnb = 0x08, CmdTxEnb = 0x04, RxBufEmpty = 0x01 } | ||||||
enum | IntrStatusBits { PCIErr = 0x8000, PCSTimeout = 0x4000, CableLenChange = 0x2000, RxFIFOOver = 0x40, RxUnderrun = 0x20, RxOverflow = 0x10, TxErr = 0x08, TxOK = 0x04, RxErr = 0x02, RxOK = 0x01, IntrDefault = RxOK | TxOK } | ||||||
Interrupt Status Register bits. More... | |||||||
enum | TxStatusBits { TxHostOwns = 0x2000, TxUnderrun = 0x4000, TxStatOK = 0x8000, TxOutOfWindow = 0x20000000, TxAborted = 0x40000000, TxCarrierLost = 0x80000000 } | ||||||
Transmit Status Register bits. More... | |||||||
enum | RxStatusBits { RxMulticast = 0x8000, RxPhysical = 0x4000, RxBroadcast = 0x2000, RxBadSymbol = 0x0020, RxRunt = 0x0010, RxTooLong = 0x0008, RxCRCErr = 0x0004, RxBadAlign = 0x0002, RxStatusOK = 0x0001 } | ||||||
Receive Status Register bits. More... | |||||||
enum | MediaStatusBits { MSRTxFlowEnable = 0x80, MSRRxFlowEnable = 0x40, MSRSpeed10 = 0x08, MSRLinkFail = 0x04, MSRRxPauseFlag = 0x02, MSRTxPauseFlag = 0x01 } | ||||||
Media Status Register bits. More... | |||||||
enum | MIIBMCRBits { BMCRReset = 0x8000, BMCRSpeed100 = 0x2000, BMCRNWayEnable = 0x1000, BMCRRestartNWay = 0x0200, BMCRDuplex = 0x0100 } | ||||||
enum | CSCRBits { CSCR_LinkOKBit = 0x0400, CSCR_LinkChangeBit = 0x0800, CSCR_LinkStatusBits = 0x0f000, CSCR_LinkDownOffCmd = 0x003c0, CSCR_LinkDownCmd = 0x0f3c0 } | ||||||
enum | rx_mode_bits { RxCfgWrap = 0x80, AcceptErr = 0x20, AcceptRunt = 0x10, AcceptBroadcast = 0x08, AcceptMulticast = 0x04, AcceptMyPhys = 0x02, AcceptAllPhys = 0x01 } | ||||||
Bits in Receive Configuration Register. More... | |||||||
Functions | |||||||
void | rtl8139_close (rtl8139_t **rtl) | ||||||
Halt the RTL8139 card and free the logical device.
| |||||||
unsigned | rtl8139_read_eeprom (rtl8139_t *rtl, unsigned location) | ||||||
Read RTL8139 informations from the EEPROM.
| |||||||
void | rtl8139_promisc (rtl8139_t *rtl, bool on) | ||||||
Enable/disable the promiscuous mode for the RTL8139 card.
| |||||||
void | rtl8139_reset (rtl8139_t *rtl) | ||||||
Reset the RTL8139 ethernet card.
| |||||||
int | rtl8139_init (bool promisc) | ||||||
Initialize the RTL8139 driver.
| |||||||
uint8_t * | get_eth_mac_addr () | ||||||
Get the MAC hardware address of the RTL8139 ethernet card.
| |||||||
rtl8139_t * | get_rtl8139_device () | ||||||
Get the pointer of the RTL8139 device structure.
| |||||||
int | send_rtl8139_packet (rtl8139_t *rtl, const void *data, size_t len) | ||||||
Send an ethernet packet to the physiscal layer.
| |||||||
void | rtl8139_handle_tx (rtl8139_t *rtl) | ||||||
Handle a transmitted packet event.
| |||||||
void | rtl8139_handle_rx (rtl8139_t *rtl) | ||||||
Handle a received packet event.
| |||||||
void | rtl8139_handler () | ||||||
The RTL8139 interrupt handler routine. It is invoked every time that an ethernet packet is received or when a packet has been transmitted. | |||||||
void | rtl8139_dump_info (rtl8139_t *rtl) | ||||||
Print the current RTL8139 card configuration on the console.
| |||||||
Variables | |||||||
rtl8139_t * | rtl = NULL | ||||||
Pointer to the RTL8139 structure. |
Definition in file rtl8139.c.
|
Definition at line 93 of file rtl8139.c.
00094 { 00095 CmdReset=0x10, 00096 CmdRxEnb=0x08, 00097 CmdTxEnb=0x04, 00098 RxBufEmpty=0x01, 00099 }; |
|
Definition at line 162 of file rtl8139.c.
00163 { 00164 CSCR_LinkOKBit=0x0400, 00165 CSCR_LinkChangeBit=0x0800, 00166 CSCR_LinkStatusBits=0x0f000, 00167 CSCR_LinkDownOffCmd=0x003c0, 00168 CSCR_LinkDownCmd=0x0f3c0, 00169 }; |
|
Interrupt Status Register bits.
Definition at line 102 of file rtl8139.c.
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 }; |
|
Media Status Register bits.
Definition at line 143 of file rtl8139.c.
00144 { 00145 MSRTxFlowEnable=0x80, 00146 MSRRxFlowEnable=0x40, 00147 MSRSpeed10=0x08, 00148 MSRLinkFail=0x04, 00149 MSRRxPauseFlag=0x02, 00150 MSRTxPauseFlag=0x01, 00151 }; |
|
Definition at line 153 of file rtl8139.c.
00154 { 00155 BMCRReset=0x8000, 00156 BMCRSpeed100=0x2000, 00157 BMCRNWayEnable=0x1000, 00158 BMCRRestartNWay=0x0200, 00159 BMCRDuplex=0x0100, 00160 }; |
|
Symbolic RTL8139 offsets to registers.
Definition at line 36 of file rtl8139.c.
00037 { 00038 MAC0=0, //!< Ethernet hardware address. 00039 MAR0=8, //!< Multicast filter. 00040 TxStatus0=0x10, //!< Transmit status: 4 32bit registers. 00041 TxAddr0=0x20, //!< Tx descriptors (also 4 32bit). 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, //!< General-purpose counter. 00057 RxMissed=0x4C, //!< 24 bits valid, write clears. 00058 00059 Cfg9346=0x50, 00060 Config0=0x51, 00061 Config1=0x52, 00062 00063 TimerIntrReg=0x54, //!< INTR if gp counter reaches this value. 00064 MediaStatus=0x58, 00065 Config3=0x59, 00066 HltClk=0x5B, 00067 MultiIntr=0x5C, 00068 RevisionID=0x5E, //!< Revision of the RTL8139 chip. 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, //!< Packet received counter. 00083 CSCR=0x74, //!< Chip status and configuration register. 00084 00085 PhyParm1=0x78, //!< Undocumented. 00086 TwisterParm=0x7c, //!< Undocumented. 00087 PhyParm2=0x80, //!< Undocumented. 00088 00089 // From 0x84 onwards are a number of power management/wakeup // 00090 // frame definitions we will probably never need to know about. // 00091 }; |
|
Bits in Receive Configuration Register.
Definition at line 172 of file rtl8139.c.
00173 { 00174 RxCfgWrap=0x80, 00175 AcceptErr=0x20, 00176 AcceptRunt=0x10, 00177 AcceptBroadcast=0x08, 00178 AcceptMulticast=0x04, 00179 AcceptMyPhys=0x02, 00180 AcceptAllPhys=0x01, 00181 }; |
|
Receive Status Register bits.
Definition at line 129 of file rtl8139.c.
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 }; |
|
Transmit Status Register bits.
Definition at line 118 of file rtl8139.c.
00119 { 00120 TxHostOwns=0x2000, 00121 TxUnderrun=0x4000, 00122 TxStatOK=0x8000, 00123 TxOutOfWindow=0x20000000, 00124 TxAborted=0x40000000, 00125 TxCarrierLost=0x80000000, 00126 }; |
|
Get the MAC hardware address of the RTL8139 ethernet card.
Definition at line 455 of file rtl8139.c.
00456 { 00457 if (rtl) 00458 return(rtl->station_address); 00459 else 00460 return(NULL); 00461 } |
|
Get the pointer of the RTL8139 device structure.
Definition at line 468 of file rtl8139.c.
00469 {
00470 return( rtl );
00471 }
|
|
Halt the RTL8139 card and free the logical device.
Definition at line 191 of file rtl8139.c.
00192 { 00193 // Disable interrupts by clearing the interrupt mask // 00194 out16((*rtl)->iobase + IntrMask, 0); 00195 // Stop the chip's Tx and Rx DMA processes // 00196 out((*rtl)->iobase + ChipCmd, 0); 00197 00198 // Put the chip in low-power mode // 00199 out((*rtl)->iobase + Cfg9346, 0xC0); 00200 out((*rtl)->iobase + Config1, 0x03); 00201 // 'R' would leave the clock running // 00202 out((*rtl)->iobase + HltClk, 'H'); 00203 00204 if ( (*rtl) != NULL ) 00205 { 00206 // Disable the IRQ line // 00207 disable_IRQ((*rtl)->irq); 00208 00209 // Deallocate the ring buffers // 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 // Deallocate the logical structure // 00214 kfree((*rtl)); 00215 *rtl = NULL; 00216 } 00217 } |
|
Print the current RTL8139 card configuration on the console.
Definition at line 654 of file rtl8139.c.
00655 { 00656 in_addr_t ip, netmask, ip_bcast; 00657 00658 if ( !rtl ) 00659 { 00660 // The card is not configured // 00661 kprintf("\n\rUsage: ifconfig [up|down]"); 00662 kprintf("\n\rRTL8139: ethernet card not configured!\n\r"); 00663 return; 00664 } 00665 00666 // Dump the device informations // 00667 kprintf("\n\rRTL8139: card configured @ I/O base=%04X IRQ=%u", rtl->iobase, rtl->irq); 00668 // Dump the MAC address // 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 // Dump the media informations // 00674 kprintf("\n\rRTL8139: %sMbps %s-duplex", 00675 rtl->speed10 ? "10" : "100", 00676 rtl->fullduplex ? "full" : "half" 00677 ); 00678 // Print the promiscuous mode flag // 00679 kprintf("\n\rRTL8139: promiscuous mode %s", (rtl->promisc) ? "ENABLED" : "DISABLED"); 00680 // Print virtual memory rings pointers // 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 // Well done! // 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 } |
|
Handle a received packet event.
Definition at line 549 of file rtl8139.c.
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 // Read status+size of the next frame from DMA // 00559 // ring buffer // 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 // Allocate a buffer to store the packet // 00578 packet = kmalloc(sizeof(rxpacket_t) - 1 + rx_size - 4); 00579 if (packet == NULL) 00580 return; 00581 00582 // No one cares about the FCS // 00583 packet->length = rx_size - 4; 00584 00585 // Received a good packet // 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 // Dump the received packet content // 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 // Send the packet to the upper layer // 00613 to_eth_layer((ethernet_t *)packet->data, packet->length); 00614 00615 // Free the packet sturcture // 00616 kfree(packet); 00617 } 00618 return; 00619 } |
|
Handle a transmitted packet event.
Definition at line 532 of file rtl8139.c.
00533 { 00534 unsigned int i, status; 00535 00536 for(i=0; i<NUM_TX_DESC; i++) 00537 { 00538 // We must read the status of every descriptor when // 00539 // a Tx interrupt occurs // 00540 status = in32(rtl->iobase + TxStatus0 + (i * 4)); 00541 #ifdef DEBUG 00542 kprintf("\n\rbuffer %u status %#010x", i, status); 00543 #endif 00544 } 00545 } |
|
Initialize the RTL8139 driver.
Definition at line 358 of file rtl8139.c.
00359 { 00360 pci_cfg_t cfg; 00361 unsigned i; 00362 dword IF = GET_IF(); 00363 00364 // Search an ethernet device on PCI and enable it! // 00365 cfg.base_class = 0x02; // Ethernet class // 00366 cfg.sub_class = 0x00; // Ethernet sub_class // 00367 cfg.interface = 0x00; // Ethernet interface // 00368 00369 if ( !pci_find_cfg(&cfg, TRUE) ) 00370 { 00371 return(-ENXIO); 00372 } 00373 00374 // Close a previous RTL8139 structure if present // 00375 if ( rtl != NULL ) 00376 { 00377 rtl8139_close(&rtl); 00378 } 00379 00380 // Allocate the RTL8139 structure // 00381 rtl = kmalloc(sizeof(rtl8139_t)); 00382 if ( !rtl ) 00383 return(-ENOMEM); 00384 00385 memset(rtl, 0, sizeof(rtl8139_t)); 00386 00387 // Setup the I/O base register // 00388 for (i=0; i<6; i++) 00389 if ( (rtl->iobase=cfg.base[i]) != 0 ) break; 00390 00391 // Check if the device I/O base address is valid // 00392 if ( rtl->iobase == 0 ) 00393 { 00394 kfree(rtl); 00395 return(-EIO); 00396 } 00397 00398 // Setup the IRQ line // 00399 disable(); 00400 rtl->irq = cfg.irq; 00401 install_irq_handler( rtl->irq, (void *)&rtl8139_handler ); 00402 00403 // Bring the chip out of low-power mode // 00404 out(rtl->iobase + Config1, 0x00); 00405 00406 // Read the MAC address // 00407 if (rtl8139_read_eeprom(rtl, 0) != 0xFFFF) 00408 { 00409 // Read from EEPROM // 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 // Read from MAC0 register // 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 // Read the media informations // 00423 rtl->speed10 = (in(rtl->iobase + MediaStatus) & MSRSpeed10) != 0; 00424 rtl->fullduplex = (in16(rtl->iobase + MII_BMCR) & BMCRDuplex) != 0; 00425 00426 // Setup the promiscuous mode // 00427 rtl->promisc = promisc; 00428 00429 // Initialize the Rx and Tx rings buffer // 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 // Initialize the RTL8139 mutex semaphore // 00442 INIT_MUTEX(&rtl->mutex); 00443 00444 // Hardware reset of the RTL8139 // 00445 rtl8139_reset(rtl); 00446 00447 // Well done! // 00448 SET_IF(IF); 00449 return(0); 00450 } |
|
Enable/disable the promiscuous mode for the RTL8139 card.
Definition at line 265 of file rtl8139.c.
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 } |
|
Read RTL8139 informations from the EEPROM.
Definition at line 223 of file rtl8139.c.
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 // Shift the read command bits out // 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 // Terminate the EEPROM access // 00256 out(ee_addr, ~EE_CS); 00257 return(retval); 00258 } |
|
Reset the RTL8139 ethernet card.
Definition at line 282 of file rtl8139.c.
00283 { 00284 unsigned i; 00285 timeout_t elapsed; 00286 dword IF = GET_IF(); 00287 00288 // Send the software-reset command // 00289 out(rtl->iobase + ChipCmd, CmdReset); 00290 00291 // Reset the Rx and Tx rings // 00292 rtl->cur_rx = 0; 00293 rtl->cur_tx = 0; 00294 00295 // Give the chip 10ms to finish the reset // 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 // Set-up the card MAC address register // 00303 for (i=0; i<_countof(rtl->station_address); i++) 00304 out(rtl->iobase + MAC0 + i, rtl->station_address[i]); 00305 00306 // Must enable Tx/Rx before setting transfer thresholds! // 00307 out(rtl->iobase + ChipCmd, CmdRxEnb | CmdTxEnb); 00308 // Accept no frames yet! // 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 // Configure the RX buffer // 00314 out32(rtl->iobase + RxBuf, rtl->rx_phys); 00315 00316 // Init Tx buffer DMA addresses // 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 // Reset the missed packets counter // 00321 out32(rtl->iobase + RxMissed, 0); 00322 00323 // Set RX mode // 00324 if ( rtl->promisc ) 00325 out(rtl->iobase + RxConfig, AcceptBroadcast | AcceptMyPhys | AcceptAllPhys); 00326 else 00327 out(rtl->iobase + RxConfig, AcceptBroadcast | AcceptMyPhys); 00328 00329 // If we add multicast support, the MAR0 register would have to // 00330 // be initialized to 0xFFFFFFFF.FFFFFFFF (two 32 bit accesses). // 00331 // Etherboot only needs broadcast (for ARP/RARP/BOOTP/DHCP) and // 00332 // unicast. // 00333 00334 // Start the chip's Tx and Rx process // 00335 out(rtl->iobase + ChipCmd, CmdRxEnb | CmdTxEnb); 00336 00337 // Disable all known interrupts by setting the interrupt mask // 00338 // out16(rtl->iobase + IntrMask, 0x0000); 00339 00340 // Enable all known interrupts // 00341 // out16(rtl->iobase + IntrMask, PCIErr | PCSTimeout | RxUnderrun | 00342 // RxOverflow | RxFIFOOver | 00343 // TxErr | TxOK | RxErr | RxOK); 00344 00345 // Enable default interrupt mask (RxOK | TxOK) // 00346 out16(rtl->iobase + IntrMask, IntrDefault); 00347 } |
|
Send an ethernet packet to the physiscal layer.
Definition at line 481 of file rtl8139.c.
00482 { 00483 // Check if the RTL8139 card has been configured // 00484 if ( !rtl ) return(-1); 00485 00486 // Adapt the packet length to the Tx buffer size // 00487 // This should be done by the ethernet layer... // 00488 len = MIN(len, TX_BUF_SIZE); 00489 00490 // Enter critical region // 00491 DOWN(&rtl->mutex); 00492 00493 // kprintf("\n\rlooking for buffer %u", desc); 00494 if ( in32(rtl->iobase + TxStatus0 + (rtl->cur_tx * 4)) & TxHostOwns ) 00495 { 00496 // Found a free buffer! // 00497 00498 // Copy the raw data to the Tx ring // 00499 memcpy(rtl->tx_ring + (TX_BUF_SIZE*rtl->cur_tx), data, len); 00500 00501 // NOTE: RTL8139 doesn't auto-pad! Be sure that // 00502 // the ethernet layer has done it correctly // 00503 while (len < ETH_MIN_LEN) 00504 (rtl->tx_ring + (TX_BUF_SIZE*rtl->cur_tx))[len++] = '\0'; 00505 00506 // Move the data from the Tx buffer to the // 00507 // internal transmit FIFO in PCI bus master // 00508 // mode // 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 // Select new descriptor for transmition // 00515 rtl->cur_tx = (rtl->cur_tx + 1) % NUM_TX_DESC; 00516 00517 // End of critical region // 00518 UP(&rtl->mutex); 00519 00520 // Return the byte transmitted // 00521 return(len); 00522 } 00523 // End of critical region // 00524 UP(&rtl->mutex); 00525 00526 // Buffer not available! // 00527 return(-1); 00528 } |
|
Pointer to the RTL8139 structure.
|