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

📄 if_elt.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                }            }        else if (pDrvCtrl->interruptTime == -1)            ++pDrvCtrl->eltStat.timerInvalid;        pDrvCtrl->interruptTime = -2;        }#endif /* ELT_TIMING */        while ( (pFrame = pDrvCtrl->pRxCurrent) != NULL)            {            statusRx = sysInWord(port + RX_STATUS);            if (statusRx & RX_S_INCOMPLETE)	/* incomplete */	        {                if (statusRx == RX_S_INCOMPLETE)	/* no bytes available */		    break;                while ((statusRx != (statusRxNew = sysInWord(port + RX_STATUS)))		       && (ix < 10000))		    {		    statusRx = statusRxNew;   		    ix++;	/* XXX */		    }	        }#ifdef ELT_DEBUG            logMsg ("eltInt: statusRx=%04x ix=%d\n", statusRx, ix, 0, 0, 0, 0);#endif /* ELT_DEBUG */                /* Copy the FIFO data into the buffer */            length = statusRx & RX_S_CNT_MASK;            /* Prevent buffer overflow.             * should we discard the packet? that's hard to do safely here.	     * so truncate packet	     */            if ( (pFrame->count + length) > MAX_FRAME_SIZE)                length = MAX_FRAME_SIZE - pFrame->count;            /* transfer only an even number of bytes to leave the pointer             * on an even boundary until we reach the end of the frame             */            if ( (statusRx & RX_S_INCOMPLETE) != 0)                length &= PARTIAL_TRANSFER_MASK;            sysInWordString (port + DATA_REGISTER, (short *) pFrame->nextByte,                             (length + 1) / 2);            pFrame->count += length;            pFrame->nextByte += length;	    /* partial packet, wait for complete packet */            if ( (statusRx & RX_S_INCOMPLETE) != 0)                break;	    /*	     * Packet is now complete. Use 'Discard' command to complete the 	     * transfer	     */            sysOutWord (port + ELT_COMMAND, RX_DISCARD); /* discard packet */            while ( (sysInWord (port + ELT_STATUS) & COMMAND_IN_PROGRESS) != 0)                ;                           /* wait for command to finish */            /* Check for errors in completed packet */            if ( (statusRx & RX_S_ERROR) != 0)                {                switch (statusRx & RX_S_CODE_MASK)                    {                    case RX_S_OVERRUN:	/* handled by statistics registers */                        break;                    case RX_S_RUNT:                        ++pDrvCtrl->eltStat.shortPacket;                        break;                    case RX_S_ALIGN:                        ++pDrvCtrl->eltStat.aligns;                        break;                    case RX_S_CRC:                        ++pDrvCtrl->eltStat.crcs;                        break;                    case RX_S_OVERSIZE:                        ++pDrvCtrl->eltStat.badPacket;                        break;                    default:		/* no other codes are defined */                        break;	                    }                ++pDrvCtrl->eltStat.rxerror;                ++pDrvCtrl->idr.ac_if.if_ierrors;   /* bump error counter */                pFrame->count = 0;                pFrame->nextByte = pFrame->header;                pFrame->length = 0;                continue;                }            /* Got a complete packet, count it. */            ++pDrvCtrl->idr.ac_if.if_ipackets;            pFrame->length = statusRx;            pDrvCtrl->pRxCurrent = pDrvCtrl->pRxCurrent->lNext;            }#ifdef ELT_TIMING        pDrvCtrl->interruptTime = -1;#endif /* ELT_TIMING */        /* receive no more for now */        if (pDrvCtrl->pRxCurrent == NULL)            pDrvCtrl->intMask &= ~(RX_COMPLETE | RX_EARLY);        if (!pDrvCtrl->rxHandling && (pDrvCtrl->pRxHead->length != 0))            {            result = netJobAdd ( (FUNCPTR) eltRxDeliver, (int) pDrvCtrl,                                 0, 0, 0, 0);#ifdef ELT_DEBUG            if (result == ERROR)                logMsg ("elt: netJobAdd (eltRxDeliver) failed\n",                        0, 0, 0, 0, 0, 0);#endif /* ELT_DEBUG */#ifdef ELT_TIMING            if (result != ERROR)                if ( (int)++pDrvCtrl->eltStat.taskQRxOuts >                          (int)pDrvCtrl->eltStat.maxRxTaskQ)                     pDrvCtrl->eltStat.maxRxTaskQ =                               pDrvCtrl->eltStat.taskQRxOuts;#endif /* ELT_TIMING */            pDrvCtrl->rxHandling = TRUE;            }        }    /* Handle transmitter interrupts */    if ( (status & TX_COMPLETE) != 0)        {        if ( ( (statusTx = sysInByte (port + TX_STATUS)) & TX_S_COMPLETE) != 0)            {            sysOutByte (port + TX_STATUS, 0);       /* clear old status */            /* other errors are tabulated by reading the statistics registers */            if ( (statusTx & TX_S_MAX_COLL) != 0)                pDrvCtrl->idr.ac_if.if_collisions += 16;            if ( (statusTx & TX_S_JABBER) != 0)                ++pDrvCtrl->eltStat.jabbers;                        if ((statusTx & (TX_S_JABBER | TX_S_MAX_COLL | TX_S_UNDERRUN)) != 0)                {                needTxStart = TRUE;                 /* restart transmitter */                /* packet not sent */                pDrvCtrl->idr.ac_if.if_oerrors++;   /* incr err count */                pDrvCtrl->idr.ac_if.if_opackets--;  /* decr sent count */                }            if ( (statusTx & (TX_S_JABBER | TX_S_UNDERRUN)) != 0)                {                /* Must reset transmitter; this clears the tx FIFO */                sysOutWord (port + ELT_COMMAND, TX_RESET);                }            }        if (needTxStart)                            /* check flag */            eltTxStart (pDrvCtrl);        if (pDrvCtrl->idr.ac_if.if_snd.ifq_head != NULL)            {            if (!pDrvCtrl->txHandling)                {                if (netJobAdd ( (FUNCPTR) eltTxFlush, (int) pDrvCtrl, (int) TRUE,                                0, 0, 0) == ERROR)                    {#ifdef ELT_DEBUG                    logMsg ("elt: netJobAdd (eltTxFlush) failed\n",                            0, 0, 0, 0, 0, 0);#endif /* ELT_DEBUG */                    }                else                    pDrvCtrl->txHandling = TRUE;#ifdef ELT_TIMING                if ( (int)++pDrvCtrl->eltStat.taskQTxOuts >                     (int)pDrvCtrl->eltStat.maxTxTaskQ)                    pDrvCtrl->eltStat.maxTxTaskQ = pDrvCtrl->eltStat.taskQTxOuts;#endif /* ELT_TIMING */                }            }        }    /* Handle update statistics interrupt */    if ( (status & UPDATE_STATS) != 0)        eltStatFlush (pDrvCtrl);    /* mask and ack the events we've just handled or queued handlers for */    sysOutWord (pDrvCtrl->port + ELT_COMMAND, MASK_STATUS | pDrvCtrl->intMask);    sysOutWord (pDrvCtrl->port + ELT_COMMAND, ACK_INTERRUPT | status);    sysBusIntAck (pDrvCtrl->intLevel);    }/********************************************************************************* eltTxFlush - transmit a packet from the output queue** This routine, if the transmitter is currently idle, and if there is a* packet in the output queue, dequeues a packet and transmits it.  The* next transmit activity will be a completion interrupt, which will cause* this routine to be scheduled again if there is a packet in the output* queue.*/static void eltTxFlush    (    ELT_CTRL *  pDrvCtrl,    BOOL        netJob    )    {    int port;    ELT_FRAME * pFrame;    UINT16 outputCount;    MBUF * m;    port = pDrvCtrl->port;    pFrame = pDrvCtrl->pTxFrame;    do        {        if (netJob)            pDrvCtrl->txHandling = TRUE;        /* Don't dequeue if currently sending */        while ( (sysInWord (pDrvCtrl->port + TX_FREE_BYTES) >= TX_IDLE_COUNT) &&                (pDrvCtrl->idr.ac_if.if_snd.ifq_head != NULL))            {            IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, m);            copy_from_mbufs (pFrame->header, m, outputCount);            outputCount = max (ETHERSMALL, outputCount);            if ( (etherOutputHookRtn != NULL) &&                 (* etherOutputHookRtn)                 (&pDrvCtrl->idr, pFrame->header, outputCount))                continue;            pFrame->length = outputCount | TX_F_INTERRUPT;            outputCount = (outputCount + TX_F_PREAMBLE_SIZE + 3) &                          TX_F_DWORD_MASK;            sysOutWordString (port + DATA_REGISTER, (short *) & pFrame->length,                              outputCount / 2);            /* Bump the statistic counter. */#ifdef ELT_DEBUG            printf ("Packet sent.\n");            fflush (stdout);#endif /* ELT_DEBUG */#ifndef BSD43_DRIVER            pDrvCtrl->idr.ac_if.if_opackets++;#endif            break;                      /* ISR must call eltTxCleanup() */            }        if (netJob)            pDrvCtrl->txHandling = FALSE;        }    while ( (sysInWord (pDrvCtrl->port + TX_FREE_BYTES) >= TX_IDLE_COUNT) &&            (pDrvCtrl->idr.ac_if.if_snd.ifq_head != NULL));#ifdef ELT_TIMING    --pDrvCtrl->eltStat.taskQTxOuts;#endif /* ELT_TIMING */    }/********************************************************************************* eltRxDeliver - pass received frames to the next layer up** Strips the Ethernet header and passes the packet to the appropriate* protocol.  If there are enough received frame buffers, the packet may* be passed to the protocol in the frame buffer.* In this latter case, the frame buffer will* eventually be returned by the protocol, via a call to our eltLoanFree().*/static void eltRxDeliver    (    ELT_CTRL * pDrvCtrl    )    {    volatile ELT_FRAME * pFrame;    UINT16      length;    struct ether_header *   pEh;    u_char *    pData;    UINT16      etherType;    MBUF *      pMbuf;#ifdef ELT_DEBUG    printf ("Elt: Handling received packet.\n");    fflush (stdout);#endif /* ELT_DEBUG */    do        {        pDrvCtrl->rxHandling = TRUE;        while ( ( (pFrame = pDrvCtrl->pRxHead) != NULL) &&                (pFrame->length != 0))            {            pDrvCtrl->pRxHead = pFrame->lNext;            length = pFrame->count - EH_SIZE;            pEh = (struct ether_header *)pFrame->header;            pData = (u_char *) pFrame->data;            etherType = ntohs (pEh->ether_type);            /* Service input hook */            if (etherInputHookRtn != NULL)                {                if ( (* etherInputHookRtn) (&pDrvCtrl->idr, (char *)pEh,                                            length) )                    {                    eltRxFree (pDrvCtrl, (ELT_FRAME *)pFrame);                    continue;                    }                }#ifdef ELT_DEBUG        printf ("elt: rxDeliver: frame at %08lx, type %04x, length %d, count %d\n",                (long) pFrame, etherType, pFrame->length, pFrame->count);#endif /* ELT_DEBUG */            /* we can loan out receive frames from our pool if:             *             * 1) we have enough (nLoanFrames > 0) and             * 2) size of the input ethernet frame is large enough to be used             *    with clustering.             */            pFrame->refCnt = 0;            if ( (pDrvCtrl->nLoanFrames > 0) && (USE_CLUSTER (length)) &&                 ( (pMbuf = build_cluster (pData, length, &pDrvCtrl->idr, MC_EI,                                     &pFrame->refCnt, eltLoanFree,                                     (int) pDrvCtrl,                                     (int) pFrame, NULL)) != NULL))                {                pDrvCtrl->nLoanFrames -= 1;             /* one less to loan */                }            else                {                pMbuf = copy_to_mbufs (pData, length, 0, &pDrvCtrl->idr);                eltRxFree (pDrvCtrl, (ELT_FRAME *)pFrame);                }            /* deliver mbufs to protocol */#ifdef BSD43_DRIVER            if (pMbuf != NULL)                do_protocol_with_type (etherType, pMbuf, &pDrvCtrl->idr,length);#else            if (pMbuf != NULL)                do_protocol (pEh, pMbuf, &pDrvCtrl->idr, length);#endif            else                ++pDrvCtrl->idr.ac_if.if_ierrors;            }        pDrvCtrl->rxHandling = FALSE;   /* allow self to be rescheduled */        }    while ( ( (pFrame = pDrvCtrl->pRxHead) != NULL) && (pFrame->length != 0));#ifdef ELT_TIMING    --pDrvCtrl->eltStat.taskQRxOuts;#endif /* ELT_TIMING */    }/********************************************************************************* eltLoanFree - return a loaned receive frame buffer** This routine is called by the protocol code when it has completed use of* a frame buffer that we loaned to it.*/static void eltLoanFree    (    ELT_CTRL * pDrvCtrl,    ELT_FRAME * pFrame    )    {    eltRxFree (pDrvCtrl, pFrame);    pDrvCtrl->nLoanFrames += 1;         /* one more to loan */    }/********************************************************************************* eltRxFree - free a received frame buffer** Reinitialize necessary fields in the frame structure and link it to the* tail of the free frames list.  If there was no current frame (the receive* routine had run out of empty buffers), make this the current frame and* unmask receive interrupts in case they were waiting for a buffer.*/

⌨️ 快捷键说明

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