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 }
|
1.2.18