Preface
Rtl8139 may be the most popular network card currently. It is cheap and can be used in functions. Although the performance
Sometimes it is slightly inferior to Intel's eepro100, but because the price is too low, it is a small problem on the chip.
It is usually ignored.
The driver 8139too will be explained immediately. 8139 although the price is not high, some functions are available.
No. It has built-in Tranceiver that complies with the MII specifications. It can automatically determine the network type of the connection.
. It can also use DMA to directly store packets received on the network in the primary memory's slow zone. Similarly
The sent packets can also be transmitted to the network card using DMA. Therefore, although the 8139 chip only has a 2 k receiving buffer
And 2 k transmission buffer, its performance is still very good.
In addition to RealTek itself, many vendors also use the same kernel to produce 8139 compatible network chips,
Including
SMC 1211.
MPX 5030
Delta 8139
Addtron 8139
DfE 1, 538
There may be more.
Driver initialization
Like other drivers, when the driver loads data using insmod, the first called function is ini.
T_module, cleanuo_module will be called when rmmod is used for 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 );
}
This structure is not much different from the last sis900. Rtl8139_init_one is used to initialize a 8139
Chip. The biggest benefit of the PCI driver is that the PCI bus provides the configuration space
Store the IO address and interrupt number required by the driver.
Determine these resources.
Rtl8139_init_one calls rtl8139_init_board to initialize the chip. Basically, this chip is counted
It is an easy-to-use chip and can be used directly after basic PCI initialization. So rtl8139_init
_ One and rtl8139_init_board are mostly error checking actions.
Resources that will be used later.
I will take some important parts from rtl8139_init_board to describe them. For other parts, refer
Source code.
......
// Read the required resources from 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 );
......
......
// Reserve these resources
Rc = pci_request_regions (pdev, "8139too ");
Pci_set_master (pdev );
......
// Map the IO address to the memory
Ioaddr = ioremap (mmio_start, mmio_len );
Dev-> base_addr = (long) ioaddr;
TP-> mmio_addr = ioaddr;
......
// Reset the chip
Rtl_w8 (chipcmd, (rtl_r8 (chipcmd) & chip1_clear) | cmdreset );
/* Check that the chip has finished the reset .*/
For (I = 1000; I> 0; I --){
Barrier ();
Udelay (10 );
If (rtl_r8 (chipcmd) & cmdreset) = 0)
Break;
}
// Determine the chip version
......
The most important part in rtl8139_init_one is the following section:
Dev-> open = rtl8139_open;
Dev-> hard_start_xmit = rtl8139_start_xmit;
Dev-> stop = rtl8139_close;
Dev-> get_stats = rtl8139_get_stats;
Dev-> set_multicast_list = rtl8139_set_rx_mode;
Dev-> do_ioctl = mii_ioctl;
Dev-> tx_timeout = rtl8139_tx_timeout;
Dev-> watchdog_timeo = tx_timeout;
Dev-> IRQ = pdev-> IRQ;
Basically the same as the previously introduced function. Only ioremap
This function is used to map the io of the mmio_start start mmio_len length to the memory.
We can directly use the return value of the function for Io operations.
Generally, the value of mmio_start is an entity address located in the specified CPU address space. In a general architecture,
The hardware designer reserves a memory location for the memory ing device.
These devices allow the CPU to use the latches on it by calling memory. In some architectures that do not support I/O calls
.
For example, you can use
Unsigned int * ap = (unsigned int *) mmio_start + 0x100;
Printf ("register 0x100 = % x/N", * AP );
Next we will explain these functions one by one.
Start device -- rtl8139_open
This function is called when you use ifconfig. In this function, you must do the following:
Register the interrupt function rtl8139_interrupt
Allocate and initialize the receiving and transfer buffer required by 8139.
Generates a kernel thread to view the network connection status.
The third action is particularly special,
Rtl8139_start_xmit
This function will call when a packet is sent,
Static int rtl8139_start_xmit (struct sk_buff * SKB, struct net_device * Dev)
{
Entry = TP-> cur_tx % num_tx_desc;
8139 supports four Transport buffers. You must pick out the next buffer zone to use. Next, you must record the Buffer Zone
The physical address of the object is set to the memory of 8139.
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 code carefully handles the alignment problem, 8139 requires that the table address of the buffer must be aligned with 32 bits
RMB. That is to say, the address must be 4 out. If not, we must have another table address alignment 32.
The bitwise buffer, copy the data to it, and store the object table address of the new buffer in the temporary memory.
.
Rtl_w32 (txstatus0 + (Entry * sizeof (u32 )),
TP-> tx_flag | (SKB-> Len> = eth_zlen? SKB-> Len: eth_zlen ));
This program is used to set the packet length. A correct Ethernet packet must have at least 64-bit leaders.
Unfortunately, no matter how long it is, you can set it to deliver. The above program is determining the packet length.
At least eth_zlen is available.
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 previously explains that when the buffer zone is used up, the upper layer must be notified not to send packets again.
Rtl8139_set_rx_mode
This function is used to set the receiving mode. 8139 provides 64 sets of MAC address filters. Only those fi
The LTER address chip will use the interrupt notification CPU to handle the issue. In general, we only receive and 8139
Mac packets. Only programs like tcpdump want to receive other packets.
Rtl8139_interrupt
In the interrupt function, we must read the status code and then perform different tasks according to the status code instructions. We want to handle
The conditions are:
An error may occur because the receiving buffer is full, the transfer is incorrect, the bus is incorrect, and the receiving is incorrect. According
Different situations must be handled differently. If a transfer error occurs, send it again. If an error is received, only
Wait for the upper-layer protocol to discover and send packets again. If a pvci bus error occurs, you may need to reset the bus.
Receives the packet and calls rtl8139_rx_interrupt.
Call rtl8139_tx_interrupt After transmitting a packet
When a packet is received, we must notify the upper-layer protocol for pre-check.
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 typical receiving package program. First, use dev_alloc_skb to allocate a buffer with sufficient size.
. Skb_put will adjust the buffer size, and check that new packets are transmitted in the upper-layer protocol when netif_rx is used. In
The bottom half of bh_net will process the packet later.
When a packet is transferred, we must release the buffer zone. This task works in rtl8139_tx_interrupt.
Finished. At this time, we must call the upper-layer protocol to indicate that new packets can be transferred. The reason for this is as follows in rtl8139
_ Tx_interrupt: The final program is completed.
If (TP-> dirty_tx! = Dirty_tx ){
TP-> dirty_tx = dirty_tx;
If (netif_queue_stopped (Dev ))
Netif_wake_queue (Dev );
}
We are careful not to call netif_wake_queue too many times, only when the device is full because of the buffer zone and there is a new
The netif_wake_queue is called only when packets are sent.
Conclusion
In fact, I still have a lot of details, such as MII processing, error processing, and EEPROM processing.
I will leave it for you to study on your own. If someone is interested in adding these details, I would be happy to add them to the article.