= GIET-VM / NIC_MNC Driver = [[PageOutline]] The [source:soft/giet_vm/giet_drivers/mnc_driver.c mnc_driver.c] and [source:soft/giet_vm/giet_drivers/mnc_driver.h 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 [source:soft/giet_vm/giet_drivers/mnc_driver.h 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 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[25:0] contain bits[31:6] of the status physical address. * desc[51:26] contain bits[31:6] 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 is defined by the NB_NIC_CHANNELS parameter in the ''hard_config.h'' file, and the SEG_NIC_BASE address must be defined in the hard_config.h file. The addressable registers map is defined [source:soft/giet_vm/giet_drivers/mnc_driver.h here]. == __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_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) unsigned int '''_mnc_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. === 4) void '''_mnc_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) void '''_mnc_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 === 6) 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 === 7) 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__ == === 8) 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. === 9) 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.