| | 1 | = GIET-VM / NIC_MNC Driver = |
| | 2 | |
| | 3 | [[PageOutline]] |
| | 4 | |
| | 5 | 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. |
| | 6 | |
| | 7 | This driver supports the vci_master_nic component, that is a Gigabit Ethernet network controller. |
| | 8 | |
| | 9 | This component has a DMA capability, to access the memory mapped RX and TX ethernet packets queues. |
| | 10 | These queues are implemented by a chained buffers structure, called NIC_CHBUF, and implemented by the ''nic_chbuf_t'' structure. |
| | 11 | |
| | 12 | 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. |
| | 13 | |
| | 14 | The Ethernet packet length can have any value, between 64 to 1538 bytes. |
| | 15 | 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. |
| | 16 | The first 34 words of a container are the container header : |
| | 17 | | word0 | NB_WORDS | NB_PACKETS | |
| | 18 | | word1 | PLEN[0] | PLEN[1] | |
| | 19 | | ... | ....... | ........ | |
| | 20 | | word33 | PLEN[64] | PLEN[65] | |
| | 21 | 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. |
| | 22 | |
| | 23 | 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". |
| | 24 | * desc[25:0] contain bits[31:6] of the status physical address. |
| | 25 | * desc[51:26] contain bits[31:6] of the buffer physical address. |
| | 26 | * desc[63:52] contain the common 12 physical address extension bits. |
| | 27 | |
| | 28 | 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. |
| | 29 | |
| | 30 | 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). |
| | 31 | |
| | 32 | The actual number of channels is defined by the NB_NIC_CHANNELS parameter in the ''hard_config.h'' file, and |
| | 33 | the SEG_NIC_BASE address must be defined in the hard_config.h file. |
| | 34 | |
| | 35 | The addressable registers map is defined [source:soft/giet_vm/giet_drivers/mnc_driver.h here]. |
| | 36 | |
| | 37 | == Access Functions == |
| | 38 | |
| | 39 | === 1) void '''_mnc_init'''( ) === |
| | 40 | This function allocates memory for the RX_CHBUF and TX_CHBUF, using a round-robin policy to have one CHBUF |
| | 41 | per cluster if the number of clusters is larger than 2 * NB_NIC_CHANNELS. It initialises both the CHBUF descriptors, |
| | 42 | and the hardware NIC registers. returns the value contained in a channel register. |
| | 43 | |
| | 44 | === 2) unsigned int '''_mnc_writable'''( unsigned int channel, unsigned int length ) === |
| | 45 | 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. |
| | 46 | The internal state of the queue (write pointer) can be modified if required. |
| | 47 | * '''channel''' : channel index |
| | 48 | * '''length''' : register index |
| | 49 | * return a non-zero value if packet can be written / return zero if queue is full. |
| | 50 | |
| | 51 | === 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 ) === |
| | 52 | 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. |
| | 53 | * '''channel''' : channel index |
| | 54 | * '''src_ip''' : source IP address (from IP header) |
| | 55 | * '''src_port''' : source port index (from TCP/UDP header) |
| | 56 | * '''src_ip''' : source IP address (from IP header) |
| | 57 | * '''src_port''' : source port index (from TCP/UDP header) |
| | 58 | * '''length''' : Ethernet packet length (bytes) |
| | 59 | * return a non-zero value if packet can be read / return zero if queue is empty. |
| | 60 | |
| | 61 | === 4) void '''_mnc_write'''( unsigned int channel , void * buffer , unsigned int length ) === |
| | 62 | This function writes an Ethernet packet in the TX queue defined by the channel argument. It should be called after the _mnc_writable() function. |
| | 63 | * '''channel''' : channel index |
| | 64 | * '''buffer''' : pointer on buffer containing packet |
| | 65 | * '''length''' : Ethernet packet length (bytes) |
| | 66 | |
| | 67 | === 5) int '''_mnc_read'''( unsigned int channel , void * buffer ) === |
| | 68 | This function read an Ethernet packet from the RX queue defined by the channel argument. It should be called after the _mnc_readable() function. |
| | 69 | * '''channel''' : channel index |
| | 70 | * '''buffer''' : pointer on buffer containing packet |
| | 71 | |
| | 72 | === 6) void '''_mnc_set_global_register( unsigned int index , unsigned int value ) === |
| | 73 | This function set a given value in a given NIC global register. |
| | 74 | * '''index''' : register index |
| | 75 | * '''value''' : value to be written |
| | 76 | |
| | 77 | === 7) unsigned int '''_mnc_get_global_register( unsigned int index ) === |
| | 78 | This function returns the value contained in a given NIC global register. |
| | 79 | * '''index''' : register index |
| | 80 | * return value |
| | 81 | |
| | 82 | == __ Interrupt Service Routines__ == |
| | 83 | |
| | 84 | === 8) void '''_nic_rx_isr'''( unsigned int irq_type, unsigned int irq_id, unsigned int channel ) === |
| | 85 | This interrupt Service Routine handles IRQs from a NIC_RX channel. |
| | 86 | WARNING : Not fully implemented yet : no IRQ acknowledge... |
| | 87 | |
| | 88 | === 9) void '''_nic_tx_isr'''( unsigned int irq_type, unsigned int irq_id, unsigned int channel ) === |
| | 89 | This interrupt Service Routine handles IRQs from a NIC_TX channel. |
| | 90 | WARNING : Not fully implemented yet : no IRQ acknowledge... |