RTL8139 LINUX source code analysis

xiaoxiao2021-03-06  20

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.

转载请注明原文地址:https://www.9cbs.com/read-47956.html

New Post(0)