Index: trunk/kernel/devices/dev_nic.h
===================================================================
--- trunk/kernel/devices/dev_nic.h	(revision 690)
+++ trunk/kernel/devices/dev_nic.h	(revision 1)
@@ -2,5 +2,5 @@
  * dev_nic.h - NIC (Network Controler) generic device API definition.
  * 
- * Author  Alain Greiner    (2016,2017,2018,2019,2020)
+ * Author  Alain Greiner    (2016)
  *
  * Copyright (c) UPMC Sorbonne Universites
@@ -25,176 +25,101 @@
 #define _DEV_NIC_H
 
-#include <kernel_config.h>
-#include <hal_kernel_types.h>
-#include <remote_busylock.h>
-#include <remote_buf.h>
-#include <xlist.h>
-
-/****  Forward declarations  ****/
-
-struct chdev_s;
+#include <almos_config.h>
+#include <hal_types.h>
 
 /*****************************************************************************************
  *     Generic Network Interface Controler definition
  *
- * This device provides access to a generic Gigabit Ethernet network controler.
- * It assumes that the NIC hardware peripheral handles two packets queues for sent (TX)
- * and received (RX) packets.
- *
- * The supported protocols stack is : Ethernet / IPV4 / TCP or UDP
+ * This device provide access to an external Gigabit Ethernet network controler.
+ * It assume that the NIC hardware peripheral handles two packets queues for sent (TX)
+ * and received (RX) packets. Packets are (Ethernet/IPV4).
  * 
- * 1) hardware assumptions
- *
- * The NIC device is handling two (infinite) streams of packets to or from the network. 
+ * The NIC device is handling an (infinite) stream of packets to or from the network. 
  * It is the driver responsibility to move the RX packets from the NIC to the RX queue,
  * and the TX packets from the TX queue to the NIC.
  *
- * AS the RX and TX queues are independant, there is one NIC_RX device descriptor 
- * to handle RX packets, and another NIC_TX device descriptor to handle TX packets.
- *
- * In order to improve throughput, the NIC controller can implement multiple (N) channels.
- * In this case, the channel index is defined by an hash function computed from the remote
- * IP address and port. This index is computed by the hardware for an RX packet, and is 
- * computed by the kernel for a TX packet, using a specific driver function. 
- * The 2*N chdevs, and the associated server threads implementing the protocols stack,
- * are distributed in 2*N different clusters.
- *
- * 2) User API
- * 
- * On the user side, ALMOS-MKH implements the POSIX socket API. 
- * The following kernel functions implement the socket related syscalls :
- * - socket_build()     : create a local socket registered in process fd_array[].
- * - socket_bind()      : attach a local IP address and port to a local socket.
- * - socket_listen()    : local server makes a passive open.
- * - socket_connect()   : local client makes an active open to a remote server.
- * - socket_accept()    : local server accept a new remote client.
- * - socket_send()      : send data on a connected socket.
- * - socket_recv()      : receive data on a connected socket.
- * - socket_sendto()    : send a packet to a remote (IP address/port). 
- * - socket_recvfrom()  : receive a paket from a remote (IP address/port).
- *
- * 3) NIC TX and NIC_RX server threads
- *
- * The dev_nic_tx_server() & dev_nic_rx_server() functions defined below execute 
- * the user commands stored in the sockets to implement the [ETH / IP / TCP or UDP] 
- * protocols stack, as defined in the <ksocket.c> and <ksocket.h> files.
- *
- * 4) NIC driver API
- *
- * The generic NIC device "driver" API defines the following commands, used by the
- * NIC_TX and NIC_RX server threads, running in the cluster containing the relevant chdev,
- * to access the NIC_TX and NIC_RX packets queues:
- *
- * - READ     : consume one packet from the NIC_RX queue.
- * - WRITE    : produce one packet to the NIC_TX queue.
- *
- * All RX or TX paquets are sent or received in standard 2 Kbytes kernel buffers,
- * that are dynamically allocated by the protocols stack. 
- * The actual TX an RX queues structures depends on the hardware NIC implementation,
- * and are defined in the HAL specific driver code. 
- *
- * Moreover, the generic NIC device "driver" API defines the following commands,
- * used directly by a client thread running in any cluster, to access the NIC device
- * configuration or status registers:
- *
- * - GET_KEY      : get channel index from remote IP address and port 
- * - SET_RUN      : activate/desactivate one channel (both directions)
- * - GET_INSTRU   : get one instrumentation counter value
- * - CLEAR_INSTRU : reset all instrumentation counters
+ * AS the RX and TX queues are independant, there is one NIC-RX device descriptor 
+ * to handle RX packets, and another NIC-TX device descriptor to handle TX packets.
+ * In order to improve throughput, the hardware NIC controller can optionnally implement
+ * multiple channels:
+ * - The RX channels are indexed by an hash key derived from the source IP address.
+ * - The TX channels are indexed by an hash key derived from the destination IP address.
+ * These 2*N devices, and 2*N associated server threads, are distributed in 2*N clusters.
+ * The  2*N server threads implement the protocols stack. The RX server threads block
+ * and deschedule when the RX queue is empty. The TX server stack block and deschedule
+ * when the queue is full. 
+ *
+ * It is the driver responsibily to re-activate a blocked server thread when
+ * the queue state is modified: not full for TX, or not empty for RX.
  *
  * WARNING: the WTI mailboxes used by the driver ro receive events from the hardware
  * (available RX packet, or available free TX slot, for a given channel), must be 
  * statically allocated during the kernel initialisation phase, and must be 
- * routed to the cluster containing the associated TX/RX chdev and server thread.
- *
+ * routed to the cluster containing the associated device descriptor and server thread.
+ * to simplify the server thread re-activation.
+ *
+ * Finally, the generic NIC device API defines the following commands:
+ * - READABLE : returns true if at least one RX paquet is available in RX queue.
+ * - WRITABLE : returns true if atleast one empty slot is available in TX queue.
+ * - READ     : consume one packet from the RX queue.
+ * - WRITE    : produce one packet fto the TX queue.
+ * All RX or TX paquets are sent or received in standard 2 Kbytes kernel buffers,
+ * that are dynamically allocated by the protocols stack. The structure pkd_t
+ * defining a packet descriptor is defined below, and contain the buffer pointer
+ * and the actual Ethernet packet Length.
+ *
+ * The actual TX an RX queues structures depends on the hardware NIC implementation,
+ * and are defined in the driver code. 
  *****************************************************************************************/
 
 /****  Forward declarations  ****/
 
-struct chdev_s;
-
-/*****************************************************************************************
- *   Various constants used by the protocols stack
- ****************************************************************************************/
-
-#define SRC_MAC_5              0x66         // This is a temporary short-cut for debug
-#define SRC_MAC_4              0x55
-#define SRC_MAC_3              0x44
-#define SRC_MAC_2              0x33
-#define SRC_MAC_1              0x22
-#define SRC_MAC_0              0x11
-
-#define DST_MAC_5              0x66         // This is a temporary short-cut for debug
-#define DST_MAC_4              0x55
-#define DST_MAC_3              0x44
-#define DST_MAC_2              0x33
-#define DST_MAC_1              0x22
-#define DST_MAC_0              0x11
-
-#define TCP_HEAD_LEN           20
-#define UDP_HEAD_LEN           8
-#define IP_HEAD_LEN            20
-#define ETH_HEAD_LEN           14
-
-#define PROTOCOL_UDP           0x11
-#define PROTOCOL_TCP           0x06
-
-#define TCP_FLAG_FIN           0x01
-#define TCP_FLAG_SYN           0x02
-#define TCP_FLAG_RST           0x04
-#define TCP_FLAG_PSH           0x08
-#define TCP_FLAG_ACK           0x10
-#define TCP_FLAG_URG           0x20
-
-/*****************************************************************************************
- * This structure defines the specific chdev extension for NIC device:
- * - queue : local pointer on the memory mapped queue of TX or RX packets, used
- *   by the NIC driver to move packets to/from the NIC hardware. The actual descriptor
- *   depends on the NIC implementation.
- * - root  : root of an xlist of sockets that are in the LISTEN state, waiting one or
- *   several TCP connection requests from remote processes. It is only used by the
- *   NIC_RX server thread attached to a NIC_RX chdev. 
- * - lock  : lock protecting concurrent access to the litening sockets list.
- ****************************************************************************************/
+struct device_s;
+
+/******************************************************************************************
+ * This defines the extension for the generic IOC device.
+ * The actual queue descriptor depends on the implementation.
+ *****************************************************************************************/
 
 typedef struct nic_extend_s
 {
-    void            * queue;    /*! pointer on NIC packets queue descriptor (RX or TX)  */
-    xlist_entry_t     root;     /*! root of listening sockets list (only used in RX[0]) */
-    remote_busylock_t lock;     /*! lock protecting this list  (only used in RX[0]      */
+    void     * queue;     /*! local pointer on the packets queue descriptor (RX or TX)   */
 }
 nic_extend_t;
 
-/*****************************************************************************************
+/******************************************************************************************
+ * This structure defines the Ethernet/IPV4 packet descriptor, that is sent to,
+ * or received from, the protocols stack.
+ *****************************************************************************************/
+
+typedef struct pkd_s
+{
+    char      * buffer;   /*! local pointer on 2 Kbytes buffer containing packet         */  
+    uint32_t    length;   /*! actual number of bytes                                     */
+}
+pkd_t;
+
+/******************************************************************************************
  * This enum defines the various implementations of the generic NIC peripheral.
  * This array must be kept consistent with the define in the arch_info.h file.
- ****************************************************************************************/
-
-typedef enum nic_impl_e
-{
-    IMPL_NIC_CBF =   0,     
+ *****************************************************************************************/
+
+enum nic_impl_e
+{
+    IMPL_NIC_SOC =   0,     
     IMPL_NIC_I86 =   1,
 }
 nic_impl_t;
 
-/****************************************************************************************
- * This defines the (implementation independant) commands to access the NIC hardware.
- * There is two types of commands
- * - The first 2 commands are used by the NIC_TX and NIC_RX server threads, and stored
- *   in the server thread descriptor, to access the NIC_RX & NIC_TX packet queues.
- *   The buffer is always a 2K bytes kernel buffer, containing an Ethernet packet.
- * - The next 4 synchronous commands are used by the client thread, and stored in the 
- *   client thread descriptor, to directly access the NIC registers. 
- ****************************************************************************************/
+/******************************************************************************************
+ * This defines the (implementation independant) command  passed to the NIC driver.
+ *****************************************************************************************/
 
 typedef enum nic_cmd_e
 {
-    NIC_CMD_WRITE        = 10,  /*! put one (given length) packet to TX queue           */
-    NIC_CMD_READ         = 11,  /*! get one (any length) packet from RX queue           */
-
-    NIC_CMD_GET_KEY      = 20,  /*! return channel index from IP address and port       */ 
-    NIC_CMD_SET_RUN      = 21,  /*! enable/disable one NIC channel                      */
-    NIC_CMD_GET_INSTRU   = 22,  /*! return one intrumentation register value            */
-    NIC_CMD_CLEAR_INSTRU = 23,  /*! reset all instrumentation registers                 */
+    NIC_CMD_WRITABLE = 0,  /*! test TX queue not full (for a given length packet)        */
+    NIC_CMD_WRITE    = 1,  /*! put one (given length) packet to TX queue                 */
+    NIC_CMD_READABLE = 2,  /*! test RX queue not empty (for any length packet)           */
+    NIC_CMD_READ     = 3,  /*! get one (any length) packet from RX queue                 */
 }
 nic_cmd_t;
@@ -202,137 +127,100 @@
 typedef struct nic_command_s
 {
-    xptr_t      dev_xp;       /*! extended pointer on NIC chdev descriptor              */
-    nic_cmd_t   type;         /*! command type                                          */
-    uint8_t   * buffer;       /*! local pointer on kernel buffer (when READ / WRITE)    */  
-    uint32_t    length;       /*! number of bytes in buffer (when READ / WRITE )        */
-    uint32_t    status;       /*! return value (depends on command type)                */
-    uint32_t    error;        /*! return an error from the hardware (0 if no error)     */
+    xptr_t      dev_xp;   /*! extended pointer on device descriptor                      */
+    nic_cmd_t   cmd;      /*! requested operation type                                   */
+    char      * buffer;   /*! local pointer on 2 Kbytes buffer containing packet         */  
+    uint32_t    length;   /*! actual number of bytes                                     */
+    bool_t      status;   /*! return true if writable or readable (depend on command)    */
+    uint32_t    error;    /*! return an error from the hardware (0 if no error)          */
 }
 nic_command_t;
 
 /******************************************************************************************
- * This function completes the NIC-RX and NIC-TX chdev descriptors initialisation.
- * namely the link with the implementation specific driver.
- * The func, impl, channel, is_rx, base fields have been previously initialised.
- * It calls the specific driver initialisation function, to initialise the hardware
- * device and the specific data structures when required.
- * It creates the associated server thread and allocates a WTI from local ICU.
- * For a TX_NIC chedv, it allocates and initializes the R2T queue used by the 
- * NIC_RX[channel] server to send direct requests to the NIC_TX[channel] server,
- * and the CRQ queue used to register connection requests.
- * It must de executed by a local thread.
- * For NIC_TX and NIC_RX chdevs, the "wait_root" field is actually a list of sockets.
- ******************************************************************************************
- * @ chdev    : local pointer on NIC chdev descriptor.
- *****************************************************************************************/
-void dev_nic_init( struct chdev_s * chdev );
-
-/* Functions directly called by a client thread in any cluster */
- 
-/******************************************************************************************
- * This function compute a channel index in range [0,nic_channels[ from the remote IP
- * address <addr> and <port>, by calling the relevant driver command.
- ******************************************************************************************
- * @ addr     : [in] IP address.
- * @ port     : [in] TCP/UDP port.
- * @ return the selected channel index
- *****************************************************************************************/
-uint32_t dev_nic_get_key( uint32_t addr,
-                          uint16_t port );
-
-/******************************************************************************************
- * This function activate / de-activate a NIC channel DMA engine identified by the
- * <channel> argument, as defined by the <run> argument.
- ******************************************************************************************
- * @ channel  : [in] NIC channel index.
- * @ run      : [in] activate if non-zero / desactivate if zero.
- * @ return 0 if success / return -1 if error.
- *****************************************************************************************/
-error_t dev_nic_set_run( uint32_t channel,
-                         uint32_t run );
-
-/******************************************************************************************
- * This instrumentation function displays on the TXT0 kernel terminal the content
- * of the instrumentation registers contained in the NIC device.
- ******************************************************************************************
- * @ return 0 if success / return -1 if error.
- *****************************************************************************************/
-error_t dev_nic_get_instru( void );
-
-/******************************************************************************************
- * This instrumentation function reset all instrumentation registers contained
- * in the NIC device.
- ******************************************************************************************
- * @ return 0 if success / return -1 if error.
- *****************************************************************************************/
-error_t dev_nic_clear_instru( void );
-
-/* Functions executed by the TX and RX server threads */ 
- 
-/******************************************************************************************
- * This function is executed by the server thread associated to a NIC_TX[channel] chdev. 
- * This TX server thread is created by the dev_nic_init() function.
- * It build and send UDP packets or TCP segments for all clients threads registered in
- * the NIC_TX[channel] chdev. The command types are (CONNECT / ACCEPT / CLOSE / SEND).
- * It takes into account the request registered by the RX server thread in the R2T queues.
- * The loop on registered sockets implements a round-robin priority between sockets.
- * When no registered socket is active, it blocks on the THREAD_BLOCKED_CLIENT condition
- * and deschedules. It is re-activated by a client thread registering a command.
- * When the NIC_TX packet queue is full, it blocks on the THREAD_BLOCKED_ISR condition
- * and deschedules. It is reactivated by the NIC_TX DMA engine.
- ******************************************************************************************
- * Implementation note:
- * At each iteration in the infinite loop, it takes the lock protecting the registered
- * client sockets queue to find one active socket (tx_valid or r2t_valid flags set).
- * For each registered socket, it takes the lock protecting the socket state, and 
- * exit the scan when an active socket has been found, without releasing the socket state.
- * When the scan is completed, it release the lock protecting the queue, before handling
- * the found active socket. The socket lock is released only when the requested packet
- * has been build, and the active socket state has been updated.
- * To handle a socket request, it calls the transport layer to build the UDP packet or
- * TCP segment in a local 2K bytes kernel buffer, calls the IP layer to add the IP header, 
- * calls the ETH layer to add the ETH header, and moves the packet to the NIC_TX_QUEUE.
- ******************************************************************************************
- * @ chdev    : [in] local pointer on one local NIC_TX[channel] chdev descriptor.
- *****************************************************************************************/
-void dev_nic_tx_server( struct chdev_s * chdev );
-
-
-/******************************************************************************************
- * This function is executed by the server thread associated to a NIC_RX[channel] chdev. 
- * This RX server thread is created by the dev_nic_init() function.
- * It handles all UDP packets or TCP segments received by the sockets attached to 
- * the NIC_RX[channel] chdev. It writes the received data in the socket rcv_buf, and
- * unblocks the client thread waiting on a RECV command.
- * To implement the three steps handshahke required by a TCP connection, it posts direct
- * requests to the TX server, using the R2T queue attached to the involved socket. 
- * It blocks on the THREAD_BLOCKED_ISR condition and deschedules when the NIC_RX_QUEUE
- * is empty, and is re-activated by the NIC_RX_ISR, when the queue becomes non empty.
- ******************************************************************************************
- * Implementation note:
- * It executes an infinite loop in which it extracts one packet from the NIC_RX_QUEUE
- * of received packets, copies this packet in a local 2 kbytes kernel buffer, checks 
- * the Ethernet header, checks the IP header, calls the relevant (TCP or UDP) transport
- * protocol that search a matching socket for the received packet. It copies the payload 
- * to the relevant socket rcv_buf when the packet is acceptable, and unblocks the client
- * thread. It discard the packet if no socket found.
- ******************************************************************************************
- * @ chdev    : [in] local pointer on one local NIC_RX[channel] chdev descriptor.
- *****************************************************************************************/
-void dev_nic_rx_server( struct chdev_s * chdev );
-
-/******************************************************************************************
- * This debug function can be called by the dev_nic_tx_server() function to display
- * on TXT0 the header of a TX [ETH/IP/TCP] segment or [ETH/IP/UDP] packet. 
- ******************************************************************************************
- * @ pid     : [in] process identifier.
- * @ fdid    : [in] socket identifier.
- * @ cycle   : [in] date (number of cycles).
- * @ buf     : [in] local pointer on kernel buffer containing the packet.
- *****************************************************************************************/
-void dev_nic_packet_display( pid_t     pid,
-                             uint32_t  fdid,
-                             uint32_t  cycle,
-                             uint8_t * buf );
+ * This function completes the NIC-RX and NIC-TX devices descriptors initialisation.
+ * The func, impl, channel, is_rx, base, and size have been previously initialised.
+ * It calls the driver initialisation function.
+ ******************************************************************************************
+ * @ dev_xp     : extended pointer on NIC-RX or NIC-TX device descriptor.
+ *****************************************************************************************/
+void dev_nic_init( xptr_t  dev_xp );
+
+/******************************************************************************************
+ * This blocking function must be called by the kernel thread running in the cluster
+ * containing the NIC_RX channel device descriptor.
+ * It read one packet (Ethernet/IPV4) from the NIC_RX queue associated to the NIC channel.
+ * It calls directly the NIC driver, without registering in a waiting queue, because 
+ * only this NIC_RX thread can access this packets queue.
+ * 1) It test the packets queue status, using the NIC_CMD_WRITABLE command.
+ *    If it is empty, it unmask the NIC-RX channel IRQ, blocks and deschedule.
+ *    It is re-activated by the NIC-RX ISR (generated by the NIC) as soon as the queue
+ *    becomes not empty.
+ * 2) if the queue is not empty, it get one packet, using the driver NIC_CMD_READ command.
+ * Both commands are successively registered in the NIC-RX server thread descriptor
+ * to be passed to the driver. 
+ *
+ * WARNING : for a RX packet the initiator is the NIC hardware, and the protocols
+ * stack is traversed upward, from the point of view of function calls.
+ ******************************************************************************************
+ * @ pkd     : pointer on packet descriptor (expected).
+ * @ returns 0 if success / returns non zero if ENOMEM, or error reported from NIC.
+ *****************************************************************************************/
+error_t dev_nic_read( pkd_t * pkd );
+
+/******************************************************************************************
+ * This blocking function must be called by the kernel thread running in the cluster
+ * containing the NIC_TX channel device descriptor.
+ * It writes one packet (Ethernet/IPV4) to the NIC_RX queue associated to the NIC channel.
+ * It calls directly the NIC driver, without registering in a waiting queue, because 
+ * only this NIC_TX thread can access this packets queue.
+ * 1) It test the packets queue status, using the NIC_CMD_READABLE command.
+ *    If it is full, it unmask the NIC-TX channel IRQ, blocks and deschedule.
+ *    It is re-activated by the NIC-TX ISR (generated by the NIC) as soon as the queue
+ *    is not full.
+ * 2) If the queue is not empty, it put one packet, using the driver NIC_CMD_WRITE command.
+ * Both commands are successively registered in the NIC-TX server thread descriptor
+ * to be passed to the driver. 
+ *
+ * WARNING : for a TX packet the initiator is the "client" thread, and the protocols
+ * stack is traversed downward from the point of view of function calls.
+ ******************************************************************************************
+ * @ pkd     : pointer on packet descriptor (to be filed).
+ * @ returns 0 if success / returns if length > 2K, undefined key, or error from NIC.
+ *****************************************************************************************/
+error_t dev_nic_write( pkd_t * pkd );
+
+
+/******************************************************************************************
+ * This function is executed by the server thread associated to a NIC channel device 
+ * descriptor (RX or TX). This thread is created by the dev_nic_init() function.
+ * It executes an infinite loop, handling one packet per iteration.
+ *
+ * -- For a TX channel --
+ * 1) It allocates a 2 Kbytes buffer.
+ * 2) It copies the client TCP/UDP packet in this buffer.
+ * 3) It calls the IP layer to add the IP header.
+ * 4) It calls the ETH layer to add the ETH header.
+ * 5) It calls the dev_nic_write() blocking function to move the packet to the TX queue.
+ * 6) It releases the 2 Kbytes buffer.
+ *
+ * When the waiting threads queue is empty, it blocks on the THREAD_BLOCKED_IO_CMD
+ * condition and deschedule. It is re-activated by a client thread registering a command.
+ *
+ * -- For a RX channel --
+ * 1) It allocates a 2 Kbytes buffer.
+ * 2  It calls the dev_nic_read() blocking function to move the ETH packet to this buffer.
+ * 3) It calls the ETH layer to analyse the ETH header.
+ * 4) It calls the IP layer to analyse the IP header. TODO ???
+ * 5) It calls the transport (TCP/UDP) layer. TODO ???
+ * 5) It deliver the packet to the client thread. TODO ???
+ * 6) It releases the 2 Kbytes buffer.
+ *
+ * When the RX packets queue is empty, it blocks on the THREAD_BLOCKED_IO_CMD
+ * condition and deschedule. It is re-activated by the NIC driver when this queue
+ * becomes non empty. 
+ ******************************************************************************************
+ * @ dev     : local pointer on NIC channel device descriptor.
+ *****************************************************************************************/
+void dev_nic_server( struct device_s * dev );
+
 
 #endif	/* _DEV_NIC_H */
