/*
 * 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 <device.h>
#include <hal_types.h>

/********************************************************************************************
 * This driver supports both the Soclib VciMultiNic component, that is a GMII compliant
 * Gigabit Ethernet controler, and the associated VciChbufDma component, that is a chained
 * buffers DMA controler, in charge of moving packets between the NIC hardware buffers,
 * and the kernel memory buffers.
 *
 * - The VciMultiNic component supports N channels, indexed by the source IP address
 *   for the RX packets, and by the destination IP address for the TX packets. 
 * - The VciChbufDma component contains 2*N channels, to support the N TX queues,
 *   and the N RX  queues. 
 * 
 * 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.
 *
 * Each DMA TX or TX channel transfers an (infinite) stream of "containers" between 
 * the hardware "chbuf" contained in the VciMultiNic hardware components, and the software 
 * "chbuf" located in a given cluster kernel memory, and implementing the TX or RX queue.
 * Each NIC channel contains one two-containers RX chbuf, and one two-containers TX chbuf.
 *
 * 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 first 4 Kbytes contain the RX_0 container data
 * 	- The next  4 Kbytes contain the RX_1 container data
 * 	- The next  4 Kbytes contain the TX_0 container data
 * 	- The next  4 Kbytes contain the TX_1 container data
 * 	- The next  4 Kbytes contain the channel addressable registers:
 *      * NIC_RX_STS_0      : RX_0 status               (read/write)
 *      * NIC_RX_STS_1      : RX_1 status               (read/write)
 *      * NIC_TX_STS_0      : TX_0 status               (read/write)
 *      * NIC_TX_STS_1      : TX_1 status               (read/write)
 *      * NIC_RX_DESC_LO_0  : RX_0 descriptor low word  (read/write)
 *      * NIC_RX_DESC_HI_0  : RX_0 descriptor high word (read/write)
 *      * NIC_RX_DESC_LO_1  : RX_1 descriptor low word  (read/write)
 *      * NIC_RX_DESC_HI_1  : RX_1 descriptor high word (read/write)
 *      * NIC_TX_DESC_LO_0  : TX_0 descriptor low word  (read/write)
 *      * NIC_TX_DESC_HI_0  : TX_0 descriptor high word (read/write)
 *      * NIC_TX_DESC_LO_1  : TX_1 descriptor low word  (read/write)
 *      * NIC_TX_DESC_HI_1  : TX_1 descriptor high word (read/write)
 * 		* NIC_MAC_4         : MAC @ 32 LSB bits         (read_only)
 * 		* NIC_MAC_2         : MAC @ 16 MSB bits         (read_only)
 *      * NIC_RX_RUN        : RX channel X activated    (write_only)
 *      * NIC_TX_RUN        : TX channel X activated    (write_only)
 *
 * To access both the container status, and the data contained in the container, the DMA
 * 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.
 * Both the buffer address and its status address must be 64 bytes aligned.
 *******************************************************************************************/

/********************************************************************************************
 *       SOCLIB_NIC registers offset 
 *******************************************************************************************/

enum SoclibMultiNicHyperRegisters {
    NIC_G_VIS                        = 0,    * bitfield : bit N = 0 -> channel N disabled
    NIC_G_ON                         = 1,    * boolean : NIC component activated
    NIC_G_NB_CHAN                    = 2,    * Number of channels (read only)
    NIC_G_BC_ENABLE                  = 3,    * boolean : Enable Broadcast if non zero
    NIC_G_TDM_ENABLE                 = 4,    * boolean : TDM Scheduler if non zero
    NIC_G_TDM_PERIOD                 = 5,    * TDM time slot value
    NIC_G_BYPASS_ENABLE              = 6,    * boolean : Enable bypass for TX packets
    NIC_G_MAC_4                      = 8,    * channel mac address 32 LSB bits array[8]
    NIC_G_MAC_2                      = 16,   * channel mac address 16 MSB bits array[8]
    NIC_G_NPKT_RX_G2S_RECEIVED       = 32,   * number of packets received on GMII RX port
    NIC_G_NPKT_RX_G2S_DISCARDED      = 33,   * number of RX packets discarded by RX_G2S FSM

    NIC_G_NPKT_RX_DES_SUCCESS        = 34,   * number of RX packets transmited by RX_DES FSM
    NIC_G_NPKT_RX_DES_TOO_SMALL      = 35,   * number of discarded too small RX packets (<60B)
    NIC_G_NPKT_RX_DES_TOO_BIG        = 36,   * number of discarded too big RX packets (>1514B)
    NIC_G_NPKT_RX_DES_MFIFO_FULL     = 37,   * number of discarded RX packets fifo full
    NIC_G_NPKT_RX_DES_CRC_FAIL       = 38,   * number of discarded RX packets CRC32 failure

    NIC_G_NPKT_RX_DISPATCH_RECEIVED  = 39,   * number of packets received by RX_DISPATCH FSM
    NIC_G_NPKT_RX_DISPATCH_BROADCAST = 40,   * number of broadcast RX packets received
    NIC_G_NPKT_RX_DISPATCH_DST_FAIL  = 41,   * number of discarded RX packets DST MAC not found
    NIC_G_NPKT_RX_DISPATCH_CH_FULL   = 42,   * number of discarded RX packets for channel full

    NIC_G_NPKT_TX_DISPATCH_RECEIVED  = 43,   * number of packets received by TX_DISPATCH FSM
    NIC_G_NPKT_TX_DISPATCH_TOO_SMALL = 44,   * number of discarded too small TX packets (<60B)
    NIC_G_NPKT_TX_DISPATCH_TOO_BIG   = 45,   * number of discarded too big TX packets (>1514B)
    NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  = 46,   * number of discarded TX packets SRC MAC failed
    NIC_G_NPKT_TX_DISPATCH_BROADCAST = 47,   * number of broadcast TX packets received
    NIC_G_NPKT_TX_DISPATCH_BYPASS    = 48,   * number of bypassed TX->RX packets
    NIC_G_NPKT_TX_DISPATCH_TRANSMIT  = 49,   * number of transmit TX packets

    NIC_CHANNEL_SPAN                 = 0x2000,
};

enum SoclibMultiNicChannelRegisters 
{
    NIC_RX_STS_0              = 0,    * RX_0 status (full or empty)      (Read/Write)
    NIC_RX_STS_1              = 16,   * RX_1 status (full or empty)      (Read/Write)
    NIC_TX_STS_0              = 32,   * TX_0 status (full or empty)      (Read/Write)
    NIC_TX_STS_1              = 48,   * TX_1 status (full or empty)      (Read/Write)
    NIC_RX_DESC_LO_0          = 64,   * RX_0 descriptor low word         (Read/Write)
    NIC_RX_DESC_HI_0          = 65,   * RX_0 descriptor high word        (Read/Write)
    NIC_RX_DESC_LO_1          = 66,   * RX_1 descriptor low word         (Read/Write)
    NIC_RX_DESC_HI_1          = 67,   * RX_1 descriptor high word        (Read/Write) 
    NIC_TX_DESC_LO_0          = 68,   * TX_0 descriptor low word         (Read/Write)
    NIC_TX_DESC_HI_0          = 69,   * TX_0 descriptor high word        (Read/Write) 
    NIC_TX_DESC_LO_1          = 70,   * TX_1 descriptor low word         (Read/Write)
    NIC_TX_DESC_HI_1          = 71,   * TX_1 descriptor high word        (Read/Write) 
    NIC_MAC_4                 = 72,   * channel mac address 32 LSB bits  (Read Only)
    NIC_MAC_2                 = 73,   * channel mac address 16 LSB bits  (Read Only)
    NIC_RX_RUN                = 74,   * RX packets can be received       (write_only)
    NIC_TX_RUN                = 75,   * TX packets can be transmitted    (write_only)
};



/********************************************************************************************
 * This structure defines the chained buffer descriptor, used to implement both
 * the RX and TX packets queues. Each buffer in a chbuf (called container) is a 4 Kbytes
 * buffer 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. and an array of set/reset
 * Moreover, It contains three pointers (cont_id, pkt_id, and word_id) that are private
 * variables used by the software thread to store the chbuf global state. 
 *******************************************************************************************/

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, alocates 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.
 ********************************************************************************************
 * @ dev     : extended pointer on the generic NIC device descriptor.
 *******************************************************************************************/
extern void soclib_nic_init( xptr_t dev );

/********************************************************************************************
 * This function implement the READ / WRITE / READABLE / WRITABLE commands.
 * - READABLE : returns in the command status a boolean true if a packet is available.
 *   It 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 boolean true if a packet with a given length
 *   can be written in the TX queue. It update the RX queue read pointer if required.
 * - WRITE : move a packet from the command buffer to the TX queue. The WRITABLE command
 *   must be called before the WRITE command.
 *******************************************************************************************/
extern void soclib_nic_cmd();

/********************************************************************************************
 * TODO
 ********************************************************************************************
 * @ dev     : local pointer on the generic IOC device descriptor.
 *******************************************************************************************/
extern void soclib_nic_isr( device_t * dev );


#endif /* _BLOCK_H_ */
