/*
 * soclib_nic.h - SOCLIB_NIC (Network Interface Controler) driver definition.
 *
 * Author    Alain Greiner (2016)
 *
 * 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 <chdev.h>
#include <hal_kernel_types.h>

/********************************************************************************************
 * This driver supports the Soclib VciMasterNic component, that is a GMII compliant
 * multi-channels Gigabit Ethernet controler. 
 *
 * The VciMasterNic component supports up to 4 channels, indexed by the source IP address
 * for the RX packets, and by the destination IP address for the TX packets. 
 * 
 * The Ethernet packet length can have any value, between 64 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 the packet[i].
 *
 * Packets are stored in the (1024 - 34) following words, and the packets are word-aligned.
 *
 * The TX and RX queues are implemented as chained buffers, where each buffer is a 4 Kbytes
 * container. Each container is protected by a SET/RESET synchronisation variable. 
 * The structure implementing the chbuf descriptor is described below.
 *
 * To access both the container status, and the data contained in the container, 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.
 *******************************************************************************************/

/********************************************************************************************
 *       Addressable registers offsets 
 *******************************************************************************************/

enum SoclibMasterNicGlobalRegisters 
{
    NIC_G_RUN                        = 0,   /*! read_write : NIC component activated       */
    NIC_G_NB_CHANNELS                = 1,   /*! read_only  : number of channels            */
    NIC_G_BC_ENABLE                  = 2,   /*! read_write : broadcast enabled if non zero */ 
    NIC_G_PERIOD                     = 3,   /*! read-write : container status poll period  */
    NIC_G_MAC_4                      = 4,   /*! read-write : mac address 32 LSB bits       */
    NIC_G_MAC_2                      = 5,   /*! read-write : mac address 16 MSB bits       */

    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_DISPATCH_RECEIVED  = 17,  /*! number of packets received by RX_DISPATCH  */
    NIC_G_NPKT_RX_DISPATCH_BROADCAST = 18,  /*! number of broadcast RX packets received    */
    NIC_G_NPKT_RX_DISPATCH_DST_FAIL  = 19,  /*! number of discarded RX packets for DST MAC */
    NIC_G_NPKT_RX_DISPATCH_CH_FULL   = 20,  /*! number of discarded RX packets cont full   */

    NIC_G_NPKT_TX_DISPATCH_RECEIVED  = 41,  /*! number of packets received by TX_DISPATCH  */
    NIC_G_NPKT_TX_DISPATCH_TOO_SMALL = 42,  /*! number of discarded too small TX packets   */
    NIC_G_NPKT_TX_DISPATCH_TOO_BIG   = 43,  /*! number of discarded too big TX packets     */
    NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  = 44,  /*! number of discarded TX packets for SRC MAC */
    NIC_G_NPKT_TX_DISPATCH_BROADCAST = 45,  /*! number of broadcast TX packets received    */
    NIC_G_NPKT_TX_DISPATCH_TRANSMIT  = 46,  /*! number of transmit TX packets              */

    NIC_GLOBAL_SPAN                  = 64   /*! 256 bytes for global registers             */
};

enum SoclibMasterNicChannelRegisters 
{
    NIC_RX_STATUS             = 0,    /*! read-only  : RX channel status                   */
    NIC_RX_CHBUF_DESC_L0      = 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_TX_STATUS             = 8,    /*! read-only  : TX channel status                   */
    NIC_TX_CHBUF_DESC_L0      = 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_CHANNEL_SPAN          = 16    /*! 64 bytes per channel                             */
};
    


/********************************************************************************************
 * This structure defines the chained buffer descriptor, used to implement both
 * the RX and TX packets queues. Each buffer in a chbuf is a 4 Kbytes container
 * containing a variable number of packets. All containers are allocated in 
 * the same cluster as the associated NIC device descriptor. The chbuf descriptor contains:
 * - an array of container pointers cont[], used by the kernet threads to access the
 *   packets contained in the containers.
 * - an array of set/reset Boolean full[] used by both the software threads and 
 *   by the hardware FSMs for lock-less synchronisation. 
 * - an array of containers descriptors containing the physical addresses of the
 *   "full[i]" and "cont[i]" variables, used by the DMA FSMs. 
 * Moreover, It contains three pointers (cont_id, pkt_id, and word_id) that are private
 * variables used by the software thread to scan the chbuf. 
 *******************************************************************************************/

typedef struct nic_chbuf_s
{
    uint32_t * cont[CONFIG_NIC_CHBUF_DEPTH]; /*! container virtual base address            */
    uint32_t   full[CONFIG_NIC_CHBUF_DEPTH]; /*! Boolean : container full if non zero      */
    uint64_t   desc[CONFIG_NIC_CHBUF_DEPTH]; /*! container & status physical addresses     */
    uint32_t   cont_id;                      /*! current container index                   */
    uint32_t   pkt_id;                       /*! current packet index in container         */
    uint32_t   word_id;                      /*! first word of current packet              */
}
nic_chbuf_t;

/********************************************************************************************
 *        SOCLIB_NIC driver access functions 
 *******************************************************************************************/

/********************************************************************************************
 * This function initializes the SOCLIB_NIC hardware registers, allocates memory for
 * the RX and TX containers, 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.
 ********************************************************************************************
 * @ chdev  :  pointer on NIC chdev descriptor.
 *******************************************************************************************/
extern void soclib_nic_init( chdev_t * chdev );

/********************************************************************************************
 * This function implement the READ / WRITE / READABLE / WRITABLE commands for TX/RX queues.
 * These command don't access the NIC peripheral but only the TX and TX chbufs.
 * It must be executed by a dedicated kernel thread running in the cluster containing
 * the CHBUF implementing the TX/RX queues.
 * It implements also the SET_MAC, SET_BC, SET_RUN configuration commands, that directly
 * access the NIC peripheral registers.
 * - READABLE 
 *   Returns in the command "status" a non zero value if a packet is available in RX queue.
 *   Update the RX queue read pointer if required.
 * - READ 
 *   Move a packet from the RX queue to the command "buffer", and returns the packet
 *   "length" in the command. The READABLE command must be called before the READ command.
 * - WRITABLE 
 *   Returns in the command "status" a non zero value if a packet with a given "length"
 *   can be written in the TX queue. Update the RX queue read pointer if required.
 * - WRITE
 *   Move a packet of a given "length" from the command "buffer" to the TX queue.
 *   The WRITABLE command must be called before the WRITE command.
 * - SET_MAC 
 *   Set the values defined in the "length" and "status" command arguments,
 *   into the NIC_C_MAC4 and NIG_G_MAC2  registers.
 * - SET_BC
 *   Enable/disable broadcast packets, as defined in the "status" command argument,
 *   into the NIC_G_BC_ENABLE register.
 * - SET_RUN
 *   Enable/disable NIC, as defined in the "status" command argument, 
 *   into the NIC_G_RUN register.
 * @ dev_xp  : extended pointer on the generic NIC device descriptor.
 ********************************************************************************************
 $ @ thread_xp : extended pointer on client thread (containing the command arguments).
 *******************************************************************************************/
extern void soclib_nic_cmd( xptr_t thread_xp );

/********************************************************************************************
 * This ISR acknowledge the NIC_RX or NIC_TX channel ISR signaling that a new container
 * has beeen moved, and reactivate the corresponding server thread.
 * In case of address error reported by the NIC controler in accessing the kernel chbuf,
 * it goes to kernel panic.
 ********************************************************************************************
 * @ chdev     : local pointer on NIC chdev descriptor.
 *******************************************************************************************/
extern void soclib_nic_isr( chdev_t * chdev );


#endif /* _BLOCK_H_ */
