⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_cs.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* While there is still more to transmit */    while (pTxQueue->ifq_head != NULL)	{	/* Dequeue an mbuf chain from the transmit queue */	IF_DEQUEUE (pTxQueue, pMbufChain);	/* Find the total length of the data to transmit */	length = 0;	for (pMbuf=pMbufChain; pMbuf!=NULL; pMbuf=pMbuf->m_next)	    length += pMbuf->m_len;	/* etherOutputHookRtn is not supported */ 	/* Request that the transmit be started after	 * all data has been copied	 */	if (pCs->inMemoryMode)	    {	    csPacketPageW (pCs, CS_PKTPG_TX_CMD, CS_TX_CMD_START_ALL);	    csPacketPageW (pCs, CS_PKTPG_TX_LENGTH, length);	    }	else  /* In IO mode */	    {	    CS_OUT_WORD (pCs->ioAddr + CS_PORT_TX_CMD, CS_TX_CMD_START_ALL);	    CS_OUT_WORD (pCs->ioAddr + CS_PORT_TX_LENGTH, length);	    }	/* Read the busStatus register which indicates success of the request */	busStatus = csPacketPageR (pCs, CS_PKTPG_BUS_ST);	/* If there was an error in the transmit bid */	if (busStatus & CS_BUS_ST_TX_BID_ERR)	    {	    csError (pCs, "Transmit bid error (too big)");	    /* Discard the bad mbuf chain */	    m_freem (pMbufChain);	    pCs->arpCom.ac_if.if_oerrors++;	    /* Loop up to transmit the next chain */	    }	else if (busStatus & CS_BUS_ST_RDY4TXNOW)	    {	    /* The chip is ready for transmission now */	    /* Copy the frame to the chip to start transmission */	    csTxFrameCopy (pCs, pMbufChain);	    /* Free the mbuf chain */	    m_freem (pMbufChain);	    /* Transmission is now in progress */	    pCs->txInProgress = TRUE;	    break;  /* Exit this routine */	    }	else  	    csError (pCs, "Not ready for transmission now");	}    /* Re-enable interrupt at the chip */    csPacketPageW (pCs, CS_PKTPG_BUS_CTL, 		   csPacketPageR (pCs, CS_PKTPG_BUS_CTL) | CS_BUS_CTL_INT_ENBL);    }/********************************************************************************* csTxFrameCopy - copies the packet from a mbuf chain to the chip** This routine copies the packet from a chain of mbufs to the chip.  When all* the data has been copied, then the chip automatically begins transmitting* the data.** The reason why this "simple" copy routine is so long and complicated is* because all reads and writes to the chip must be done as 16-bit words.* If an mbuf has an odd number of bytes, then the last byte must be saved* and combined with the first byte of the next mbuf.** RETURNS: N/A*/LOCAL void csTxFrameCopy    (    CS_SOFTC *pCs,    struct mbuf *pMbufChain    )    {    struct mbuf *pMbuf;    FAST USHORT *pFrame;    FAST USHORT *pBuff;    FAST USHORT *pBuffLimit;    FAST int txDataPort;    UCHAR  *pStart;    USHORT  length;    BOOL haveExtraByte;    union	{	UCHAR  byte[2];	USHORT word;	} straddle;    /* Initialize frame pointer and data port address */    pFrame = pCs->pPacketPage + (CS_PKTPG_TX_FRAME/2);    txDataPort = pCs->ioAddr + CS_PORT_RXTX_DATA;    haveExtraByte = FALSE;  /* Start out with no extra byte */    /* Process the chain of mbufs */    for (pMbuf=pMbufChain; pMbuf!=NULL; pMbuf=pMbuf->m_next)	{	/* Setup starting pointer and length */	pStart = mtod (pMbuf, UCHAR *);	length = pMbuf->m_len;	/* If there is an extra byte left over from the previous mbuf */	if (haveExtraByte)	    {	    /* Add the first byte from this mbuf to make a word */	    straddle.byte[1] = *pStart;	    /* Write the word which straddles the mbufs to the chip */	    if (pCs->inMemoryMode)		*pFrame++ = straddle.word;	    else		{		CS_OUT_WORD (txDataPort, straddle.word);		}	    /* Adjust starting pointer and length */	    pStart++;	    length--;	    }	/* Point pBuff to the correct starting point */	pBuff = (USHORT *)pStart; 	/* If there are odd bytes remaining in the mbuf */	if (length & 1)	    {	    haveExtraByte = TRUE;	    /* Point pBuffLimit to the extra byte */	    pBuffLimit = (USHORT *)(pStart+length-1);	    }	else  /* There is an even number of bytes remaining */	    {	    haveExtraByte = FALSE;	    /* Point pBuffLimit to just beyond the last word */	    pBuffLimit = (USHORT *)(pStart+length);	    }	/* Copy the words in the mbuf to the chip */	if (pCs->inMemoryMode)	    while (pBuff < pBuffLimit)		*pFrame++ = *pBuff++;	else	    while (pBuff < pBuffLimit)		{		CS_OUT_WORD (txDataPort, *pBuff++);		}        /* If there is an extra byte left over in this mbuf	 *   Save the extra byte for later	 */        if (haveExtraByte)	    straddle.byte[0] = *(UCHAR *)pBuff;	}    /* If there is an extra byte left over from the last mbuf */    if (haveExtraByte)	{	/* Add a zero byte to make a word */	straddle.byte[1] = 0;	/* Write the last word to the chip */	if (pCs->inMemoryMode)	    *pFrame = straddle.word;	else	    {	    CS_OUT_WORD (txDataPort, straddle.word);	    }	}    } /********************************************************************************* csIntr - Ethernet interface interrupt** This routine in the interrupt service routine.  This routine is called by* assembly language wrapper code whenever the CS8900 chip generates and* interrupt.  The wrapper code issues an EOI command intr. controller.** This routine processes the events on the Interrupt Status Queue.  The events* are read one at a time from the ISQ and the appropriate event handlers are* called.  The ISQ is read until it is empty.  If the chip's interrupt request* line is active, then reading a zero from the ISQ will deactivate the* interrupt request line.** RETURNS: N/A*/LOCAL void csIntr    (    int unit    )    {    FAST CS_SOFTC *pCs = &cs_softc[unit];    USHORT event;    if (unit >= MAXUNITS)	return;    /* Ignore any interrupts that happen while the chip is being reset */    if (pCs->resetting)	return;    /* Read an event from the Interrupt Status Queue */    if (pCs->inMemoryMode)	event = csPacketPageR (pCs, CS_PKTPG_ISQ);    else	{	CS_IN_WORD (pCs->ioAddr + CS_PORT_ISQ, &event);	}    /* Process all the events in the Interrupt Status Queue */    while (event != 0)	{	/* Dispatch to an event handler based on the register number */	switch (event & CS_REG_NUM_MASK)	    {	    case CS_REG_NUM_RX_EVENT:		csIntrRx (pCs, event);		break;	    case CS_REG_NUM_TX_EVENT:		csIntrTx (pCs, event);		break;	    case CS_REG_NUM_BUF_EVENT:		csIntrBuffer (pCs, event);		break;	    default:		csError (pCs, "Unknown interrupt event");		break;	    }	/* Read another event from the Interrupt Status Queue */	if (pCs->inMemoryMode)	    event = csPacketPageR (pCs, CS_PKTPG_ISQ);	else	    {	    CS_IN_WORD (pCs->ioAddr + CS_PORT_ISQ, &event);	    }	}    }/********************************************************************************* csIntrBuffer - interrupt handler for the receive miss event** The routine is called whenever an event occurs regarding the transmit and* receive buffers within the CS8900 chip.  The only buffer event that could* happen with this network interface driver is the receive miss event.  When* there are no receive buffers available within the chip and a packet arrives* from the LAN, then this interrupt is generated.  This routine simply* increments the input error counter.** RETURNS: N/A*/LOCAL void csIntrBuffer     (    CS_SOFTC *pCs,    USHORT bufEvent    )    {    struct ifnet *pIf = &pCs->arpCom.ac_if;    if (bufEvent & CS_BUF_EVENT_RX_MISS)	{	/* Increment the input error count */	pIf->if_ierrors++;	csError (pCs, "Receive miss");	}    if (bufEvent & CS_BUF_EVENT_SW_INT)	{	csError (pCs, "Software initiated interrupt");	}    }/********************************************************************************* csIntrTx - interrupt handler for the transmission** This routine is called whenever the transmission of a packet has completed* successfully or unsuccessfully.  If the transmission was not successful,* then the output error count is incremented.  If collisions occured while* sending the packet, then the number of collisions is added to the collision* counter.  If there are more packets on the transmit queue, then the next* packet is started at task time by calling csStartOutput() via netTask().** RETURNS: N/A*/LOCAL void csIntrTx    (    CS_SOFTC *pCs,    USHORT txEvent    )    {    struct ifnet *pIf = &pCs->arpCom.ac_if;    /* If there were any errors transmitting this frame */    if (txEvent & (CS_TX_EVENT_LOSS_CRS | CS_TX_EVENT_SQE_ERR 		| CS_TX_EVENT_OUT_WIN | CS_TX_EVENT_JABBER		| CS_TX_EVENT_16_COLL))	{	/* Increment the output error count */	pIf->if_oerrors++;	/* If debugging is enabled then log error messages */	if (pIf->if_flags & IFF_DEBUG)	    {	    if (txEvent & CS_TX_EVENT_LOSS_CRS)		csError (pCs, "Loss of carrier");	    if (txEvent & CS_TX_EVENT_SQE_ERR)		csError (pCs, "SQE error");	    if (txEvent & CS_TX_EVENT_OUT_WIN)		csError (pCs, "Out-of-window collision");	    if (txEvent & CS_TX_EVENT_JABBER)		csError (pCs, "Jabber");	    if (txEvent & CS_TX_EVENT_16_COLL)		csError (pCs, "16 collisions");	    }	}    /* Add the number of collisions for this frame */    if (txEvent & CS_TX_EVENT_16_COLL)	pIf->if_collisions += 16;    else	pIf->if_collisions += ((txEvent & CS_TX_EVENT_COLL_MASK) >> 11);    /* Transmission is no longer in progress */    pCs->txInProgress = FALSE;    /* If there is more to transmit     *   Start the next transmission at task time     */    if (pIf->if_snd.ifq_head != NULL)	{#ifdef BSD43_DRIVER	netJobAdd ((FUNCPTR)csStartOutput, pIf->if_unit, 0, 0, 0, 0);#else /* BSD43_DRIVER */	netJobAdd ((FUNCPTR)csStartOutput, (int)pCs, 0, 0, 0, 0);#endif /* BSD43_DRIVER */	}    }/********************************************************************************* csIntrRx - interrupt handler for the reception** This routine is called whenever a packet is received at the chip.  If the* packet is received with errors, then the input error count is incremented.* If the packet is received OK, then the data is copied to an internal receive* buffer and the csRxProcess() routine is called via netTask() to* process the received packet at task time.** RETURNS: N/A*/LOCAL void csIntrRx    (    CS_SOFTC *pCs,    USHORT rxEvent    )    {    struct ifnet *pIf = &pCs->arpCom.ac_if;    CS_RXBUF *pRxBuff;    /* If the frame was not received OK */    if (!(rxEvent & CS_RX_EVENT_RX_OK))        {        /* Increment the input error count */        pIf->if_ierrors++;        /* If debugging is enabled then log error messages */        if (pIf->if_flags & IFF_DEBUG)	    {	    /* If an error bit is set */	    if (rxEvent != CS_REG_NUM_RX_EVENT)	        {	        if (rxEvent & CS_RX_EVENT_RUNT)		    csError (pCs, "Runt");	        if (rxEvent & CS_RX_EVENT_X_DATA)		    csError (pCs, "Extra data");	        if (rxEvent & CS_RX_EVENT_CRC_ERR)		    {		    if (rxEvent & CS_RX_EVENT_DRIBBLE)		        csError (pCs, "Alignment error");		    else		        csError (pCs, "CRC Error");		    }	        else if (rxEvent & CS_RX_EVENT_DRIBBLE)		    csError (pCs, "Dribble bits");	        /* Must read the length of all received frames */	        csPacketPageR (pCs, CS_PKTPG_RX_LENGTH);	        /* Skip the received frame */	        csPacketPageW (pCs, CS_PKTPG_RX_CFG,			       csPacketPageR (pCs,CS_PKTPG_RX_CFG)					    | CS_RX_CFG_SKIP);	        }	    else 	        csError (pCs, "Implied skip");	    }	return;	}    /* Get a receive frame buffer */    pRxBuff = csRxBuffAlloc (pCs);    if (pRxBuff == NULL)  /* If no buffer available */	{	/* Increment the input error count */	pIf->if_ierrors++;	csError (pCs, "No receive buffer available");	/* Must read the length of all received frames */	csPacketPageR (pCs, CS_PKTPG_RX_LENGTH);	/* Skip the received frame */	csPacketPageW (pCs, CS_PKTPG_RX_CFG,		       csPacketPageR (pCs, CS_PKTPG_RX_CFG) | CS_RX_CFG_SKIP);	return;	}    /* Copy the received frame from the chip to the buffer */    csRxFrameCopy (pCs, pRxBuff);    /* Process the received frame at task time */    netJobAdd ((FUNCPTR)csRxProcess, (int)pCs, (int)pRxBuff, 0, 0, 0);    }/********************************************************************************* csRxFrameCopy - copies a received frame from the chip to a receive buffer** This routine copies a received frame from the chip to a receive buffer.** RETURNS: N/A*/LOCAL void csRxFrameCopy    (    CS_SOFTC *pCs,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -