Data Structures | |||||||
struct | rtl8139 | ||||||
The RTL8139 device structure. More... | |||||||
struct | rxpacket | ||||||
A receive packet structure. More... | |||||||
struct | txpacket | ||||||
A transmitted packet structure. More... | |||||||
Typedefs | |||||||
typedef rxpacket | rxpacket_t | ||||||
A receive packet structure. | |||||||
typedef txpacket | txpacket_t | ||||||
A transmitted packet structure. | |||||||
typedef rtl8139 | rtl8139_t | ||||||
The RTL8139 device structure. | |||||||
Functions | |||||||
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.
| |||||||
int | rtl8139_init (bool promisc) | ||||||
Initialize the RTL8139 driver.
| |||||||
void | rtl8139_close (rtl8139_t **rtl) | ||||||
Halt the RTL8139 card and free the logical device.
| |||||||
void | rtl8139_promisc (rtl8139_t *rtl, bool on) | ||||||
Enable/disable the promiscuous mode for the RTL8139 card.
| |||||||
void | rtl8139_dump_info (rtl8139_t *rtl) | ||||||
Print the current RTL8139 card configuration on the console.
| |||||||
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. |
|
The RTL8139 device structure.
|
|
A receive packet structure.
|
|
A transmitted packet structure.
|
|
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 } |
|
The RTL8139 interrupt handler routine. It is invoked every time that an ethernet packet is received or when a packet has been transmitted.
Definition at line 626 of file rtl8139.c.
00627 { 00628 uint16_t status; 00629 00630 out16(rtl->iobase + IntrMask, 0); 00631 00632 status = in16(rtl->iobase + IntrStatus); 00633 // Acknowledge all known interrupts // 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 // #ifdef DEBUG 00642 else 00643 kprintf("\n\rRTL8139: unknown interrupt: isr = %#010x\n", status); 00644 // #endif 00645 00646 // Re-enable interrupts from the RTL8139 card // 00647 out16(rtl->iobase + IntrStatus, status & (RxFIFOOver | RxOverflow | RxOK)); 00648 out16(rtl->iobase + IntrMask, IntrDefault); 00649 } |
|
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 } |
|
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 } |