| 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... |