wiki:mnc_driver

GIET-VM / NIC_MNC Driver

The mnc_driver.c and mnc_driver.h files define the NIC_MNC driver.

This driver supports the vci_master_nic component, that is a Gigabit Ethernet network controller.

This component has a DMA capability, to access the memory mapped RX and TX ethernet packets queues. These queues are implemented as the chained buffers structure nic_chbuf_t, defined here .

It can exist only one Ethernet network controller in the architecture, but to improve the throughput, it supports up to 4 channels (i.e. 4 TX and 4 RX queues), indexed by a key depending on the source IP address for the RX packets, and depending on the destination IP address for the TX packets. All channels use the same source MAC address.

The Ethernet packet length can have any value, from 60 to 1538 bytes. The data transfer unit between software and the NIC is a 4 Kbytes "container", containing an integer number of variable size packets. The max number of packets in a container is 66 packets. The first 34 words of a container are the container header :

word0 NB_WORDS NB_PACKETS
word1 PLEN[0] PLEN[1]
... ....... ........
word33 PLEN[64] PLEN[65]

NB_PACKETS is the actual number of packets in the container, NB_WORDS is the number of useful words in the container, PLEN[i] is the number of bytes for packet[i]. Packets are stored in the (1024 - 34) following words, and are word-aligned.

Each 4 Kbytes container is protected by a SET/RESET status synchronisation variable. To access both the container status, and the container itself, the NIC uses two physical addresses, that are packed in a 64 bits "container descriptor".

  • desc[31:0] contain bits[31:0] of the status physical address.
  • desc[51:32] contain bits[31:12] of the buffer physical address.
  • desc[63:52] contain the common 12 physical address extension bits.

To each TX or RX queue is associated a kernel thread that is in charge of moving the infinite stream of containers between the NIC and the RX/TX queue.

The RX/TX queues (and the associated kernel threads) are physically distributed on various clusters, using a round robin policy (modulo the number of clusters).

The actual number of channels NB_NIC_CHANNELS parameter, and the segment SEG_NIC_BASE address must be defined in the hard_config.h file.

The addressable registers map is defined here.

TX/RX queues

The following structure defines the chained buffer descriptor, used by the MNC driver to implement both the NIC_RX_QUEUE and NIC_TX_QUEUE. Each buffer is a 4K bytes container containing a variable number of packets. All containers are allocated in the same cluster.

typedef struct nic_chbuf_s
{
    unsigned long long desc[NIC_CHBUF_DEPTH];  
    unsigned int *     cont[NIC_CHBUF_DEPTH];  
    unsigned int       full[NIC_CHBUF_DEPTH];  
    unsigned int       cont_id;                
    unsigned int       pkt_id;               
    unsigned int       word_id;             
    unsigned int       timeout;              
} 
nic_chbuf_t;

The chbuf descriptor contains:

  • an array of container pointers cont[], used by the kernel thread to access the packets contained in the containers.
  • an array of set/reset Boolean full[], used by both the kernel thread and by the hardware FSM for lock-less synchronisation.
  • an array of containers descriptors desc[], containing the physical addresses of the full[i] and cont[i] variables, is used by the NIC FSM.
  • the cont_id variable defines the current container for the kernel thread.
  • the pkt_id variable defines the current packet index for the kernel thread.
  • the word_id variable defines the current word index for the kernel thread.
  • the timeout variable defines the number of timeout checks for the kernel thread.

The container descriptor is a 64 bits containing three fields:

  • the 26 LSB bits contain bits[31:6] of the status physical address.
  • the 26 following bits contain bits[31:6] of the buffer physical address.
  • the 12 MSB bits contain the common address extension.

Three hardware parameters can be redefined if required. #define NIC_CHBUF_DEPTH 4 number of containers #define NIC_CHBUF_WIDTH 4096 single container size (bytes) #define NIC_CHBUF_TIMEOUT 10 max number of retry for a TX-CHBUF

Access Functions

1) void _mnc_init( )

This function allocates memory for the RX_CHBUF and TX_CHBUF implementing the RX and TX queues for all channels. It uses a round-robin policy, to distribute one CHBUF per cluster if the number of clusters is larger than 2 * NB_NIC_CHANNELS. It initialises both the CHBUF descriptors, and the hardware NIC registers.

2) unsigned int _mnc_tx_writable( unsigned int channel, unsigned int length )

This function returns a Boolean indicating if an Ethernet packet of a given length can be stored in the TX queue defined by the channel argument. The internal state of the queue (write pointer) can be modified if required.

  • channel : channel index
  • length : register index
  • return a non-zero value if packet can be written / return zero if queue is full.

3) void _mnc_tx_timeout( unsigned int channel )

This function implements a watch dog for the TX-QUEUE associated to a given channel: It must be periodically called to check that TX packets are not waiting indefinitely in a partially filled container. If the container state has not been modified after NIC_CHBUF_TIMEOUT checks, it releases the current container to the NIC hardware.

4) void _mnc_tx_write( unsigned int channel , char * buffer , unsigned int length )

This function writes an Ethernet packet in the TX queue defined by the channel argument. It should be called after the _mnc_writable() function.

  • channel : channel index
  • buffer : pointer on buffer containing packet
  • length : Ethernet packet length (bytes)

5) unsigned int _mnc_rx_readable( unsigned int channel , unsigned int * src_ip , unsigned int * src_port , unsigned int * dst_ip , unsigned int * dst_port , unsigned int * length )

This function returns a Boolean indicating if an Ethernet packet is available in the RX queue defined by the channel argument. It also returns various informations contained in the IP and TCP/UDP headers. The internal state of the queue (read pointer) can be modified if required.

  • channel : channel index
  • src_ip : source IP address (from IP header)
  • src_port : source port index (from TCP/UDP header)
  • src_ip : source IP address (from IP header)
  • src_port : source port index (from TCP/UDP header)
  • length : Ethernet packet length (bytes)
  • return a non-zero value if packet can be read / return zero if queue is empty.

6) void _mnc_rx_read( unsigned int channel , char * buffer )

This function read an Ethernet packet from the RX queue defined by the channel argument. It should be called after the _mnc_readable() function.

  • channel : channel index
  • buffer : pointer on buffer containing packet

7) void _mnc_set_global_register( unsigned int index , unsigned int value )

This function set a given value in a given NIC global register.

  • index : register index
  • value : value to be written

8) unsigned int _mnc_get_global_register( unsigned int index )

This function returns the value contained in a given NIC global register.

  • index : register index
  • return value

Interrupt Service Routines

1) void _mnc_rx_isr( unsigned int irq_type, unsigned int irq_id, unsigned int channel )

This Interrupt Service Routine handles IRQs from a NIC_RX channel.

2) void _mnc_tx_isr( unsigned int irq_type, unsigned int irq_id, unsigned int channel )

This Interrupt Service Routine handles IRQs from a NIC_TX channel.

Last modified 7 years ago Last modified on Jan 3, 2017, 1:39:27 PM