Foreword
RTL8139 may be the most popular network card, which is cheap and functions. Although in performance
Sometimes I will be slightly unpletely EEPRO100, but because the price is too cheap, there is a little problem on the chip.
It is usually negligible.
Narcitation, immediately explain the 8139too driver. Although the price is not high, the function is a bit
Nor lack. It built TRANCEIVER in accordance with MII specifications, which can automatically determine the connection network is the type.
. It can also use DMA to directly use the encapsulated package on the network located in the network, the same, to be passed
The package can also be transferred to the network card using DMA. So although only 2K receiving buffers on the 8139 chip
The transfer buffer of 2K is still very good.
In addition to Realtek itself, many manufacturers also produce and 8139 compatible network chips using the same kernel.
included
SMC 1211
MPX 5030
Delta 8139
Addtron 8139
DFE 538
There may be more.
Driver initialization
Like other drivers, the first first call function is ini when using INSMOD load.
T_Module, clenaryuo_module will be called when using RMMOD removal. In init_module, we
Registered a PCI driver
STATIC STRUCT PCI_DRIVER RTL8139_PCI_Driver = {
Name: MODNAME,
ID_TABLE: RTL8139_PCI_TBL,
Probe: RTL8139_INIT_ONE,
REMOVE: RTL8139_Remove_one,
Suspend: RTL8139_SUSPEND,
Resume: RTL8139_RESUME,
}
Static int __init RTL8139_INIT_MODULE (VOID)
{
RETURN PCI_Module_init (& RTL8139_PCI_Driver);
}
The SIS900 introduced by this structure is not large. RTL8139_INIT_ONE is used to initialize an 8139
chip. The biggest benefit of the PCI driver is that PCI BUS provides configuration space (Configuration Space)
Information such as the IO address required to store drivers and interrupt numbers, we don't have to refer to it like ISA drivers.
These resources are set.
RTL8139_INIT_ONE will call RTL8139_INIT_BOARD to initialize the chip, basically 8139 this chip calculation
It is a very easy-to-use chip that can be used directly after the basic PCI initialization. So RTL8139_INIT
_ONE and RTL8139_INIT_BOARD In fact, most of them are doing some errors, and by the PCI form
I have to use the resources you will use later.
I take out some important pieces from RTL8139_INIT_BOARD to explain, please refer to yourself
Source code.
......
// read the required resources by the PCI subsystem
MMIO_START = PCI_Resource_Start (PDEV, 1);
MMIO_END = PCI_Resource_END (PDEV, 1);
MMIO_FLAGS = PCI_Resource_Flags (PDEV, 1);
MMIO_LEN = PCI_Resource_Len (PDEV, 1);
......
......
// keep these resources down
RC = PCI_Request_Regions (PDEV, "8139too");
PCI_SET_MASTER (PDEV); ......
// Transfer the IO site to the memory
IOADDR = IOREMAP (MMIO_START, MMIO_LEN);
DEV-> BASE_ADDR = (long) oaddr;
TP-> MMIO_ADDR = IOADDR;
......
// Reset the chip
RTL_W8 (CHIPCMD, (RTL_R8 (CHIPCMD) & chipcmdclear) | cmdreset;
/ * Check what the chip Has finished the reset. * /
For (i = 1000; I> 0; I -) {
Barrier ();
Udelay (10);
IF ((RTL_R8 (ChiPCMD) & cmdreset) == 0)
Break;
}
/ / Judgment the emblem of the chip
......
The most important thing in RTL8139_INIT_ENE is the following paragraph
DEV-> open = r r;
Dev-> hard_start_xmit = rtl8139_start_xmit;
DEV-> stop = RTL8139_Close;
DEV-> GET_STATS = RTL8139_GET_STATS;
DEV-> set_multicast_list = r r 88;
DEV-> do_ioctl = mii_ioctl;
DEV-> TX_TIMEOUT = RTL8139_TX_TIMEOUT;
DEV-> Watchdog_timeo = tx_timeout;
DEV-> IRQ = PDEV-> IRQ;
Basically, the function introduced is basically the same, and it is no longer repeated here. The above is particularly possible with only ioremap
This function, its use is to map MMIO_START to the IO of the MMIO_LEN length to the memory, then
We can use the transfer value of the function to do the action of IO.
In general, the value of MMIO_START is an entity address located in the CPU address space, under the general architecture,
Hardware designers will retain a memory location to use Memory-Mapped Device.
These devices allow the CPU to use the scratcher on the memory to call, in some architectures that are not supported by IO
In these unique methods of acquiring the device scratcher.
For example, if you want to call the No. 100 Transmission, you can use
Unsigned int * ap = (unsigned int *) mmio_start 0x100;
Printf ("Register 0x100 =% x / n", * AP);
Next, we explain these functions one by one.
Start device - RTL8139_Open
This function will call when you use ifconfig, in this function, you have to do the following
Registered interrupt function RTL8139_INTERRUPT
Assign and initialize the received and transfer buffers required for 8139.
Generate a KERNEL THREAD to view the status of network connection
The more special is the third action,
RTL8139_START_XMIT
This function will call when sending a package.
Static int RTL8139_START_XMIT (STRUCT SK_BUFF * SKB, STRUCT NET_DEVICE * DEV)
{
Entry = TP-> CUR_TX% NUM_TX_DESC;
8139 Supports four transfer buffers, you must pick out the next buffer. Next, you must set the physical address of the buffer memory to the 8139 terminus.
TP-> TX_INFO [ENTRY] .skb = SKB;
IF ((long) SKB-> DATA & 3) {/ * must use alignment buffer. * /
/ * TP-> TX_INFO [ENTRY]. mapping = 0; * /
Memcpy (TP-> TX_BUF [Entry], SKB-> DATA, SKB-> LEN);
RTL_W32 (TXADDR0 (Entry * 4),
TP-> TX_BUFS_DMA (TP-> TX_BUF [ENTRY] - TP-> TX_BUFS);
} else {
TP-> TX_INFO [Entry]. mapping =
PCI_map_single (TP-> PCI_DEV, SKB-> DATA, SKB-> LEN,
PCI_DMA_TODEVICE);
RTL_W32 (TXADDR0 (Entry * 4), TP-> TX_INFO [Entry]. Mapping);
}
The above program code is careful about the process of Alignment, 8139 requires the solvent to the solizes must be aligned with 32 bits.
yuan. That is to say, the address must be removed by 4. If you don't work, we must arrange another site alignment 32
Buffer of the position, copy the information to where, then store this new buffer solid solution to the scratch
.
RTL_W32 (TXSTATUS0 (Entry * SizeOf (U32)),
TP-> TX_FLAG | (SKB-> LEN> = Eth_zlen? SKB-> LEN: Eth_zlen);
This segment is used to set the length of the package, and a correct Ethernet packet must have at least 64-bit group lengths.
Unfortunately, 8139 doesn't care how long it is set. The above line program is determined to determine the length of the package
At least there is Eth_zlen.
DEV-> Trans_start = Jiffies;
Spin_lock_irq (& tp-> lock);
TP-> CUR_TX ;
IF ((tp-> cur_tx - num_tx_desc) == TP-> DIRTY_TX)
Netif_Stop_Queue (dev);
Spin_unlock_irq (& tp-> lock);
Return 0;
}
This has been explained before. When the buffer is used, it must be notified that the upper layer should not be sent again.
RTL8139_SET_RX_MODE
This function is used to set the received mode, and 8139 provides 64 sets of MAC location filter. Only in line with these FI
The LTER's location chip will be used to handle the CPU with an interrupt, in general, we only receive and 8139 itself
Mac matches the package. Only in programs like TCPDUMP will only want to receive other packets.
RTL8139_INTERRUPT
In the interrupt function, we must read the status code and do different things depending on the indication of the status code. We have to handle
Condition
An error may be that the receiving buffer is full, the transmission error is incorrect, and the BUS has an error, and an error occurred. according to
Different conditions must do different processing. If you send an error, send it again. If the received error, it may only
Waiting for the upper level agreement to discover and re-seal the package. If it is a PVCI BUS error, you may have to reset the BUS. Receive a packet, call RTL8139_RX_InterRupt
Transfer a package, call RTL8139_TX_Interrupt
When a packet is received, we must notify the upper agreement pre-inspection process.
SKB = dev_alloc_skb (pkt_size 2);
IF (SKB) {
SKB-> DEV = DEV;
SKB_RESERVE (SKB, 2); / * 16 Byte Align The IP Fields. * /
Eth_copy_and_sum (SKB, & RX_RING [RING_OFFSET 4], PKT_SIZE, 0);
SKB_PUT (SKB, PKT_SIZE);
SKB-> Protocol = Eth_Type_Trans (SKB, DEV);
Netif_Rx (SKB);
DEV-> Last_Rx = Jiffies
TP-> stats.rx_bytes = pkt_size;
TP-> Stats.rx_packets ;
} else {
This program is a very typical receiving package program, first assign a sufficiently size buffer using dev_alloc_skb.
. SKB_PUT adjusts the size of the buffer, and it is related to the new packet incoming informs the upper level agreement with Netif_Rx. in
This package will be processed by BH_NET this Bottom Half later.
When a packet is delivered, we must release the buffer. This work is in RTL8139_TX_INTERRUPT
Completed, at this time we have to call the upper level agreement indicating that the new package can be transmitted. This thing is listed in RTL8139
_TX_INTERRUPT final procedure complete
IF (tp-> dirty_tx! = dirty_tx) {
TP-> DIRTY_TX = DIRTY_TX;
IF (Netif_Queue_Stopped (dev))
Netif_wake_queue (dev);
}
We are careful to avoid calling too many Netif_Wake_Queue, only in the device, because the buffer is full and new
The package is to call Netif_Wake_Queue when it is transmitted.
Conclusion
In fact, I still have a lot of details, such as MII processing, wrong processing and EEPROM processing, these
Leave it to everyone. If someone is interested, I will make these details, I am happy to join them in the article.