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

📄 if_seeq.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	pDrvCtrl->rxNext = nextFrame;	SEEQ_WRITE (pDev->pRxend, (nextFrame >> 8));	} while (headerStatus & SEEQ_RX_HSTAT_CHAIN);    }/******************************************************************************** seeqTransmit - handle transmitted packets.** NOMANUAL*/LOCAL void seeqTransmit    (    int unit    )    {    int		pktCount;    DRV_CTRL	*pDrvCtrl = &drvCtrl[unit];    SEEQ_DEVICE *pDev = pDrvCtrl->devAdrs;    BOOL resetTx = FALSE;#ifdef DEBUG    if (seeqDebug)	logMsg ("TX Cnt %d Curr 0x%04x Next 0x%04x Space 0x%04x\n",		pDrvCtrl->txCount, pDrvCtrl->txCurr,		pDrvCtrl->txNext, TX_SPACE(pDrvCtrl),		0, 0);#endif    /* If interface was shutdown, abort service request */    if (!(pDrvCtrl->idr.ac_if.if_flags & IFF_UP))	{	pDrvCtrl->flags &= ~SEEQ_TX_OUTSTANDING;	return;	}    if (!(pDrvCtrl->flags & SEEQ_TX_OUTSTANDING))	{#ifdef DEBUG	if (seeqDebug)	    logMsg ("seeq: no TX request outstanding\n",		    0, 0, 0, 0, 0, 0);#endif	return;	}    pDrvCtrl->flags &= ~SEEQ_TX_OUTSTANDING;    pktCount = pDrvCtrl->txCount;    if (!pDrvCtrl->txCount)	{#ifdef DEBUG	if (seeqDebug)	    logMsg ("seeq: no xmit curr 0x%04x next 0x%04x space 0x%04x\n",		    pDrvCtrl->txCurr, pDrvCtrl->txNext, TX_SPACE(pDrvCtrl),		    0, 0, 0);#endif	return;	}    /* Now process the packets */    while (1)	{	USHORT tmp;	USHORT nextFrame;	USHORT frameCommand;	USHORT frameStatus;	if (seeqSetDMARead(pDrvCtrl, pDrvCtrl->txCurr) != OK)	    {	    /* re-queue for later processing. */#ifdef DEBUG	    if (seeqDebug)		logMsg ("TX: Set DMA failed\n", 0, 0, 0, 0, 0, 0);#endif	    seeqTxReset (pDrvCtrl->unit);	    pDrvCtrl->flags |= SEEQ_TX_OUTSTANDING;	    netJobAdd ((FUNCPTR) seeqTransmit, unit, 0, 0, 0, 0);	    break;	    }	/* Move curr to the end of the last transmitted packet */	nextFrame = SEEQ_READ (pDev->pBwind);	/* get the frame status and command */	tmp = SEEQ_READ (pDev->pBwind);	frameCommand = tmp >> 8;	frameStatus = tmp & 0x00ff;#ifdef DEBUG	if (seeqDebug)	    logMsg ("TX @ 0x%04x command %02x status 0x%02x next 0x%04x\n",		    pDrvCtrl->txCurr, frameCommand, frameStatus, nextFrame,		    0, 0);#endif	/*	 * At this point, we should be at a valid TX header since	 * txCount > 0.	 */	if (nextFrame > pDrvCtrl->txEnd)	    {#ifdef DEBUG	    if (seeqDebug)		logMsg ("TX: bad next pointer\n", 0, 0, 0, 0, 0, 0);#endif	    resetTx = TRUE;	    }	if (!(frameCommand & SEEQ_TX_CMD_XMIT))	    {#ifdef DEBUG	    if (seeqDebug)		logMsg ("TX: not an xmit header\n", 0, 0, 0, 0, 0, 0);#endif	    resetTx = TRUE;	    }	if (!(frameCommand & SEEQ_TX_CMD_CHAIN))	    {#ifdef DEBUG	    if (seeqDebug)		logMsg ("TX: ran off end\n", 0, 0, 0, 0, 0, 0);#endif	    resetTx = TRUE;	    }	if (!(frameCommand & SEEQ_TX_CMD_DATA))	    {#ifdef DEBUG	    if (seeqDebug)		logMsg ("TX: no data in packet\n", 0, 0, 0, 0, 0, 0);#endif	    resetTx = TRUE;	    }	if (resetTx)	    {#ifdef DEBUG	    if (seeqDebug)		logMsg ("TX: reset cnt %d curr 0x%04x cmd %02x stat 0x%02x next 0x%04x\n",			pDrvCtrl->txCount, pDrvCtrl->txCurr, frameCommand,			frameStatus, nextFrame, 0);#endif	    seeqTxReset (pDrvCtrl->unit);	    break;	    }	/* If not done, stop processing. */	if (!(frameStatus & SEEQ_TX_PSTAT_DONE))	    break;	/* Check for error status. */	if (frameStatus & SEEQ_TX_PSTAT_BABBLE)	    ++pDrvCtrl->idr.ac_if.if_oerrors;	if (frameStatus & SEEQ_TX_PSTAT_COLL16)	    pDrvCtrl->idr.ac_if.if_collisions += 16;	else if (frameStatus & SEEQ_TX_PSTAT_COLL)	    ++pDrvCtrl->idr.ac_if.if_collisions;	/* Move past this packet. */	pDrvCtrl->txCurr = nextFrame;	/* Exit if all packets accounted for. */	if (!--pDrvCtrl->txCount)	    break;	}    /* If packets where waiting on the queue for free space, re-start */    if (((pktCount != pDrvCtrl->txCount) || resetTx)	&& (pDrvCtrl->idr.ac_if.if_snd.ifq_head != NULL))	(void)netJobAdd ((FUNCPTR) seeqStart, unit, 0, 0, 0, 0);    }/******************************************************************************** seeqInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.  All of the real work is handled at task level through* netJobAdd.** NOMANUAL*/void seeqInt    (    int unit    )    {    USHORT	status;    DRV_CTRL	*pDrvCtrl = &drvCtrl[unit];    SEEQ_DEVICE	*pDev = pDrvCtrl->devAdrs;    ++seeqIntCnt;    status = SEEQ_READ (pDev->pStat);    SEEQ_WRITE (pDev->pCmd, ((SEEQ_READ(pDev->pStat) & SEEQ_STAT_CMD_MASK) | SEEQ_CMD_ALL_ACK));    if (pDrvCtrl->idr.ac_if.if_flags & IFF_UP)	{	/* Make sure only one TX and RX request is outstanding at a time. */	if ((status & SEEQ_STAT_RX_INT)	    && !(pDrvCtrl->flags & SEEQ_RX_OUTSTANDING))	    {	    pDrvCtrl->flags |= SEEQ_RX_OUTSTANDING;	    netJobAdd ((FUNCPTR) seeqReceive, unit, 0, 0, 0, 0);	    }	if ((status & SEEQ_STAT_TX_INT)	    && !(pDrvCtrl->flags & SEEQ_TX_OUTSTANDING))	    {	    pDrvCtrl->flags |= SEEQ_TX_OUTSTANDING;	    netJobAdd ((FUNCPTR) seeqTransmit, unit, 0, 0, 0, 0);	    }	}    }/******************************************************************************** seeqOutput - the driver output routine** NOMANUAL*/LOCAL int seeqOutput    (    IDR  *pIDR,    MBUF *pMbuf,    SOCK *pDest    )    {    return ether_output ((IFNET*)pIDR, pMbuf, pDest,			 (FUNCPTR) seeqStart, pIDR);    }/******************************************************************************** seeqStart - start outputing a packet.** Get another datagram to send off of the interface queue,* and map it to the interface before starting the output.* This routine is called by seeqOutput().** NOMANUAL*/LOCAL void seeqStart    (    int unit    )    {    DRV_CTRL	*pDrvCtrl = &drvCtrl[unit];    SEEQ_DEVICE *pDev = pDrvCtrl->devAdrs;    int		space;    int		s;    s = splnet ();    space = TX_SPACE(pDrvCtrl);    if (space < (ETHERMTU + 8))	{#ifdef DEBUG	if (seeqDebug)	    logMsg ("TX: low space %4d: flags %d curr 0x%04x next 0x%04x\n",		    space, pDrvCtrl->flags, pDrvCtrl->txCurr, pDrvCtrl->txNext,		    0, 0);#endif	/* May have dropped a TX interrupt */	if (pDrvCtrl->txLow++ > 2)	    {	    pDrvCtrl->txLow = 0;	    seeqTxReset (pDrvCtrl->unit);	    }	else if (!(pDrvCtrl->flags & SEEQ_TX_OUTSTANDING))	    {	    pDrvCtrl->flags |= SEEQ_TX_OUTSTANDING;	    netJobAdd ((FUNCPTR) seeqTransmit, unit, 0, 0, 0, 0);	    }	}    /* Only start if we have at least enough room */    if ((space >= ETHERMTU + 8)	&& pDrvCtrl->idr.ac_if.if_snd.ifq_head != NULL)	{	MBUF	*pMbuf;	int	len;	UCHAR	*buf;	USHORT	txNext;	BOOL error = FALSE;	pDrvCtrl->txLow = 0;	IF_DEQUEUE(&pDrvCtrl->idr.ac_if.if_snd, pMbuf);	/* copy packet to write buffer */	copy_from_mbufs (pDrvCtrl->txBuf, pMbuf, len);	buf = (UCHAR *) pDrvCtrl->txBuf;	/* After this point, if there's a problem with the chip, the	   packet is lost. */	/* Adjust length to ensure minimum packet size */	len = max (ETHERSMALL, len);	++pDrvCtrl->txCount;#ifdef DEBUG	if (seeqDebug > 1)	    {	    int i;	    char *ptr;	    static char lbuf[4096];	    sprintf(lbuf, "TX %4d:", len);	    ptr = lbuf + strlen(lbuf);	    for (i = 0; i < len; ++i, ptr += 3)		sprintf(ptr , " %02x", buf[i]);	    logMsg ("%s\n", (int) lbuf, 0, 0, 0, 0, 0);	    }#endif	/* Compute where the next packet will go */	txNext = pDrvCtrl->txNext + len + 4;	if (txNext > pDrvCtrl->txEnd)	    txNext -= (pDrvCtrl->txEnd + 1);#ifdef DEBUG	if (seeqDebug)	    logMsg ("TX pkt: @ %04x len %4d space %5d next %04x\n",		    pDrvCtrl->txNext, len, TX_SPACE(pDrvCtrl), txNext,		    0, 0);#endif	/* place a transmit request (while TX possibly running) */	/* Setup for writing */	if (seeqSetDMAWrite(pDrvCtrl, pDrvCtrl->txNext) != OK)	    error = TRUE;	if (error == FALSE)	    {	    /* Write a dummy header, so TX will stop if it catches up. */	    SEEQ_WRITE (pDev->pBwind, 0);	    SEEQ_WRITE (pDev->pBwind, 0);	    /* Write out the packet, two bytes at a time */	    for ( ; len >= 2; len -= 2, buf += 2)		{		SEEQ_WRITE (pDev->pBwind, *(USHORT *)buf);		}	    if (len)		{		SEEQ_WRITE_BYTE (pDev->pBwind, *buf);		}	    /* Write dummy end header to stop chain */	    SEEQ_WRITE (pDev->pBwind, 0);	    SEEQ_WRITE (pDev->pBwind, 0);	    /* Flush FIFO and move back and write the real header */	    if (seeqSetDMAWrite (pDrvCtrl, pDrvCtrl->txNext) != OK)		error = TRUE;	    }	if (error == FALSE)	    {	    /* TX packet header: next pointer (2 bytes) */	    SEEQ_WRITE (pDev->pBwind, txNext);	    /* TX packet header: cmd and status bytes */	    SEEQ_WRITE (pDev->pBwind,			((SEEQ_TX_CMD_SUCC_EN			 | SEEQ_TX_CMD_DATA			 | SEEQ_TX_CMD_CHAIN			 | SEEQ_TX_CMD_XMIT) << SEEQ_MSB_SHIFT));	    /* Flush FIFO */	    if (seeqFlushFIFO (pDrvCtrl) != OK)		error = TRUE;	    }	if (error == FALSE)	    {	    /* If TX has stopped, reload xmit pointer. */	    if (!(SEEQ_READ(pDev->pStat) & SEEQ_STAT_TX_ON))		{		SEEQ_WRITE (pDev->pTxptr, pDrvCtrl->txNext);		}	    /* Adjust pointer to next buffer */	    pDrvCtrl->txNext = txNext;	    /* Turn on Tx and ack the buffer interrupt */	    SEEQ_WRITE (pDev->pCmd,  			((SEEQ_READ(pDev->pStat) & SEEQ_STAT_CMD_MASK)			 | SEEQ_CMD_TX_ON | SEEQ_CMD_BUF_ACK));	    }	if (error == TRUE)	    seeqTxReset (pDrvCtrl->unit);	}    splx (s);    }/******************************************************************************** seeqIoctl - the driver I/O control routine** Process an ioctl request.** NOMANUAL*/LOCAL int seeqIoctl    (    IDR  *ifp,    int            cmd,    caddr_t        data    )    {    int error = OK;    switch (cmd)        {      case (int)SIOCSIFADDR:	ifp->ac_ipaddr = IA_SIN (data)->sin_addr;	break;      case (int)SIOCSIFFLAGS:	/* No further work to be done */	break;      default:	error = EINVAL;        }    return (error);    }

⌨️ 快捷键说明

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