ixethaccend.c
来自「ixEthAccEnd END network interface driver」· C语言 代码 · 共 1,681 行 · 第 1/4 页
C
1,681 行
END_DEVICE *pDrvCtrl /* device structure */){ /* Not supported by this device */ return(char *)NULL;}/********************************************************************************* ixEthAccEndHandleRcvInt - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.** The double loop is to protect against a race condition where the interrupt* code see rxHandling as TRUE, but it is then turned off by task code.* This race is not fatal, but does cause occassional delays until a second* packet is received and then triggers the netTask to call this routine again.** RETURNS: N/A.*/LOCAL void ixEthAccEndHandleRcvInt(END_DEVICE *pDrvCtrl, /* interrupting device */IX_ETH_ACC_REC_BUF *pBufList){ M_BLK_ID pMblk = pBufList->ix_rec_buf;#if defined(IXP_DRV_DEBUG_LOG) || defined(IXP_DRV_DEBUG) int unit = pDrvCtrl->unit;#endif int oldLevel; IxEthAccStatus result; do { /* Expunge buffer data from cache. The header was done earlier */#ifdef IXE_CACHED_BUFFERS_ENABLE IXP425_END_CACHE_INVALIDATE (pMblk->m_data, pMblk->m_len);#endif /* IXE_CACHED_BUFFERS_ENABLE */ IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "Rx ixe[%d] Hdr: 0x%08X Buf: 0x%08X Sz: 0x%08X\n" , unit , (int)pMblk , (int)pMblk->m_data , (int)pMblk->m_len , 5, 6);#ifdef IXP_DRV_DEBUG_LOG ixEthAccRxBufs[unit][ixEthAccRxBufsIndex[unit]].pMhdr = pMblk; ixEthAccRxBufs[unit][ixEthAccRxBufsIndex[unit]].pData = pMblk->m_data; ixEthAccRxBufs[unit][ixEthAccRxBufsIndex[unit]].pSize = pMblk->m_len; if( ++ixEthAccRxBufsIndex[unit] >= IXETHACC_BUF_HISTORY_CNT) ixEthAccRxBufsIndex[unit] = 0;#endif /* IXP_DRV_DEBUG_LOG */ /* Add one to our unicast data. */ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); /* Other stats inc */ /* No chained MBUF's on receive side */ pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = pMblk->m_len; pMblk->m_next = 0; /* IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "Calling upper layer!\n", 1, 2, 3, 4, 5, 6); */ /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk); /* * Load Rx path with a new buffer. */ oldLevel = intLock (); /* protect IxEthAccEndInt */ pDrvCtrl->rxBufsActive--; /* The number of cblk/mblk pairs owned by NPE */ /* Mark this buffer done */ pBufList->ix_rec_buf = NULL; /* Step to the next buffer */ pBufList = pBufList->ix_rec_next; pDrvCtrl->rxHandling--; /* Are we done ? */ if ( (pMblk = pBufList->ix_rec_buf) == NULL ) pDrvCtrl->rxHandling = 0; intUnlock (oldLevel); } while ( pMblk ); /* Return buffers to the Intel Ethernet Engine */ do { if ((pMblk = netTupleGet(pDrvCtrl->end.pNetPool, IX_ETHACC_RX_MBUF_MIN_SIZE, M_DONTWAIT, MT_HEADER, FALSE )) == NULL) { /* Clear the error */ if( errnoGet () == S_netBufLib_NO_POOL_MEMORY ) errnoSet(0); break; } /* Force Quad align for Ip packet */ pMblk->m_data += 2; pMblk->m_len = IX_ETHACC_RX_MBUF_MIN_SIZE; pMblk->m_next = NULL;#ifdef IXE_CACHED_BUFFERS_ENABLE IXP425_END_CACHE_FLUSH(pMblk,sizeof(M_BLK)); IXP425_END_CACHE_FLUSH(pMblk->m_data, IX_ETHACC_RX_MBUF_MIN_SIZE);#endif /* IXE_CACHED_BUFFERS_ENABLE */#ifdef IXP_DRV_DEBUG_LOG ixEthAccRtnRxBufs[unit][ixEthAccRtnRxBufsIndex[unit]].pMhdr = pMblk; ixEthAccRtnRxBufs[unit][ixEthAccRtnRxBufsIndex[unit]].pData = pMblk->m_data; ixEthAccRtnRxBufs[unit][ixEthAccRtnRxBufsIndex[unit]].pSize = pMblk->m_len; if( ++ixEthAccRtnRxBufsIndex[unit] >= IXETHACC_BUF_HISTORY_CNT) ixEthAccRtnRxBufsIndex[unit] = 0;#endif /* IXP_DRV_DEBUG_LOG */ oldLevel = intLock (); /* protect IxEthAccEndInt */ result = ixEthAccPortRxFreeReplenish ( pDrvCtrl->unit, pMblk); pDrvCtrl->rxBufsActive++; /* The number of cblk/mblk pairs owned by NPE */ intUnlock (oldLevel); if ( result != IX_ETH_ACC_SUCCESS) { /* Free buffer back */ netMblkClChainFree (pMblk); IXP_DRV_LOG(IXP_DRV_DEBUG_RX,"Error:Registering IxEthAcc Rx Callbacks Port[%d]\n",pDrvCtrl->unit,2,3,4,5,6); break; } } while ( pMblk != 0 && (pDrvCtrl->rxBufsActive < pDrvCtrl->rxBufsAlloc));}/********************************************************************************* ixEthAccEndSend - the driver send routine** This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it. This is done by a higher layer.** RETURNS: OK, ERROR, or END_ERR_BLOCK.*/LOCAL STATUS ixEthAccEndSend(END_DEVICE * pDrvCtrl, /* device ptr */M_BLK_ID pMblk /* data to send */){#if defined(IXP_DRV_DEBUG_LOG) || defined(IXP_DRV_DEBUG) int unit = pDrvCtrl->unit;#endif STATUS rtnStatus = OK; M_BLK *mbufPtr; if (pMblk == NULL) return ERROR; /* * Obtain exclusive access to transmitter. This is necessary because * we might have more than one stack transmitting at once. */ if (!(pDrvCtrl->flags & IxEthAccEnd_POLLING)) { END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER); } for ( mbufPtr = pMblk; mbufPtr; mbufPtr = mbufPtr->m_next ) { /* Force outbound packets to 60 bytes minimum */ if ( mbufPtr->m_pkthdr.len < 60 ) mbufPtr->m_pkthdr.len = 60;/* mbufPtr->m_len = mbufPtr->m_pkthdr.len;*/ IXP_DRV_LOG (IXP_DRV_DEBUG_TX, "Tx ixe[%d] Hdr: 0x%08X Buf: 0x%08X Sz: 0x%08X\n", unit, (int)mbufPtr, (int)mbufPtr->m_data, mbufPtr->m_pkthdr.len, 5, 6);#ifdef IXP_DRV_DEBUG_LOG ixEthAccTxBufs[unit][ixEthAccTxBufsIndex[unit]].pMhdr = mbufPtr; ixEthAccTxBufs[unit][ixEthAccTxBufsIndex[unit]].pData = mbufPtr->m_data; ixEthAccTxBufs[unit][ixEthAccTxBufsIndex[unit]].pSize = mbufPtr->m_len; if( ++ixEthAccTxBufsIndex[unit] >= IXETHACC_BUF_HISTORY_CNT) ixEthAccTxBufsIndex[unit] = 0;#endif /* IXP_DRV_DEBUG_LOG */ /* Xmit blocks and buffers can come from cached memory */ IXP425_END_CACHE_FLUSH(mbufPtr, sizeof(M_BLK)); IXP425_END_CACHE_FLUSH(mbufPtr->m_data, mbufPtr->m_pkthdr.len); } /* place a transmit request */ if ( ixEthAccPortTxFrameSubmit(pDrvCtrl->unit, pMblk,IX_ETH_ACC_TX_DEFAULT_PRIORITY) != IX_ETH_ACC_SUCCESS ) { IXP_DRV_LOG (IXP_DRV_DEBUG_TX, "Error Tx Send Unit[%d] : Buffer:08x%08X\n", pDrvCtrl->unit, (int)pMblk, 3, 4, 5, 6); rtnStatus = ERROR; } else { /* Bump the statistics counters. */ if ( ! pMblk->mBlkHdr.mData[0] & (UINT8) 0x01 ) END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1); } if (!(pDrvCtrl->flags & IxEthAccEnd_POLLING)) { END_TX_SEM_GIVE (&pDrvCtrl->end); } return(rtnStatus);}/********************************************************************************* ixEthAccEndIoctl - the driver I/O control routine** Process an ioctl request.** RETURNS: A command specific response, usually OK or ERROR.*/LOCAL STATUS ixEthAccEndIoctl(END_DEVICE * pDrvCtrl, /* device receiving command */int cmd, /* ioctl command code */caddr_t data /* command argument */){ int error = 0; long value; IXP_DRV_LOG (IXP_DRV_DEBUG_IOCTL, "ixe: Ioctl:unit[%d]:CMD:0x%08X\n", pDrvCtrl->unit, cmd, 3, 4, 5, 6); switch (cmd) { case EIOCSADDR: if (data == NULL) return(EINVAL); bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end), END_HADDR_LEN(&pDrvCtrl->end)); break; case EIOCGADDR: if (data == NULL) return(EINVAL); bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data, END_HADDR_LEN(&pDrvCtrl->end)); break; case EIOCSFLAGS: value = (long)data; if (value < 0) { value = -(--value); END_FLAGS_CLR (&pDrvCtrl->end, value); } else { END_FLAGS_SET (&pDrvCtrl->end, value); } ixEthAccEndConfig (pDrvCtrl); break; case EIOCGFLAGS: *(int *)data = END_FLAGS_GET(&pDrvCtrl->end); break; case EIOCPOLLSTART: /* Begin polled operation */ ixEthAccEndPollStart (pDrvCtrl); break; case EIOCPOLLSTOP: /* End polled operation */ ixEthAccEndPollStop (pDrvCtrl); break; case EIOCGMIB2: /* return MIB information */ if (data == NULL) return(EINVAL); bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data, sizeof(pDrvCtrl->end.mib2Tbl)); break; case EIOCGFBUF: /* return minimum First Buffer for chaining */ if (data == NULL) return(EINVAL); *(int *)data = IxEthAccEnd_MIN_FBUF; break; default: error = EINVAL; } return(error);}/******************************************************************************** ixEthAccEndConfig - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** RETURNS: N/A.*/LOCAL void ixEthAccEndConfig(END_DEVICE *pDrvCtrl /* device to be re-configured */){ /* Set promiscuous mode if it's asked for. */ if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) { IXP_DRV_LOG ((IXP_DRV_DEBUG_IOCTL | IXP_DRV_DEBUG_LOAD), "Setting promiscuous mode on!\n", 1, 2, 3, 4, 5, 6); ixEthAccPortPromiscuousModeSet(pDrvCtrl->unit); } else { IXP_DRV_LOG ((IXP_DRV_DEBUG_IOCTL | IXP_DRV_DEBUG_LOAD), "Setting promiscuous mode off!\n", 1, 2, 3, 4, 5, 6); ixEthAccPortPromiscuousModeClear(pDrvCtrl->unit); } /* Set up address filter for multicasting. */ if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0) { ixEthAccEndAddrFilterSet (pDrvCtrl); } return;}/******************************************************************************** ixEthAccEndAddrFilterSet - set the address filter for multicast addresses** This routine goes through all of the multicast addresses on the list* of addresses (added with the endAddrAdd() routine) and sets the* device's filter correctly.** RETURNS: N/A.*/void ixEthAccEndAddrFilterSet(END_DEVICE *pDrvCtrl /* device to be updated */){ ETHER_MULTI* pCurr; pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end); while (pCurr != NULL) { pCurr = END_MULTI_LST_NEXT(pCurr); }}/********************************************************************************* ixEthAccEndPollRcv - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device.** RETURNS: OK upon success. EAGAIN is returned when no packet is available.*/LOCAL STATUS ixEthAccEndPollRcv(END_DEVICE * pDrvCtrl, /* device to be polled */M_BLK_ID pMblk /* ptr to buffer */){#ifdef IXE_ETHACC_POLL_ENABLE u_short stat; char* pPacket; int len; IXP_DRV_LOG (IXP_DRV_DEBUG_POLL_RX, "ixEthAccEndPollRcv\n", 1, 2, 3, 4, 5, 6); stat = ixEthAccEndStatusRead (pDrvCtrl); if (!(stat & IxEthAccEnd_RINT)) { IXP_DRV_LOG (IXP_DRV_DEBUG_POLL_RX, "ixEthAccEndPollRcv no data\n", 1, 2, 3, 4, 5, 6); return(EAGAIN); } /* Get packet and length from device buffer/descriptor */ pPacket = NULL; /* DUMMY CODE */ len = 64; /* DUMMY CODE */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?