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

rtl8139.c File Reference

RTL8139C(L) single chip fast ethernet controller driver. More...

#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.
Parameters:
rtl  An indirect pointer to the RTL8139 structure. Must be passed as an indirect pointer because it will be modified inside this routine!!!


unsigned rtl8139_read_eeprom (rtl8139_t *rtl, unsigned location)
 Read RTL8139 informations from the EEPROM.
Parameters:
rtl  The RTL8139 structure.
location  The location in the EEPROM to read.
Returns:
The value read from the EEPROM.


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_reset (rtl8139_t *rtl)
 Reset the RTL8139 ethernet card.
Parameters:
rtl  The RTL8139 structure.


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;.


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.


void rtl8139_handle_tx (rtl8139_t *rtl)
 Handle a transmitted packet event.
Parameters:
rtl  The RTL8139 structure.


void rtl8139_handle_rx (rtl8139_t *rtl)
 Handle a received packet event.
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.

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



Variables

rtl8139_trtl = NULL
 Pointer to the RTL8139 structure.


Detailed Description

RTL8139C(L) single chip fast ethernet controller driver.

Author:
Andrea Righi <drizzt@inwind.it>
Date:
Last update: 2003-11-09
Note:
Copyright (©) 2003 Andrea Righi

Based on drivers/net/8139too.c from Linux. -Andrea Righi.

Definition in file rtl8139.c.


Enumeration Type Documentation

enum ChipCmdBits
 

Enumeration values:
CmdReset 
CmdRxEnb 
CmdTxEnb 
RxBufEmpty 

Definition at line 93 of file rtl8139.c.

00094 {
00095         CmdReset=0x10,
00096         CmdRxEnb=0x08,
00097         CmdTxEnb=0x04,
00098         RxBufEmpty=0x01,
00099 };

enum CSCRBits
 

Enumeration values:
CSCR_LinkOKBit 
CSCR_LinkChangeBit 
CSCR_LinkStatusBits 
CSCR_LinkDownOffCmd 
CSCR_LinkDownCmd 

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

enum IntrStatusBits
 

Interrupt Status Register bits.

Enumeration values:
PCIErr 
PCSTimeout 
CableLenChange 
RxFIFOOver 
RxUnderrun 
RxOverflow 
TxErr 
TxOK 
RxErr 
RxOK 
IntrDefault 

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

enum MediaStatusBits
 

Media Status Register bits.

Enumeration values:
MSRTxFlowEnable 
MSRRxFlowEnable 
MSRSpeed10 
MSRLinkFail 
MSRRxPauseFlag 
MSRTxPauseFlag 

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

enum MIIBMCRBits
 

Enumeration values:
BMCRReset 
BMCRSpeed100 
BMCRNWayEnable 
BMCRRestartNWay 
BMCRDuplex 

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

enum RTL8139_registers
 

Symbolic RTL8139 offsets to registers.

Enumeration values:
MAC0  Ethernet hardware address.
MAR0  Multicast filter.
TxStatus0  Transmit status: 4 32bit registers.
TxAddr0  Tx descriptors (also 4 32bit).
RxBuf 
RxEarlyCnt 
RxEarlyStatus 
ChipCmd 
RxBufPtr 
RxBufAddr 
IntrMask 
IntrStatus 
TxConfig 
RxConfig 
Timer  General-purpose counter.
RxMissed  24 bits valid, write clears.
Cfg9346 
Config0 
Config1 
TimerIntrReg  INTR if gp counter reaches this value.
MediaStatus 
Config3 
HltClk 
MultiIntr 
RevisionID  Revision of the RTL8139 chip.
TxSummary 
MII_BMCR 
MII_BMSR 
NWayAdvert 
NWayLPAR 
NWayExpansion 
DisconnectCnt 
FalseCarrierCnt 
NWayTestReg 
RxCnt  Packet received counter.
CSCR  Chip status and configuration register.
PhyParm1  Undocumented.
TwisterParm  Undocumented.
PhyParm2  Undocumented.

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

enum rx_mode_bits
 

Bits in Receive Configuration Register.

Enumeration values:
RxCfgWrap 
AcceptErr 
AcceptRunt 
AcceptBroadcast 
AcceptMulticast 
AcceptMyPhys 
AcceptAllPhys 

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

enum RxStatusBits
 

Receive Status Register bits.

Enumeration values:
RxMulticast 
RxPhysical 
RxBroadcast 
RxBadSymbol 
RxRunt 
RxTooLong 
RxCRCErr 
RxBadAlign 
RxStatusOK 

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

enum TxStatusBits
 

Transmit Status Register bits.

Enumeration values:
TxHostOwns 
TxUnderrun 
TxStatOK 
TxOutOfWindow 
TxAborted 
TxCarrierLost 

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


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_handle_rx rtl8139_t   rtl
 

Handle a received packet event.

Parameters:
rtl  The RTL8139 structure.

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 }

void rtl8139_handle_tx rtl8139_t   rtl
 

Handle a transmitted packet event.

Parameters:
rtl  The RTL8139 structure.

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 }

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 }

unsigned rtl8139_read_eeprom rtl8139_t   rtl,
unsigned    location
[static]
 

Read RTL8139 informations from the EEPROM.

Parameters:
rtl  The RTL8139 structure.
location  The location in the EEPROM to read.
Returns:
The value read 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 }

void rtl8139_reset rtl8139_t   rtl
 

Reset the RTL8139 ethernet card.

Parameters:
rtl  The RTL8139 structure.

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 }

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 }


Variable Documentation

rtl8139_t* rtl = NULL
 

Pointer to the RTL8139 structure.

Definition at line 184 of file rtl8139.c.


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