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

📄 if_lnisa.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	    printf ("Lance Error during initialization:\t0x%x\n",		    stat);	    }	}    /* log chip initialization failure */    if ( (stat & CSR0_ERR) || (timeoutCount >= 0x10000) )        {        printf ("lnIsa%d: Device initialization failed\n",                    pDrvCtrl->idr.ac_if.if_unit);        return (ERROR);        }    /* Device is initialized.  Start transmitter and receiver.  The device     * RAP register is left selecting CSR 0.     */    lnCsrWrite(pDrvCtrl, 0, CSR0_IDON | CSR0_IENA | CSR0_STRT);    }    sysIntEnablePIC (ilevel);                   /* enable LANCE interrupts */    pDrvCtrl->idr.ac_if.if_flags |= (IFF_UP | IFF_RUNNING | IFF_NOTRAILERS);    } /* Block end; device initialization */    /* Set our flag */    pDrvCtrl->attached = TRUE;    return (OK);}/********************************************************************************* lnReset - reset the interface** Mark interface as inactive & reset the chip*/static void lnReset    (    int unit    )    {    DRV_CTRL *pDrvCtrl = & drvCtrl [unit];    pDrvCtrl->idr.ac_if.if_flags = 0;    lnChipReset (pDrvCtrl);                           /* reset LANCE */    }/********************************************************************************* lnInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.*/static void lnInt    (    DRV_CTRL  *pDrvCtrl    )    {    ln_tmd         *tmd;    int            *pDindex;    int            *pTindex;    int            *pTsize;    ln_tmd         *pTring;    USHORT	   stat;    /* Read the device status register */        stat = lnCsrRead (pDrvCtrl, 0);    /* If false interrupt, return. */    if ( ! (stat & CSR0_INTR) )        return;    /*     * enable interrupts, clear receive and/or transmit interrupts, and clear     * any errors that may be set.     */    lnCsrWrite (pDrvCtrl, 0, ((stat &            (CSR0_BABL|CSR0_CERR|CSR0_MISS|CSR0_MERR|             CSR0_RINT|CSR0_TINT|CSR0_IDON)) | CSR0_IENA));    /* Check for errors */    if (stat & (CSR0_BABL | CSR0_MISS | CSR0_MERR))        {        ++pDrvCtrl->idr.ac_if.if_ierrors;        /* restart chip on fatal error */        if (stat & CSR0_MERR)        /* memory error */            {            pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);            (void) netJobAdd (                             (FUNCPTR)lnRestart,                             pDrvCtrl->idr.ac_if.if_unit,                             1,(int)stat,0,0                             );            }        }    /* Have netTask handle any input packets */    if ((stat & CSR0_RINT) && (stat & CSR0_RXON))        {        if ( ! (pDrvCtrl->flags & LS_RCV_HANDLING_FLAG) )            {            pDrvCtrl->flags |= LS_RCV_HANDLING_FLAG;            (void) netJobAdd (                             (FUNCPTR)lnHandleRecvInt,                             (int)pDrvCtrl,                             0,0,0,0                             );            }        }    /*     * Did LANCE update any of the TMD's?     * If not then don't bother continuing with transmitter stuff     */    if (!(stat & CSR0_TINT))        return;    pDindex = &pDrvCtrl->dindex;    pTindex = &pDrvCtrl->tindex;    pTsize  = &pDrvCtrl->tsize;    pTring  = pDrvCtrl->tring;    while (*pDindex != *pTindex)        {        /* disposal has not caught up */        tmd = pTring + *pDindex;        /* if the buffer is still owned by LANCE, don't touch it */        LN_CACHE_INVALIDATE (tmd, TMD_SIZ);        if (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 ((tmd->tbuf_tmd1 & TMD1_ERR) || 	    (tmd->tbuf_tmd3 & TMD3_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 (tmd->tbuf_tmd3 & TMD3_RTRY)                pDrvCtrl->idr.ac_if.if_collisions++;            /* check for no carrier */            if (tmd->tbuf_tmd3 & TMD3_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 ((tmd->tbuf_tmd3 & TMD3_BUFF) || 		(tmd->tbuf_tmd3 & TMD3_UFLO))                {                pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);                (void) netJobAdd (                                 (FUNCPTR)lnRestart,                                 pDrvCtrl->idr.ac_if.if_unit,                                 2,(int)(tmd->tbuf_tmd3),0,0                                 );                return;                }            }        tmd->tbuf_tmd1 &= 0x00ff;   /* clear status/err bits, keep hadr bits */        tmd->tbuf_tmd3 = 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 ((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    )    {    ENET_HDR    *pEnetHdr;    MBUF        *pMbuf;    u_char      *pData;    int         len;    u_short     ether_type;    BOOL        hookAte;    /* Packet must be checked for errors. */    if  (        /* If error flag */        (rmd->rbuf_rmd1 & (RMD1_ERR | RMD1_FRAM)) ||        /* OR if packet is not completely in one buffer */        (        (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 */        }    ++pDrvCtrl->idr.ac_if.if_ipackets;			/* bump statistic */    len = rmd->rbuf_mcnt & RMD3_MCNT_MSK;	/* get packet length */    /* Get pointer to packet */    pEnetHdr = (ENET_HDR *)                (pDrvCtrl->rmd_ring.r_bufs + (pDrvCtrl->rindex * LN_BUFSIZ));    LN_CACHE_INVALIDATE (pEnetHdr, len);   /* make the packet data coherent */    /* 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->type );        /* 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);	          }    /* Done with descriptor, clean up and give it to the device. */    cleanRXD:    /* clear status bits */    rmd->rbuf_rmd1 &= 0x00ff;	/* clear status/err bits, keep address */    rmd->rbuf_mcnt = 0;		/* reset count */    rmd->rbuf_rmd1 |= RMD1_OWN;	/* give device ownership */    /* Flush the write pipe */    CACHE_PIPE_FLUSH ();    /* Advance our management index */    pDrvCtrl->rindex = (pDrvCtrl->rindex + 1) & (pDrvCtrl->rsize - 1);    return (OK);    }/********************************************************************************* 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;    BOOL        hookAte;    /* 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  (((tmd->tbuf_tmd1 & TMD1_OWN) != 0) ||        (((pDrvCtrl->tindex + 1) & (pDrvCtrl->tsize - 1)) == pDrvCtrl->dindex))        {        m_freem (pMbuf);            /* Discard data */        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);

⌨️ 快捷键说明

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