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

📄 if_lnpci.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        /* if the buffer is still owned by LANCE, don't touch it */        LN_CACHE_INVALIDATE (tmd, TMD_SIZ);        if (PCISWAP(tmd->tbuf_tmd1) & TMD1_OWN)            break;        /*         * tbuf_err (TMD1.ERR) is an "OR" of LCOL, LCAR, UFLO or RTRY.         * Note that BUFF is not indicated in TMD1.ERR.         * We should therefore check both tbuf_err and tbuf_buff         * here for error conditions.         */        if ((PCISWAP(tmd->tbuf_tmd1) & TMD1_ERR) || 	    (PCISWAP(tmd->tbuf_tmd2) & TMD2_BUFF))            {            pDrvCtrl->idr.ac_if.if_oerrors++;     /* output error */            pDrvCtrl->idr.ac_if.if_opackets--;            /* If error was due to excess collisions, bump the collision             * counter.  The LANCE does not keep an individual counter of             * collisions, so in this driver, the collision statistic is not             * an accurate count of total collisions.             */            if (PCISWAP(tmd->tbuf_tmd2) & TMD2_RTRY)                pDrvCtrl->idr.ac_if.if_collisions++;            /* check for no carrier */            if (PCISWAP(tmd->tbuf_tmd2) & TMD2_LCAR)                logMsg ("ln%d: no carrier\n",                    pDrvCtrl->idr.ac_if.if_unit, 0,0,0,0,0);            /* Restart chip on fatal errors.             * The following code handles the situation where the transmitter             * shuts down due to an underflow error.  This is a situation that             * will occur if the DMA cannot keep up with the transmitter.             * It will occur if the LANCE is being held off from DMA access             * for too long or due to significant memory latency.  DRAM             * refresh or slow memory could influence this.  Many             * implementation use a dedicated LANCE buffer.  This can be             * static RAM to eliminate refresh conflicts; or dual-port RAM             * so that the LANCE can have free run of this memory during its             * DMA transfers.             */            if ((PCISWAP(tmd->tbuf_tmd2) & TMD2_BUFF) || 		(PCISWAP(tmd->tbuf_tmd2) & TMD2_UFLO))                {                pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);                (void) netJobAdd (                                 (FUNCPTR)lnRestart,                                 pDrvCtrl->idr.ac_if.if_unit,                                 0,0,0,0                                 );                return;                }            }        tmd->tbuf_tmd1 = 0;		/* clear tmd1 */        tmd->tbuf_tmd2 = 0;		/* clear all error & stat stuff */        /* now bump the tmd disposal index pointer around the ring */        *pDindex = (*pDindex + 1) & (*pTsize - 1);        }    /* Flush the write pipe */    CACHE_PIPE_FLUSH ();    }/********************************************************************************* lnHandleRecvInt - 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.*/static void lnHandleRecvInt    (    DRV_CTRL *pDrvCtrl    )    {    ln_rmd *rmd;    do        {        pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;        while ((rmd = lnGetFullRMD (pDrvCtrl)) != NULL)            lnRecv (pDrvCtrl, rmd);        /*         * There is a RACE right here.  The ISR could add a receive packet         * and check the boolean below, and decide to exit.  Thus the         * packet could be dropped if we don't double check before we         * return.         */        pDrvCtrl->flags &= ~LS_RCV_HANDLING_FLAG;        }    while (lnGetFullRMD (pDrvCtrl) != NULL);    /* this double check solves the RACE */    }/********************************************************************************* lnGetFullRMD - get next received message RMD** Returns ptr to next Rx desc to process, or NULL if none ready.*/static ln_rmd *lnGetFullRMD    (    DRV_CTRL  *pDrvCtrl    )    {    ln_rmd   *rmd;    /* Refuse to do anything if flags are down */    if  (        (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING) ) !=        (IFF_UP | IFF_RUNNING)        )        return ((ln_rmd *) NULL);    rmd = pDrvCtrl->rring + pDrvCtrl->rindex;       /* form ptr to Rx desc */    LN_CACHE_INVALIDATE (rmd, RMD_SIZ);    if ((PCISWAP(rmd->rbuf_rmd1) & RMD1_OWN) == 0)        return (rmd);    else        return ((ln_rmd *) NULL);    }/********************************************************************************* lnRecv - process the next incoming packet**/static STATUS lnRecv    (    DRV_CTRL *pDrvCtrl,    ln_rmd *rmd    )    {    struct ether_header * 	pEnetHdr;    MBUF        *pMbuf;    u_char      *pData;    int         len;    u_short     ether_type;    BOOL        hookAte;    /* Packet must be checked for errors. */    if  (        /* If error flag */        (PCISWAP(rmd->rbuf_rmd1) & (RMD1_ERR | RMD1_FRAM)) ||        /* OR if packet is not completely in one buffer */        (        (PCISWAP(rmd->rbuf_rmd1) & (RMD1_STP | RMD1_ENP) ) !=        (RMD1_STP | RMD1_ENP)        )        )        {        ++pDrvCtrl->idr.ac_if.if_ierrors;       /* bump error stat */        goto cleanRXD;                          /* skip to clean up */        }    len = PCISWAP(rmd->rbuf_mcnt) & RMD2_MCNT_MSK;	/* get packet length */    /* Get pointer to packet */    pEnetHdr = (struct ether_header *)                (pDrvCtrl->rmd_ring.r_bufs + (pDrvCtrl->rindex * LN_BUFSIZ));    LN_CACHE_INVALIDATE (pEnetHdr, len);   /* make the packet data coherent */    ++pDrvCtrl->idr.ac_if.if_ipackets;		/* bump statistic */    /* call input hook if any */    hookAte = FALSE;    if  (etherInputHookRtn != NULL)        {        if  (            (* etherInputHookRtn) (&pDrvCtrl->idr.ac_if, (char *)pEnetHdr, len)            )            hookAte = TRUE;        }    /* Normal path; send packet upstairs */    if (hookAte == FALSE)        {        /* Adjust length to size of data only */        len -= ENET_HDR_REAL_SIZ;        /* Get pointer to packet data */        pData = ((u_char *) pEnetHdr) + ENET_HDR_REAL_SIZ;        ether_type = ntohs ( pEnetHdr->ether_type );#ifdef BSD43_DRIVER        /* Copy packet data into MBUFs, using the specified width */        pMbuf = bcopy_to_mbufs (pData, len, 0, (IFNET *) & pDrvCtrl->idr.ac_if,                            pDrvCtrl->memWidth);        if (pMbuf != NULL)            do_protocol_with_type (ether_type, pMbuf, & pDrvCtrl->idr, len);        else            ++pDrvCtrl->idr.ac_if.if_ierrors;    /* bump error statistic */#else        pMbuf = bcopy_to_mbufs (pData, len, 0, &pDrvCtrl->idr.ac_if,                                 pDrvCtrl->memWidth);        if (pMbuf != NULL)            do_protocol (pEnetHdr, pMbuf, &pDrvCtrl->idr, len);        else            ++pDrvCtrl->idr.ac_if.if_ierrors;    /* bump error statistic */#endif        }    /* Done with descriptor, clean up and give it to the device. */    cleanRXD:    /* reset statistics counters and message byte count */    rmd->rbuf_mcnt = 0;    /* reset status bits, reinitialize buffer size, and give device ownership */    rmd->rbuf_rmd1 = PCISWAP((RMD1_BCNT_MSK & - (pDrvCtrl->bufSize)) |                              RMD1_CNST | RMD1_OWN);    /* Flush the write pipe */    CACHE_PIPE_FLUSH ();    /* Advance our management index */    pDrvCtrl->rindex = (pDrvCtrl->rindex + 1) & (pDrvCtrl->rsize - 1);    return (OK);    }#ifdef BSD43_DRIVER/********************************************************************************* lnOutput - the driver output routine**/static int lnOutput    (    IDR  *pIDR,    MBUF *pMbuf,    SOCK *pDest    )    {    char destEnetAddr [6];                  /* space for enet addr */    u_short packetType;                     /* type field for the packet */    DRV_CTRL    *pDrvCtrl;    ln_tmd      *tmd;    char        *buf;    int         len;    int         oldLevel;    /* Check ifnet flags. Return error if incorrect. */    if  (        (pIDR->ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=        (IFF_UP | IFF_RUNNING)        )        return (ENETDOWN);    /* Attempt to convert socket addr into enet addr and packet type.     * Note that if ARP resolution of the address is required, the ARP     * module will call our routine again to transmit the ARP request     * packet.  This means we may actually call ourselves recursively!     */    if (convertDestAddr (pIDR,pDest, destEnetAddr, &packetType, pMbuf) == FALSE)        return (OK);    /* I KNOW returning OK is stupid, but it is correct */    /* Get driver control pointer */    pDrvCtrl = & drvCtrl [pIDR->ac_if.if_unit];    /* Obtain exclusive access to transmitter.  This is necessary because     * certain events can cause netTask to run a job that attempts to transmit     * a packet.  We can only allow one task here at a time.     */    semTake (pDrvCtrl->TxSem, WAIT_FOREVER);    pDrvCtrl->flags |= LS_START_OUTPUT_FLAG;    /* See if next TXD is available */    tmd = pDrvCtrl->tring + pDrvCtrl->tindex;    LN_CACHE_INVALIDATE (tmd, TMD_SIZ);    if  (        ((PCISWAP(tmd->tbuf_tmd1) & TMD1_OWN) != 0) ||        (        ((pDrvCtrl->tindex + 1) & (pDrvCtrl->tsize - 1)) ==        pDrvCtrl->dindex        )        )        {        m_freem (pMbuf);            /* Discard data */        pIDR->ac_if.if_oerrors++;        goto outputDone;        }    /* Get pointer to transmit buffer */    buf = (char *)        (pDrvCtrl->tmd_ring.t_bufs + (pDrvCtrl->tindex * LN_BUFSIZ));    /* Fill in the Ethernet header */    bcopy (destEnetAddr, buf, 6);    bcopy ( (char *) pIDR->ac_enaddr, (buf + 6), 6);    ((ENET_HDR *)buf)->type = htons (packetType);    /* Copy packet from MBUFs to our transmit buffer.  MBUFs are     * transparently freed.     */    bcopy_from_mbufs    (                        (buf + ENET_HDR_REAL_SIZ),                        pMbuf,                        len,                            /* stuffed by macro */                        pDrvCtrl->memWidth                        );    /* Ensure we send a legal size frame. */    len += ENET_HDR_REAL_SIZ;    len = max (ETHERSMALL, len);    /* place a transmit request */    oldLevel = intLock ();          /* disable ints during update */    tmd->tbuf_tmd3 = 0;                     /* clear buffer error status */    /* negative message byte count */    tmd->tbuf_tmd1 &= PCISWAP(~TMD1_BCNT_MSK);    tmd->tbuf_tmd1 |= PCISWAP((TMD1_CNST | TMD1_BCNT_MSK) & -len);    tmd->tbuf_tmd1 |= PCISWAP(TMD1_ENP);    /* buffer is end of packet */    tmd->tbuf_tmd1 |= PCISWAP(TMD1_STP);    /* buffer is start of packet */    tmd->tbuf_tmd1 &= PCISWAP(~TMD1_DEF);   /* clear status bit */    tmd->tbuf_tmd1 &= PCISWAP(~TMD1_MORE);    tmd->tbuf_tmd1 &= PCISWAP(~TMD1_ERR);    tmd->tbuf_tmd1 |= PCISWAP(TMD1_OWN);    /* Flush the write pipe */    CACHE_PIPE_FLUSH ();    intUnlock (oldLevel);   /* now lnInt won't get confused */    /* Advance our management index */    pDrvCtrl->tindex = (pDrvCtrl->tindex + 1) & (pDrvCtrl->tsize - 1);    /* kick start the transmitter, if selected */    if (lnKickStartTx)        lnCsrWrite (pDrvCtrl, 0, (CSR0_INEA | CSR0_TDMD));    pDrvCtrl->flags &= ~LS_START_OUTPUT_FLAG;    /* Bump the statistic counter. */    pIDR->ac_if.if_opackets++;    outputDone:    /* Release exclusive access. */    semGive (pDrvCtrl->TxSem);    return (OK);    }#else           /* BSD43_DRIVER *//********************************************************************************* lnPciStartOutput - the driver output routine**/LOCAL void lnPciStartOutput    (    DRV_CTRL *  pDrvCtrl        /* pointer to driver control structure */    )    {    struct mbuf * pMbuf;    ln_tmd      *tmd;    char        *buf;    int         len;    int         oldLevel;    pDrvCtrl->flags |= LS_START_OUTPUT_FLAG;        /* ??? */    /* See if next TXD is available */   while (pDrvCtrl->idr.ac_if.if_snd.ifq_head)        {        /* Dequeue a packet from the transmit queue. */          IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf);

⌨️ 快捷键说明

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