/* * soclib_nic.h - SOCLIB_NIC (Network Interface Controler) driver definition. * * Author Alain Greiner (2016,2017,2018,2019,2020) * * Copyright (c) UPMC Sorbonne Universites * * This file is part of ALMOS-MKH. * * ALMOS-MKH is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2.0 of the License. * * ALMOS-MKH is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ALMOS-MKH; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _SOCLIB_NIC_H_ #define _SOCLIB_NIC_H_ #include #include /******************************************************************************************** * This driver supports the Soclib VciMasterNic component, that is a GMII compliant * multi-channels Gigabit Ethernet controler with a DMA capability. * * To improve the throughput, this component supports several channels. * The channel index is derived from the (source) remote IP address and port * for the received (RX) packets, and from the (destination) remote IP address * and port for the sent (TX) packets. The actual number of channels is an * hardware parameter that cannot be larger than 8. * * The Ethernet packet length can have any value, in range [42,1538] bytes. * * For each channel, the received packets (RX) and the sent packets (TX) are stored * in two memory mapped software FIFOs, called NIC_TX_QUEUE and NIC_RX_QUEUE, implemented * as chained buffers (chbuf). Each slot in these FIFOs is a container, containing one * single packet. The number of containers, defining the queue depth, is a software defined * parameter. The data transfer unit between is a container (one single packet). * * - The "container" structure contains a 2040 bytes data buffer, the packet length, and * the container state : full (owned by the reader) / empty (owned by the writer). * For each container, the state variable is used as a SET/RESET flip-flop to synchronize * the software server thread, and the hardware NIC DMA engines. * * - The "chbuf" descriptor contains an array of local pointers on the containers, used * by the software driver, an array of physical addresses, used by the DMA engines and * two "pointers", defining the current container to be written (wid) by the writer, * and the current container to be read (rid) by the reader. * * WARNING : Both the chbuf descriptor (containing the and wid> indexes), and the * containers themselve containing the and the are shared variables * accessed by the server threads (accessing the L2 caches), and by the NIC_DMA * engines (accessing directly the L3 caches). * Therefore, the L2/L3 cache coherence must be handled by this NIC driver for * the INIT, READ & WRITE commands, using the MMC SYNC & INVAL commands. *******************************************************************************************/ /******************************************************************************************** * This section defines the NIC device addressable registers offsets: * - The 8 channels registers are stored in the first 512 bytes (8 * 64 bytes). * - The global registers are stored in the next 256 bytes (global offset is 512 bytes). * All values defined below are number of words (one word = 4 bytes). *******************************************************************************************/ enum SoclibMasterNicGlobalRegisters { NIC_G_CHANNELS = 1, /*! read_only : number of channels */ NIC_G_NPKT_RESET = 2, /*! write-only : reset packets counters */ NIC_G_NPKT_RX_G2S_RECEIVED = 10, /*! number of packets received */ NIC_G_NPKT_RX_G2S_DISCARDED = 11, /*! number of RX packets discarded by RX_G2S */ NIC_G_NPKT_RX_DES_SUCCESS = 12, /*! number of RX packets transmited by RX_DES */ NIC_G_NPKT_RX_DES_TOO_SMALL = 13, /*! number of discarded too small RX packets */ NIC_G_NPKT_RX_DES_TOO_BIG = 14, /*! number of discarded too big RX packets */ NIC_G_NPKT_RX_DES_MFIFO_FULL = 15, /*! number of discarded RX packets fifo full */ NIC_G_NPKT_RX_DES_CRC_FAIL = 16, /*! number of discarded RX packets CRC32 */ NIC_G_NPKT_RX_DISP_RECEIVED = 17, /*! number of packets received by RX_DISPATCH */ NIC_G_NPKT_RX_DISP_DST_FAIL = 18, /*! number of discarded RX packets for DST MAC */ NIC_G_NPKT_RX_DISP_CH_FULL = 19, /*! number of discarded RX packets cont full */ NIC_G_NPKT_TX_DISP_RECEIVED = 41, /*! number of packets received by TX_DISPATCH */ NIC_G_NPKT_TX_DISP_TOO_SMALL = 42, /*! number of discarded too small TX packets */ NIC_G_NPKT_TX_DISP_TOO_BIG = 43, /*! number of discarded too big TX packets */ NIC_G_NPKT_TX_DISP_TRANSMIT = 44, /*! number of discarded TX packets for SRC MAC */ NIC_GLOBAL_OFFSET = 128, /*! 512 bytes reserved for channel registers */ }; enum SoclibMasterNicChannelRegisters { NIC_RX_CHANNEL_RUN = 0, /*! write-only : RX channel activation/desactivation */ NIC_RX_CHBUF_DESC_LO = 1, /*! read-write : RX chbuf descriptor 32 LSB bits */ NIC_RX_CHBUF_DESC_HI = 2, /*! read-write : RX chbuf descriptor 32 MSB bits */ NIC_RX_CHBUF_NBUFS = 3, /*! read-write : RX chbuf depth (number of buffers) */ NIC_RX_CHANNEL_STATE = 4, /*! read-only : RX channel status */ NIC_TX_CHANNEL_RUN = 8, /*! write-only : TX channel activation */ NIC_TX_CHBUF_DESC_LO = 9, /*! read-write : TX chbuf descriptor 32 LSB bits */ NIC_TX_CHBUF_DESC_HI = 10, /*! read-write : TX chbuf descriptor 32 MSB bits */ NIC_TX_CHBUF_NBUFS = 11, /*! read-write : TX chbuf depth (number of buffers) */ NIC_TX_CHANNEL_STATE = 12, /*! read-only : TX channel status */ NIC_CHANNEL_SPAN = 16 /*! 64 bytes per channel */ }; /******************************************************************************************** * Return values for the RX/TX channel master FSM status *******************************************************************************************/ enum SoclibMasterNicStatusValues { NIC_CHANNEL_STATUS_IDLE = 0, NIC_CHANNEL_STATUS_ERROR = 1, NIC_CHANNEL_STATUS_BUSY = 2, // busy for any value >= 2 }; /******************************************************************************************** * This structure defines the chbuf descriptor, used to implement both the RX and TX packets * queues. Each container contains one single packet, and has only two states (full/empty). * All containers are allocated in the same cluster as the associated NIC chdev descriptor. * The chbuf descriptor contains: * - an array of containers physical addresses cont_pad[], used by the DMA engines. * - an array of container pointers cont_ptr[], used by the kernel threads. * - two indexes rid and wid, defining the next container for read & write respectively. * WARNING : dont modify this structure, used by the DMA engines. *******************************************************************************************/ #define SOCLIB_NIC_CHBUF_DEPTH 8 typedef struct nic_chbuf_s { uint32_t wid; /*! current container write index */ uint32_t rid; /*! current container read index */ uint64_t cont_pad[SOCLIB_NIC_CHBUF_DEPTH]; /*! containers physical base addresses */ uint32_t * cont_ptr[SOCLIB_NIC_CHBUF_DEPTH]; /*! containers virtual base addresses */ } nic_chbuf_t; /******************************************************************************************** * This structure defines the container descriptor format. *******************************************************************************************/ typedef struct nic_cont_s { uint8_t buf[2040]; /*! Ethernet packet (42 to 1538 bytes */ uint32_t length; /*! actual packet length in bytes */ uint32_t state; /*! zero == empty / non zero == full */ } nic_cont_t; /******************************************************************************************** * Driver access functions *******************************************************************************************/ /******************************************************************************************** * This function initializes the SOCLIB_NIC hardware registers, for one NIC chdev * (one direction of one channel). It allocates memory for the RX and TX containers, * it allocates and initializes the RX and TX chbuf descriptors. * It allocates one WTI mailbox for the IRQ signaling availability of an RX full container, * or a TX empty container, and route the WTI IRQ to the core running the server thread. * It activates the TX and RX DMA engines. ******************************************************************************************** * @ chdev : pointer on NIC chdev descriptor. *******************************************************************************************/ extern void soclib_nic_init( chdev_t * chdev ); /******************************************************************************************** * 1) This function implement the READ & WRITE commands, used by the local server threads * to access the NIC_TX & NIC_RX packets queues. These commands don't access the NIC * registers but only the TX and RX chbufs implementing the queues: * * * Move a packet from the NIC_RX queue to the command "buffer". * Return 0 in "status" if queue empty / return length in "status" if success. * * * Move a packet of a given "length" from the command "buffer" to the TX queue. * Return 0 in "status" if queue full / return length in "status" if success. * * 2) It implements the GET_KEY / SET_RUN / GET_INSTRU / CLEAR_INSTRU commands, * directly called by any thread running in any cluster to access the NIC registers : * * * Return in "status" argument the channel index (key) computed from the IP address * defined in the "buffer" argument, and from the port defined by the "length" argument. * * * Enable/disable the NIC_TX_CHANNEL_RUN & NIC_RX_CHANNEL_RUN registers.The channel * is defined in the "length" argument / run value defined in the "status" argument. * * * Display on kernel TXT0 the contaent of all NIC instrumentation registers. * * * Reset all NIC instrumentation registers. * * Note (i) For the NIC device, the command arguments are always registered in the calling * thread descriptor (i.e. the calling thread is always the client thread). * Note (ii) The actual command mnemonics are defined in the file. *******************************************************************************************/ extern void soclib_nic_cmd( xptr_t thread_xp ); /******************************************************************************************** * This ISR is executed when a new RX container has been moved to an empty TX queue, * or when a TX container has been removed from a full TX queue. In both cases, it * reactivate the corresponding server thread from the BLOCKED_ISR condition. * It is also executed in case of error reported by the DMA engines accessing the TX or RX * queues. It simply print an error message on the kernel terminal. * TODO improve this error handling... ******************************************************************************************** * @ chdev : local pointer on NIC chdev descriptor. *******************************************************************************************/ extern void soclib_nic_isr( chdev_t * chdev ); #endif /* _BLOCK_H_ */