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

📄 if_nic.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        pDrvCtrl->idr.ac_if.if_oerrors++;        }    /* handle packet received */    if  ((isr & PRX) &&        (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) &&        (!pDrvCtrl->taskRcvActive))        {        pDrvCtrl->taskRcvActive = TRUE;                 /* set flag */        /* defer to netTask */        netJobAdd ((FUNCPTR) nicHandleInt, (int) pDrvCtrl, 0, 0, 0, 0);        }    /* handle packet transmitted */    if  ((isr & PTX) &&        (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) &&                                                /* copy ptr, safety check it */        ((pTxDesc = (TX_DESC *) pDrvCtrl->pTxActive) != NULL))        {        tsr = pNic->Tsr;                          /* read Tx status reg */        pTxDesc->ready = FALSE;                   /* active pkt completed */        if (pTxDesc->next->ready)                 /* if next pkt ready to go */            {            pTxDesc = pTxDesc->next;              /* use next desc */            pDrvCtrl->pTxActive = pTxDesc;        /* update active ptr */            pNic->Tpsr = pTxDesc->addr >> 8;            pNic->Tbcr0 = pTxDesc->len & 0xff;            pNic->Tbcr1 = pTxDesc->len >> 8;            /* Start NIC transmitting. Note that since we could be doing             * a NIC remote DMA transfer at this time, we must maintain the             * state of these bits.             */            pNic->Cr = TXP | (pNic->Cr & (RREAD | RWRITE));            }        else            pDrvCtrl->pTxActive = NULL;             /* transmitter idle */        if (tsr & COL)                              /* collision */            pDrvCtrl->idr.ac_if.if_collisions++;        }    /* handle DMA complete */    if (isr & RDC)        pDrvCtrl->dmaWait = FALSE;                  /* clr the waiting flag */    }/********************************************************************************* nicRestart - restart the device after fatal error*/LOCAL void nicRestart    (    int unit    )    {    int         temp;    int         loopy;    DRV_CTRL    *pDrvCtrl;    NIC_DEVICE  *pNic;                         /* address of device */    pDrvCtrl = & drvCtrl [unit];    pNic = pDrvCtrl->nicAddr;    /* The device has all interrupts disabled and the interface flags are down.     * Our job is to reset the device and our dynamic driver variables,     * bring the device back to life, and put the interface online.     */    temp = RESET_ON;                            /* Issue a hardware reset */    temp = RESET_OFF;                           /* release the reset */    /* Wait for device reset indication */    while ( ! (pNic->Isr & RST) )        ;    pNic->Cr = RPAGE0 | STP;                    /* select page 0 and stop */    pNic->Dcr = NOTLS | FIFO8;    pNic->Rbcr0 = 0;                /* clear remote DMA byte count registers */    pNic->Rbcr1 = 0;    for (loopy = 0; loopy < MAXXMT; loopy++)        pDrvCtrl->txDesc[loopy].ready = FALSE;    pDrvCtrl->pTxNext = pDrvCtrl->txDesc;          /* reset "next Tx" ptr */    pDrvCtrl->pTxActive = NULL;                    /* no active Tx desc */    pDrvCtrl->taskRcvActive = FALSE;               /* reset flag */    pDrvCtrl->NextPkt = CURR;                      /* reset to initial value */    pNic->Rcr = AB;         /* accept broadcast, but not runt or multicast */    pNic->Tcr = MODE1;                          /* internal loopback mode */    pNic->Pstart = PSTART;    pNic->Pstop  = PSTOP;    pNic->Bnry   = BNRY;    pNic->Cr   = RPAGE1;                        /* map in page 1 */    pNic->Par0 = pDrvCtrl->idr.ac_enaddr [0];    pNic->Par1 = pDrvCtrl->idr.ac_enaddr [1];    pNic->Par2 = pDrvCtrl->idr.ac_enaddr [2];    pNic->Par3 = pDrvCtrl->idr.ac_enaddr [3];    pNic->Par4 = pDrvCtrl->idr.ac_enaddr [4];    pNic->Par5 = pDrvCtrl->idr.ac_enaddr [5];    pNic->nic_pg1.mar0 = 0xff;    pNic->nic_pg1.mar1 = 0xff;    pNic->nic_pg1.mar2 = 0xff;    pNic->nic_pg1.mar3 = 0xff;    pNic->nic_pg1.mar4 = 0xff;    pNic->nic_pg1.mar5 = 0xff;    pNic->nic_pg1.mar6 = 0xff;    pNic->nic_pg1.mar7 = 0xff;    pNic->Curr = CURR;    pNic->Cr = RPAGE0;                          /* back to page 0 */    pNic->Tcr = MODE0;                          /* put Tx into normal mode */    pNic->Cr = STA;                             /* start the beast running */    pNic->Isr = 0xff;                           /* clr any pending ints */    pNic->Imr = PRXE|PTXE|TXEE|OVWE|RDCE;       /* enable these ints */    /* Raise the interface flags */    pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS;    }/********************************************************************************* nicHandleInt - defered recv interrupt handler** This function handles the received frames from the device.  It runs in the* context of the netTask, which was triggered by a received packet interrupt.*/LOCAL void nicHandleInt    (    DRV_CTRL *pDrvCtrl    )    {    do        {        pDrvCtrl->taskRcvActive = TRUE;        while (nicRead (pDrvCtrl))            /* process a received frame */            ;        pDrvCtrl->taskRcvActive = FALSE;        } while (nicRead (pDrvCtrl));    }/********************************************************************************* nicRead - read a packet off the interface** nicRead copies packets from local memory into an mbuf and hands it to* the next higher layer.*/LOCAL BOOL nicRead    (    DRV_CTRL *pDrvCtrl    )    {    MBUF *m;    NIC_DEVICE *pNic;                      /* ptr to the NIC registers */    RX_FRAME *pRxFrame;                    /* ptr to our frame storage */    ETH_HDR *eh;                                /* ptr to enet hdr */    u_int len;                                  /* length of the enet pkt */    u_short curr;                               /* current page NIC using */    int oldLevel;    if (!(pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)))        return (FALSE);    pNic = pDrvCtrl->nicAddr;    pRxFrame = &pDrvCtrl->rxFrame;    eh = &pRxFrame->enetHdr;    /*     * See if any unprocessed frames in NIC buffer. Unfortunately, there     * is no reliable way of doing this other than reading the CURR register.     * The NIC designers, in their infinite wisdom, put this register in     * page 1. To access page 1, we need to temporarily disable our interrupt     * handler.     */    oldLevel = intLock ();    pNic->Cr = RPAGE1;                              /* select page 1 */    curr = pNic->Curr;                              /* get current page */    pNic->Cr = RPAGE0;                              /* restore page 0 */    intUnlock (oldLevel);    if (pDrvCtrl->NextPkt == curr)             /* if NIC has not moved ahead */        return (FALSE);    pDrvCtrl->idr.ac_if.if_ipackets++;    /*     * OK, there is work to be done.     * First we copy the NIC receive status header from the NIC buffer     * into our local area. This is done so that we can obtain the length     * of the packet before copying out the rest of it. Note that the length     * field in the NIC header includes the Ethernet header, the data, and     * the 4 byte FCS field.     */    while   (            pktBufRead  (                        pDrvCtrl,                        pDrvCtrl->NextPkt << 8,                        RX_HDR_SIZ,                        (char *) pRxFrame                        )            == ERROR            )        ;    len = pRxFrame->rxHdr.cntL + (pRxFrame->rxHdr.cntH << 8) - 4 /* FCS */;#if 0   /* valid frame checks, for paranoia */    if  (        ((pRxFrame->rxHdr.status & ~PHY) != PRX) ||        (pRxFrame->rxHdr.nextRxPage < PSTART) ||        (pRxFrame->rxHdr.nextRxPage >= PSTOP) ||        (len < 60) || (len > 1514)        )        return (FALSE);#endif    /* copy Ethernet packet section of the frame */    while   (            pktBufRead  (                        pDrvCtrl,                        (pDrvCtrl->NextPkt << 8) + RX_HDR_SIZ,                        len,                        (char *) eh                        )            == ERROR            )        ;    /* done with frame in NIC buf, so update vars */    pDrvCtrl->NextPkt = pRxFrame->rxHdr.nextRxPage;/* where dev will use next */    pNic->Bnry = (pDrvCtrl->NextPkt == PSTART) ?   /* if dev is at beginning */                (PSTOP - 1) :                     /* boundary is 1 before end */                (pDrvCtrl->NextPkt - 1);           /* else it's 1 before next */    /* call input hook if any */    if (etherInputHookRtn != NULL)        if  ( (* etherInputHookRtn) (&pDrvCtrl->idr.ac_if, (char *)eh, len))            return (TRUE);    len -= sizeof (ETH_HDR);            /* now equals length of data only */    m = copy_to_mbufs   (                        pRxFrame->data,                        len,                        0,                        (IFNET *) & pDrvCtrl->idr.ac_if                        );    if (m != NULL)#ifdef BSD43_DRIVER        do_protocol_with_type (eh->ether_type, m, &pDrvCtrl->idr, len);#else        do_protocol (eh, m, &pDrvCtrl->idr, len);#endif    else        pDrvCtrl->idr.ac_if.if_ierrors++;    return (TRUE);    }#ifdef BSD43_DRIVER/********************************************************************************* nicOutput - the driver's output routine** This function attempts to copy the data from the mbuf chain to the buffer* that NIC transmits from.  If successfull, and the NIC is not currently busy* transmitting, it then attempts to start the NIC transmitting.*/LOCAL int nicOutput    (    IDR  *pIDR,    MBUF *pMbuf,    SOCK *pDest    )    {    int         unit;    int         oldLevel;    u_long      nicBufAddr;    MBUF        *pTempMbuf;    DRV_CTRL    *pDrvCtrl;    NIC_DEVICE  *pNic;    TX_DESC     *pTxNext;                   /* ptr to next desc to use */    ETH_HDR     enetHdr;                    /* space for the packet header */    /* init ptrs */    unit = pIDR->ac_if.if_unit;    pDrvCtrl = & drvCtrl [unit];    pNic = pDrvCtrl->nicAddr;          /* copy it, due to frequent use */    /* Check ifnet flags. Return error if incorrect. */    if  (        (pIDR->ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=        (IFF_UP | IFF_RUNNING)        )        {        m_freem (pMbuf);                /* release MBUFs */        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,                        &enetHdr.ether_dhost,     /* fill our local header */                        &enetHdr.ether_type, /* fill our local header */                        pMbuf                        )        == FALSE        )        return (OK);    /* Get next transmit resource */    pTxNext = pDrvCtrl->pTxNext;        /* copy it, due to frequent use */    if (pTxNext->ready)                 /* if still in use */        {        m_freem (pMbuf);                /* release MBUFs */        return (ENETDOWN);        }    /* Fill in the source address of the Ethernet header */    bcopy ( (char *) pIDR->ac_enaddr, &enetHdr.ether_shost, 6 );    /* copy Ethernet header to NIC buffer */    nicBufAddr = pTxNext->addr;    while   (            pktBufWrite (                        pDrvCtrl,                        nicBufAddr,                        ENET_HDR_REAL_SIZ,                        (char *) & enetHdr                        )            == ERROR            )            ;    /* copy mbufs to NIC buffer */    pTempMbuf = pMbuf;                      /* copy head of MBUF chain */    for (        nicBufAddr += (u_long) ENET_HDR_REAL_SIZ;        pTempMbuf != NULL;        nicBufAddr += (u_long) pTempMbuf->m_len, pTempMbuf = pTempMbuf->m_next)        {        while            (            pktBufWrite (                        pDrvCtrl,                        nicBufAddr,                        pTempMbuf->m_len,                        mtod (pTempMbuf, caddr_t)                        )            == ERROR            )            ;        }    pTxNext->len = max (MINPKTSIZE, (nicBufAddr - pTxNext->addr));    m_freem (pMbuf);                       /* free the mbufs */    oldLevel = intLock ();                 /* keep our int handler out */    pTxNext->ready = TRUE;                 /* mark packet as "ready" */    if (pDrvCtrl->pTxActive == NULL)       /* if transmitter not active */        {        pDrvCtrl->pTxActive = pTxNext;           /* set active ptr */        pNic->Tpsr = pTxNext->addr >> 8;        pNic->Tbcr0 = pTxNext->len & 0xff;        pNic->Tbcr1 = pTxNext->len >> 8;        pNic->Cr = TXP;                    /* start NIC transmitting */        }    pDrvCtrl->pTxNext = pTxNext->next;     /* move ptr to next desc */    intUnlock (oldLevel);                  /* allow interrupts again */    /* Bump packet counter */    pIDR->ac_if.if_opackets++;    return (0);    }#else/********************************************************************************* nicTxStartup - the driver's output routine** This function attempts to copy the data from the mbuf chain to the buffer

⌨️ 快捷键说明

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