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

📄 if_nic.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
* that NIC transmits from.  If successful, and the NIC is not currently busy* transmitting, it then attempts to start the NIC transmitting.*/LOCAL int nicTxStartup    (    DRV_CTRL * 	pDrvCtrl 	/* pointer to driver control structure */    )    {    MBUF * 	pMbuf;    int         oldLevel;    u_long      nicBufAddr;    MBUF        *pTempMbuf;    NIC_DEVICE  *pNic;    TX_DESC     *pTxNext;                   /* ptr to next desc to use */    pNic = pDrvCtrl->nicAddr;          /* copy it, due to frequent use */    /* Get next transmit resource */    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);        pTxNext = pDrvCtrl->pTxNext;        /* copy it, due to frequent use */        if (pTxNext->ready)                 /* if still in use */            {            m_freem (pMbuf);                /* release MBUFs */            pDrvCtrl->idr.ac_if.if_oerrors++;            break;            }        /* copy mbufs to NIC buffer */        pTempMbuf = pMbuf;                      /* copy head of MBUF chain */        nicBufAddr = pTxNext->addr;        while (pTempMbuf != NULL)            {            while (pktBufWrite (pDrvCtrl, nicBufAddr, pTempMbuf->m_len,                                mtod (pTempMbuf, caddr_t))                   == ERROR)                ;            nicBufAddr += (u_long) pTempMbuf->m_len;            pTempMbuf = pTempMbuf->m_next;            }        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 */        pDrvCtrl->idr.ac_if.if_opackets++;        }    return (0);    }#endif/********************************************************************************* nicIoctl - the driver's I/O control routine**/LOCAL int nicIoctl    (    IDR *pIDR,    int cmd,    caddr_t data    )    {    int error;    error = 0;    switch (cmd)        {        case SIOCSIFADDR:            ((struct arpcom *)pIDR)->ac_ipaddr = IA_SIN (data)->sin_addr;            arpwhohas (pIDR, &IA_SIN (data)->sin_addr);            break;        case SIOCSIFFLAGS:            /* Flags are set outside this module. No additional work to do. */            break;        default:            error = EINVAL;        }    return (error);    }/********************************************************************************* nicEnetAddrGet - get hardwired Ethernet address.** Read the Ethernet address out of the ROM*/LOCAL void nicEnetAddrGet    (    int unit    )    {    DRV_CTRL *pDrvCtrl = & drvCtrl [unit];    NIC_DEVICE *pNic = pDrvCtrl->nicAddr;    int i;    pNic->Rsar0 = 0;                            /* ID ROM starts at 0 */    pNic->Rsar1 = 0;    pNic->Rbcr0 = 6;                            /* length of enet addr */    pNic->Rbcr1 = 0;    pNic->Cr = RREAD;                           /* Start NIC Remote DMA */    for (i = 0; i < 6; i++)        {        while (pNic->Rsar0 == i)            /* wait for byte available */            ;        pDrvCtrl->idr.ac_enaddr [i] = *NIC_BUF_PORT;  /* read byte from port */        }    }/********************************************************************************* nicConfig - configure the NIC chip for Ethernet and program address*/LOCAL void nicConfig    (    int unit    )    {    DRV_CTRL *pDrvCtrl = & drvCtrl [unit];    NIC_DEVICE *pNic = pDrvCtrl->nicAddr;    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;    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;    nicEnetAddrGet (unit);                      /* Get Ethernet address */    /* set up page 1 registers */    pNic->Cr   = RPAGE1;    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 */    }/********************************************************************************* pktBufWrite - write data to NIC buffer*/LOCAL STATUS pktBufWrite    (    DRV_CTRL *pDrvCtrl,    unsigned long nicBufAddr,    unsigned long len,    char *pData    )    {    NIC_DEVICE *pNic;    WE32104 *pDmac;    STATUS status;    if (len == 0)                                       /* nothing to do */        return (OK);    pNic = pDrvCtrl->nicAddr;    pDmac = (WE32104 *) DMA_BASE;    semTake(pDrvCtrl->dmaSem, WAIT_FOREVER);           /* obtain semaphore */    pDrvCtrl->dmaWait = TRUE;                          /* set our flag */    /* set up NIC remote DMA transfer */    pNic->Rsar0 = nicBufAddr;    pNic->Rsar1 = nicBufAddr >> 8;    pNic->Rbcr0 = len;    pNic->Rbcr1 = len >> 8;    /* set up main DMAC transfer */    cacheFlush (DATA_CACHE, pData, len);            /* ensure coherency */    pDmac->Ch2.SourceAdd = (unsigned long) pData;    pDmac->Ch2.TranCount = len;    pDmac->Ch2.Mode = MODE_TT_MP | MODE_DS_LONG | MODE_BR;    /* start both devices doing the transfer */    pDmac->Ch2.StatCont = SCR_STR;    pNic->Cr = RWRITE;    /* wait for interrupt handler to clear our flag */    while (pDrvCtrl->dmaWait)        {        if  (            (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=            (IFF_UP | IFF_RUNNING)            )            {            pDrvCtrl->dmaWait = FALSE;            pDmac->Ch2.StatCont = SCR_SA;               /* abort */            semGive(pDrvCtrl->dmaSem);                  /* release the sem */            return (OK);                                /* this is correct */            }        }    /* check for DMAC error */    if(pDmac->Ch2.StatCont & SCR_ACT)        {        pDmac->Ch2.StatCont = SCR_SA;               /* abort */        status = ERROR;        }    else        status = OK;    semGive(pDrvCtrl->dmaSem);    return (status);    }/********************************************************************************* pktBufRead - read data from NIC buffer*/LOCAL STATUS pktBufRead    (    DRV_CTRL *pDrvCtrl,    unsigned long nicBufAddr,    unsigned long len,    char *pData    )    {    NIC_DEVICE *pNic;    WE32104 *pDmac;    STATUS status;    if (len == 0)                                       /* nothing to do */        return (OK);    /* Avoid starting DMA if device is down to to fatal error */    if  (        (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=        (IFF_UP | IFF_RUNNING)        )        return (OK);    pNic = pDrvCtrl->nicAddr;    pDmac = (WE32104 *) DMA_BASE;    semTake(pDrvCtrl->dmaSem, WAIT_FOREVER);            /* obtain semaphore */    pDrvCtrl->dmaWait = TRUE;                           /* set our flag */    /* set up NIC remote DMA transfer */    pNic->Rsar0 = nicBufAddr;    pNic->Rsar1 = nicBufAddr >> 8;    pNic->Rbcr0 = len;    pNic->Rbcr1 = len >> 8;    /* set up main DMAC transfer */    pDmac->Ch2.DestAdd = (unsigned long) pData;    pDmac->Ch2.TranCount = len;    pDmac->Ch2.Mode = MODE_TT_PM | MODE_DS_LONG | MODE_BR;    /* start both devices doing the transfer */    pDmac->Ch2.StatCont = SCR_STR;    pNic->Cr = RREAD;    /* wait for interrupt handler to clear our flag */    while (pDrvCtrl->dmaWait)        {        if  (            (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=            (IFF_UP | IFF_RUNNING)            )            {            pDrvCtrl->dmaWait = FALSE;            pDmac->Ch2.StatCont = SCR_SA;               /* abort */            semGive(pDrvCtrl->dmaSem);                  /* release the sem */            return (OK);                                /* this is correct */            }        }    /* check for DMAC error */    if(pDmac->Ch2.StatCont & SCR_ACT)        {        pDmac->Ch2.StatCont = SCR_SA;               /* abort */        status = ERROR;        }    else        {        cacheInvalidate (DATA_CACHE, pData, len);   /* ensure coherency */        status = OK;        }    semGive(pDrvCtrl->dmaSem);    return (status);    }#ifdef BSD43_DRIVER#include "sys/socket.h"/********************************************************************************* convertDestAddr - converts socket addr into enet addr and packet type**/static BOOL convertDestAddr    (    IDR *pIDR,                          /* ptr to i/f data record */    SOCK *pDestSktAddr,                 /* ptr to a generic sock addr */    char *pDestEnetAddr,                /* where to write enet addr */    u_short *pPacketType,               /* where to write packet type */    MBUF *pMbuf                         /* ptr to mbuf data */    )    {#ifdef	__STDC__    extern arpresolve   (               /* we call this */                        IDR *,                        MBUF *,                        struct in_addr *,                        char *,                        int *                        );#else	/* __STDC__ */    extern arpresolve   ();#endif	/* __STDC__ */    /***** Internet family *****/    {    struct in_addr destIPAddr;              /* not used */    int trailers;                           /* not supported */     if (pDestSktAddr->sa_family == AF_INET)        {        *pPacketType = ETHERTYPE_IP;            /* stuff packet type */        destIPAddr = ((struct sockaddr_in *) pDestSktAddr)->sin_addr;        if (!arpresolve (pIDR, pMbuf, &destIPAddr, pDestEnetAddr, &trailers))            return (FALSE);     /* if not yet resolved */        return (TRUE);        }    }    /***** Generic family *****/    {    ETH_HDR *pEnetHdr;    if (pDestSktAddr->sa_family == AF_UNSPEC)        {        pEnetHdr = (ETH_HDR *) pDestSktAddr->sa_data;      /* ptr to hdr */        bcopy (pEnetHdr->dst, pDestEnetAddr, 6);            /* copy dst addr */        *pPacketType = pEnetHdr->ether_type;                /* copy type */        return (TRUE);        }    }    /* Unsupported family */    return (FALSE);    }#endif

⌨️ 快捷键说明

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