Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals   Related Pages  

RTL8139C(L) Fast Ethernet Controller
[Device Drivers]


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_tget_eth_mac_addr ()
 Get the MAC hardware address of the RTL8139 ethernet card.
Returns:
A pointer to the MAC address value.
Exceptions:
NULL  if a RTL8139 card has not been initialized.


rtl8139_tget_rtl8139_device ()
 Get the pointer of the RTL8139 device structure.
Returns:
  • a pointer of the RTL8139 structure if it has been initialized;
  • 0 if the RTL8139 card has not been initialized.


int send_rtl8139_packet (rtl8139_t *rtl, const void *data, size_t len)
 Send an ethernet packet to the physiscal layer.
Parameters:
rtl  The RTL8139 structure.
data  The data to be sent.
len  The size of the data to be sent in bytes.
Returns:
The number of bytes sent, or -1 if an error occurred.


int rtl8139_init (bool promisc)
 Initialize the RTL8139 driver.
Parameters:
promisc 
  • TRUE initialize the card and put it in promiscuous mode;
  • FALSE initialize the card and don't put it in promiscuous mode.
Returns:
  • 0 if we can successfully enable the RTL8139 ethernet card;
  • -ENXIO if the device if not present on PCI bus;
  • -EIO if we cannot read ethernet card informations;.


void rtl8139_close (rtl8139_t **rtl)
 Halt the RTL8139 card and free the logical device.
Parameters:
rtl  An indirect pointer to the RTL8139 structure. Must be passed as an indirect pointer because it will be modified inside this routine!!!


void rtl8139_promisc (rtl8139_t *rtl, bool on)
 Enable/disable the promiscuous mode for the RTL8139 card.
Parameters:
rtl  The RTL8139 structure.
on 
  • TRUE enable the promiscuous mode;
  • FALSE disable the promiscuous mode.


void rtl8139_dump_info (rtl8139_t *rtl)
 Print the current RTL8139 card configuration on the console.
Parameters:
rtl  The RTL8139 structure.


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.


Detailed Description

The RTL8139C(L) sinle chip fast ethernt controller driver.

Typedef Documentation

typedef struct rtl8139 rtl8139_t
 

The RTL8139 device structure.

typedef struct rxpacket rxpacket_t
 

A receive packet structure.

typedef struct txpacket txpacket_t
 

A transmitted packet structure.


Function Documentation

uint8_t* get_eth_mac_addr  
 

Get the MAC hardware address of the RTL8139 ethernet card.

Returns:
A pointer to the MAC address value.
Exceptions:
NULL  if a RTL8139 card has not been initialized.

Definition at line 455 of file rtl8139.c.

00456 {
00457         if (rtl)
00458                 return(rtl->station_address);
00459         else
00460                 return(NULL);
00461 }

rtl8139_t* get_rtl8139_device  
 

Get the pointer of the RTL8139 device structure.

Returns:
  • a pointer of the RTL8139 structure if it has been initialized;
  • 0 if the RTL8139 card has not been initialized.

Definition at line 468 of file rtl8139.c.

00469 {
00470         return( rtl );
00471 }

void rtl8139_close rtl8139_t **    rtl
 

Halt the RTL8139 card and free the logical device.

Parameters:
rtl  An indirect pointer to the RTL8139 structure. Must be passed as an indirect pointer because it will be modified inside this routine!!!

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 }

void rtl8139_dump_info rtl8139_t   rtl
 

Print the current RTL8139 card configuration on the console.

Parameters:
rtl  The RTL8139 structure.

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 }

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.

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 }

int rtl8139_init bool    promisc
 

Initialize the RTL8139 driver.

Parameters:
promisc 
  • TRUE initialize the card and put it in promiscuous mode;
  • FALSE initialize the card and don't put it in promiscuous mode.
Returns:
  • 0 if we can successfully enable the RTL8139 ethernet card;
  • -ENXIO if the device if not present on PCI bus;
  • -EIO if we cannot read ethernet card informations;.

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 }

void rtl8139_promisc rtl8139_t   rtl,
bool    on
 

Enable/disable the promiscuous mode for the RTL8139 card.

Parameters:
rtl  The RTL8139 structure.
on 
  • TRUE enable the promiscuous mode;
  • FALSE disable the promiscuous mode.

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 }

int send_rtl8139_packet rtl8139_t   rtl,
const void *    data,
size_t    len
 

Send an ethernet packet to the physiscal layer.

Parameters:
rtl  The RTL8139 structure.
data  The data to be sent.
len  The size of the data to be sent in bytes.
Returns:
The number of bytes sent, or -1 if an error occurred.

Todo:
Set up a timeout for the transmitted packets.

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 }


Generated on Fri Feb 20 15:32:22 2004 for Minirighi by doxygen1.2.18