/* ********************************************************************************************************* * uC/TCP-IP * The Embedded TCP/IP Suite * * (c) Copyright 2003-2006; Micrium, Inc.; Weston, FL * * All rights reserved. Protected by international copyright laws. * Knowledge of the source code may not be used to write a similar * product. This file may only be used in accordance with a license * and should not be redistributed in any way. ********************************************************************************************************* */ /* ********************************************************************************************************* * * PACKET-BASED NETWORK INTERFACE LAYER * * Filename : net_if_pkt.c * Version : V1.86 * Programmer(s) : ITJ ********************************************************************************************************* * Note(s) : (1) Supports packet-based Network Interface Cards/Layers. * * (2) Packet-based Network Interface Layer also referred to as 'Packet Interface' & also * abbreviated as network interface. ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #define NET_IF_PKT_MODULE #include /* ********************************************************************************************************* * MODULE * * Note(s) : (1) See 'net_if_pkt.h MODULE'. ********************************************************************************************************* */ #ifdef NET_IF_PKT_MODULE_PRESENT /* ********************************************************************************************************* * LOCAL DEFINES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL CONSTANTS ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL DATA TYPES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL TABLES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL GLOBAL VARIABLES ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * LOCAL FUNCTION PROTOTYPES ********************************************************************************************************* */ /* ------------------- RX FNCTS ------------------- */ static void NetIF_Pkt_Rx (void); #if (NET_CFG_LOAD_BAL_EN == DEF_ENABLED) static void NetIF_Pkt_RxHandlerLoadBal(void); #endif static void NetIF_Pkt_RxPktDiscard (NET_BUF *pbuf); /* ------------------- TX FNCTS ------------------- */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) static void NetIF_Pkt_TxPktValidate (NET_BUF *pbuf, NET_BUF_HDR *pbuf_hdr, NET_ERR *perr); #endif static void NetIF_Pkt_TxPktFree (NET_BUF *pbuf); static void NetIF_Pkt_TxPktDiscard (NET_BUF *pbuf, NET_ERR *perr); /* ********************************************************************************************************* * LOCAL CONFIGURATION ERRORS ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * NetIF_Pkt_Init() * * Description : (1) Initialize Packet-based Network Interface Layer : * * (a) Perform Packet Interface/OS initialization * (b) Initialize Packet Interface statistics & error counters * * * Argument(s) : perr Pointer to variable that will receive the return error code from this function : * * NET_IF_ERR_NONE Network interface layer successfully * initialized. * * --- RETURNED BY NetOS_IF_Init() : ---- * NET_OS_ERR_INIT_IF_RX_Q Network interface receive queue signal * NOT successfully initialized. * NET_OS_ERR_INIT_IF_RX_Q_NAME Network interface receive queue name * NOT successfully configured. * NET_OS_ERR_INIT_IF_RX_TASK Network interface receive task * NOT successfully initialized. * NET_OS_ERR_INIT_IF_RX_TASK_NAME Network interface receive task name * NOT successfully configured. * * Return(s) : none. * * Caller(s) : Net_Init(). * * Note(s) : none. ********************************************************************************************************* */ void NetIF_Pkt_Init (NET_ERR *perr) { /* -------------- PERFORM PKT IF/OS INIT -------------- */ NetOS_IF_Init(perr); /* Create pkt IF obj(s)/task(s). */ if (*perr != NET_OS_ERR_NONE) { return; } /* ----------- INIT PKT IF STAT & ERR CTRS ------------ */ #if (NET_CTR_CFG_STAT_EN == DEF_ENABLED) NetIF_Pkt_StatRxPktCtr = 0; NetIF_Pkt_StatRxPktProcessedCtr = 0; NetIF_Pkt_StatTxPktCtr = 0; #endif #if (NET_CTR_CFG_ERR_EN == DEF_ENABLED) NetIF_Pkt_ErrRxPktDiscardedCtr = 0; NetIF_Pkt_ErrTxPktDiscardedCtr = 0; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NetIF_Pkt_ErrTxProtocolCtr = 0; NetIF_Pkt_ErrTxInvalidBufIxCtr = 0; #endif #endif *perr = NET_IF_ERR_NONE; } /*$PAGE*/ /* ********************************************************************************************************* * NetIF_RxTaskHandlerInit() * * Description : Initialize Packet-based Network Interface Receive Task Handler. * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : NetOS_IF_RxTask() [see 'net_os.c']. * * Note(s) : (1) Network Interface Receive Task Handler functions named 'NetIF_' ONLY to allow NIC & OS port * interfaces to be generic for either packet-based or character-based network interface. ********************************************************************************************************* */ void NetIF_RxTaskHandlerInit (void) { } /*$PAGE*/ /* ********************************************************************************************************* * NetIF_RxTaskHandler() * * Description : (1) Handle received data packets from network interface card : * * (a) Wait for Receive ISR signal from Network Interface Card (NIC) * (b) Handle received packet * (c) Handle network load balancing * * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : NetOS_IF_RxTask() [see 'net_os.c']. * * Note(s) : (2) Network Interface Receive Task Handler functions named 'NetIF_' ONLY to allow NIC & OS port * interfaces to be generic for either packet-based or character-based network interface. * * (3) NetIF_RxTaskHandler() blocked until network initialization completes. * * (4) NetIF_RxTaskHandler() blocks ALL other network protocol tasks by pending on & acquiring * the global network lock (see 'net.h Note #2'). ********************************************************************************************************* */ void NetIF_RxTaskHandler (void) { NET_ERR err_rx; if (Net_InitDone != DEF_YES) { /* If init NOT complete, ... */ NetOS_InitWait(&err_rx); /* ... wait on net init (see Note #3). */ if (err_rx != NET_OS_ERR_NONE) { return; } } while (DEF_ON) { /* -------------- WAIT FOR NIC RX SIGNAL -------------- */ do { NetOS_IF_RxTaskWait(&err_rx); } while (err_rx != NET_IF_ERR_NONE); NetOS_Lock(&err_rx); /* Acquire net lock (see Note #4). */ if (err_rx != NET_OS_ERR_NONE) { return; } /* ------------------ HANDLE PKT RX ------------------- */ NetIF_Pkt_Rx(); #if (NET_CFG_LOAD_BAL_EN == DEF_ENABLED) /* --------------- HANDLE NET LOAD BAL ---------------- */ NetIF_Pkt_RxHandlerLoadBal(); #endif NetOS_Unlock(); /* Release net lock. */ } } /*$PAGE*/ /* ********************************************************************************************************* * NetIF_Pkt_Tx() * * Description : (1) Transmit data packets from network interface layer to network interface card : * * (a) Check NIC status * (b) Prepare NIC transmit packet(s) * (c) Wait for NIC transmit ready signal * (d) Transmit packet(s) * (e) Free transmit packet buffer(s) * (f) Update transmit statistics * * * Argument(s) : pbuf Pointer to network buffer with data packet to transmit. * * perr Pointer to variable that will receive the return error code from this function : * * NET_IF_ERR_NONE Packet successfully transmitted. * NET_ERR_INIT_INCOMPLETE Network initialization NOT complete. * * - RETURNED BY NetIF_Pkt_TxPktDiscard() : - * NET_ERR_TX Transmit error; packet discarded. * * Return(s) : none. * * Caller(s) : NetIF_TxPktHandler(). * * Note(s) : (2) NetIF_Pkt_Tx() blocked until network initialization completes; perform NO action. ********************************************************************************************************* */ void NetIF_Pkt_Tx (NET_BUF *pbuf, NET_ERR *perr) { #if ((NET_CTR_CFG_STAT_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_BUF_HDR *pbuf_hdr; NET_BUF_SIZE size; CPU_INT08U *p_data; CPU_BOOLEAN conn_status; #if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) if (Net_InitDone != DEF_YES) { /* If init NOT complete, exit tx (see Note #2). */ NetIF_Pkt_TxPktDiscard(pbuf, perr); *perr = NET_ERR_INIT_INCOMPLETE; return; } #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------- VALIDATE PTR ------------------- */ if (pbuf == (NET_BUF *)0) { NetIF_Pkt_TxPktDiscard(pbuf, perr); return; } #endif /* ----------------- VALIDATE DRV PKT ----------------- */ pbuf_hdr = &pbuf->Hdr; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NetIF_Pkt_TxPktValidate(pbuf, pbuf_hdr, perr); switch (*perr) { case NET_IF_ERR_NONE: break; case NET_ERR_INVALID_PROTOCOL: case NET_BUF_ERR_INVALID_IX: default: NetIF_Pkt_TxPktDiscard(pbuf, perr); return; /* Prevent 'break NOT reachable' compiler warning. */ } #endif /*$PAGE*/ /* ------------------ CHK NIC STATUS ------------------ */ conn_status = NetNIC_ConnStatusGet(); switch (conn_status) { case DEF_ON: break; case DEF_OFF: default: NetIF_Pkt_TxPktDiscard(pbuf, perr); return; /* Prevent 'break NOT reachable' compiler warning. */ } /* ---------------- PREPARE NIC TX PKT ---------------- */ p_data = &pbuf->Data[pbuf_hdr->IF_HdrIx]; size = pbuf_hdr->TotLen; #if (NET_NIC_CFG_TX_PKT_PREPARE_EN == DEF_ENABLED) NetNIC_TxPktPrepare((void *)p_data, (CPU_INT16U)size, (NET_ERR *)perr); switch (*perr) { case NET_NIC_ERR_NONE: break; default: NetIF_Pkt_TxPktDiscard(pbuf, perr); return; /* Prevent 'break NOT reachable' compiler warning. */ } #endif /* ---- WAIT FOR NIC TX READY SIGNAL & TX NIC PKT ----- */ NetOS_NIC_TxRdyWait(perr); switch (*perr) { case NET_NIC_ERR_NONE: NetNIC_TxPkt((void *)p_data, (CPU_INT16U)size, (NET_ERR *)perr); break; case NET_NIC_ERR_TX_RDY_SIGNAL_TIMEOUT: default: NetIF_Pkt_TxPktDiscard(pbuf, perr); return; /* Prevent 'break NOT reachable' compiler warning. */ } /* ---------- FREE TX PKT / UPDATE TX STATS ----------- */ switch (*perr) { /* Chk err from NetNIC_TxPkt(). */ case NET_NIC_ERR_NONE: NetIF_Pkt_TxPktFree(pbuf); NET_CTR_STAT_INC(NetIF_Pkt_StatTxPktCtr); *perr = NET_IF_ERR_NONE; break; default: NetIF_Pkt_TxPktDiscard(pbuf, perr); return; /* Prevent 'break NOT reachable' compiler warning. */ } } /*$PAGE*/ /* ********************************************************************************************************* ********************************************************************************************************* * LOCAL FUNCTIONS ********************************************************************************************************* ********************************************************************************************************* */ /* ********************************************************************************************************* * NetIF_Pkt_Rx() * * Description : (1) Receive data packets from network interface card & demultiplex to network interface layer : * * (a) Validate receive packet size * (b) Get network buffer of sufficient size to receive packet * (c) Read receive packet from NIC * (d) Demultiplex to network interface layer * (e) Update receive statistics * * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : NetIF_RxTaskHandler(). * * Note(s) : (2) When network buffer is demultiplexed to network IF receive, the buffer's reference * counter is NOT incremented since the packet interface layer does NOT maintain a * reference to the buffer. * * (3) Network buffer already freed by higher layer; only increment error counter. ********************************************************************************************************* */ static void NetIF_Pkt_Rx (void) { #if (((NET_CTR_CFG_STAT_EN == DEF_ENABLED) || \ (NET_CTR_CFG_ERR_EN == DEF_ENABLED)) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_ERR err_rx; CPU_BOOLEAN size_valid; CPU_INT16U size; CPU_INT16U ix_rx; NET_BUF *pbuf; NET_BUF_HDR *pbuf_hdr; CPU_INT08U *p_data; NET_CTR_STAT_INC(NetIF_Pkt_StatRxPktCtr); /* --------------- VALIDATE RX PKT SIZE --------------- */ size = NetNIC_RxPktGetSize(); /* Get pkt size. */ size_valid = NetIF_IsValidPktSize(size); if (size_valid != DEF_YES) { NetNIC_RxPktDiscard(size, &err_rx); /* If size err, rd data from NIC & discard. */ NetIF_Pkt_RxPktDiscard((NET_BUF *)0); return; } /* ----------------- GET BUF / RX PKT ----------------- */ ix_rx = NET_IF_RX_IX; pbuf = NetBuf_Get((NET_BUF_SIZE) size, /* Get buf large enough for pkt. */ (NET_BUF_SIZE) ix_rx, (CPU_INT16U ) NET_BUF_FLAG_NONE, (NET_ERR *)&err_rx); switch (err_rx) { case NET_BUF_ERR_NONE: /* If NO errs, buf avail; ... */ p_data = &pbuf->Data[ix_rx]; /* ... set appropriate rx ix ... */ NetNIC_RxPkt((void *)p_data, size, &err_rx); /* ... & rd data from NIC into buf. */ break; case NET_BUF_ERR_NONE_AVAIL: case NET_BUF_ERR_INVALID_TYPE: case NET_BUF_ERR_INVALID_SIZE: default: NetNIC_RxPktDiscard(size, &err_rx); /* If errs, rd data from NIC & discard. */ NetIF_Pkt_RxPktDiscard(pbuf); return; /* Prevent 'break NOT reachable' compiler warning. */ } /*$PAGE*/ /* -------------------- DEMUX PKT --------------------- */ switch (err_rx) { /* Chk err from NetNIC_RxPkt(). */ case NET_NIC_ERR_NONE: pbuf_hdr = &pbuf->Hdr; pbuf_hdr->TotLen = (NET_BUF_SIZE)size; /* Set pkt size as buf tot len & data len. */ pbuf_hdr->DataLen = (NET_BUF_SIZE)pbuf_hdr->TotLen; pbuf_hdr->IF_HdrIx = ix_rx; pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_FRAME; /* See Note #2. */ NetIF_Rx(pbuf, &err_rx); break; case NET_ERR_INIT_INCOMPLETE: default: NetIF_Pkt_RxPktDiscard(pbuf); return; /* Prevent 'break NOT reachable' compiler warning. */ } /* ----------------- UPDATE RX STATS ------------------ */ switch (err_rx) { /* Chk err from NetIF_Rx(). */ case NET_IF_ERR_NONE: NET_CTR_STAT_INC(NetIF_Pkt_StatRxPktProcessedCtr); break; case NET_ERR_INIT_INCOMPLETE: case NET_ERR_RX: NET_CTR_ERR_INC(NetIF_Pkt_ErrRxPktDiscardedCtr); /* See Note #3. */ break; default: NetIF_Pkt_RxPktDiscard(pbuf); return; /* Prevent 'break NOT reachable' compiler warning. */ } } /*$PAGE*/ /* ********************************************************************************************************* * NetIF_Pkt_RxHandlerLoadBal() * * Description : Handle network receive versus transmit load balancing. * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : NetIF_RxTaskHandler(). * * Note(s) : (1) To balance network receive versus transmit packet loads for certain network connection * types (e.g. stream-type connections), network receive & transmit packets SHOULD be * handled in an APPROXIMATELY balanced ratio. * * (a) Network task priorities & lock mechanisms partially maintain a balanced ratio * between network receive versus transmit packet handling. * * However, the handling of network receive & transmit packets : * * (1) SHOULD be interleaved so that for every few packet(s) received & handled, * several packet(s) should be transmitted; & vice versa. * * (2) SHOULD NOT exclusively handle receive nor transmit packets, even for a * short period of time. * * (b) To implement network receive versus transmit load balancing : * * (1) The availability of network receive packets MUST be managed at the network * interface layer : * * (A) Increment the number of available network receive packets queued for * each network packet received. * * (B) Decrement the number of available network receive packets queued for * each received packet handled. * * (2) Certain network connections MUST periodically suspend network transmit(s) * to handle network receive packet(s) : * * (A) Suspend network transmit(s) if network receive packets are available. * * (B) Signal or timeout network transmit suspend(s) to restart transmit(s). * * See also 'NETWORK RECEIVE PACKET MACRO'S Note #1'. ********************************************************************************************************* */ #if (NET_CFG_LOAD_BAL_EN == DEF_ENABLED) static void NetIF_Pkt_RxHandlerLoadBal (void) { #if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL) CPU_SR cpu_sr; #endif NET_RX_PKT_DEC(); /* Dec nbr q'd rx pkts avail (see Note #1b1B). */ Net_TxSuspendSignal(); /* Signal net tx suspend (see Note #1b2B). */ } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetIF_Pkt_RxPktDiscard() * * Description : On any Packet-based Network Interface Receive errors, discard packet & buffer. * * Argument(s) : pbuf Pointer to network buffer. * * Return(s) : none. * * Caller(s) : NetIF_Pkt_Rx(). * * Note(s) : none. ********************************************************************************************************* */ static void NetIF_Pkt_RxPktDiscard (NET_BUF *pbuf) { NET_CTR *pctr; #if (NET_CTR_CFG_ERR_EN == DEF_ENABLED) pctr = (NET_CTR *)&NetIF_Pkt_ErrRxPktDiscardedCtr; #else pctr = (NET_CTR *) 0; #endif NetBuf_FreeBuf((NET_BUF *)pbuf, (NET_CTR *)pctr); } /*$PAGE*/ /* ********************************************************************************************************* * NetIF_Pkt_TxPktValidate() * * Description : (1) Validate network interface transmit packet parameters : * * (a) Packets with the following invalid parameters will be "silently discarded" : * * (1) Protocols other than supported protocols : * (A) Frame * * (2) Total Length * * * Argument(s) : pbuf Pointer to network buffer to transmit network interface packet. * ---- Argument checked in NetIF_Pkt_Tx(). * * pbuf_hdr Pointer to network buffer header. * -------- Argument validated in NetIF_Pkt_Tx(). * * perr Pointer to variable that will receive the return error code from this function : * * NET_IF_ERR_NONE Transmit packet validated. * NET_ERR_INVALID_PROTOCOL Invalid/unknown protocol type. * NET_BUF_ERR_INVALID_IX Invalid or insufficient buffer index. * * Return(s) : none. * * Caller(s) : NetIF_Pkt_Tx(). * * Note(s) : none. ********************************************************************************************************* */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) static void NetIF_Pkt_TxPktValidate (NET_BUF *pbuf, NET_BUF_HDR *pbuf_hdr, NET_ERR *perr) { #if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif CPU_INT16U ix; /* ----------------- VALIDATE PROTOCOL ---------------- */ switch (pbuf_hdr->ProtocolHdrType) { case NET_PROTOCOL_TYPE_FRAME: ix = pbuf_hdr->IF_HdrIx; break; case NET_PROTOCOL_TYPE_NONE: default: NET_CTR_ERR_INC(NetIF_Pkt_ErrTxProtocolCtr); *perr = NET_ERR_INVALID_PROTOCOL; return; /* Prevent 'break NOT reachable' compiler warning. */ } if (ix == NET_BUF_IX_NONE) { NET_CTR_ERR_INC(NetIF_Pkt_ErrTxInvalidBufIxCtr); *perr = NET_BUF_ERR_INVALID_IX; return; } *perr = NET_IF_ERR_NONE; } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetIF_Pkt_TxPktFree() * * Description : Free network buffer. * * Argument(s) : pbuf Pointer to network buffer. * * Return(s) : none. * * Caller(s) : NetIF_Pkt_Tx(). * * Note(s) : none. ********************************************************************************************************* */ static void NetIF_Pkt_TxPktFree (NET_BUF *pbuf) { NetBuf_FreeBuf((NET_BUF *)pbuf, (NET_CTR *)0); } /* ********************************************************************************************************* * NetIF_Pkt_TxPktDiscard() * * Description : On any Transmit errors, discard packet & buffer. * * Argument(s) : pbuf Pointer to network buffer. * * perr Pointer to variable that will receive the return error code from this function : * * NET_ERR_TX Transmit error; packet discarded. * * Return(s) : none. * * Caller(s) : NetIF_Pkt_Tx(). * * Note(s) : none. ********************************************************************************************************* */ static void NetIF_Pkt_TxPktDiscard (NET_BUF *pbuf, NET_ERR *perr) { NET_CTR *pctr; #if (NET_CTR_CFG_ERR_EN == DEF_ENABLED) pctr = (NET_CTR *)&NetIF_Pkt_ErrTxPktDiscardedCtr; #else pctr = (NET_CTR *) 0; #endif NetBuf_FreeBuf((NET_BUF *)pbuf, (NET_CTR *)pctr); *perr = NET_ERR_TX; } /*$PAGE*/ /* ********************************************************************************************************* * MODULE END * * Note(s) : (1) See 'MODULE Note #1' & 'net_if_pkt.h MODULE Note #1'. ********************************************************************************************************* */ #endif /* End of pkt-based net IF module include (see Note #1).*/