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

📄 if_enp.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    return (OK);    }#ifdef BSD43_DRIVER/********************************************************************************* enpOutput - the driver's output routine** The destination address is passed to this function as a pointer to a* generic socket address structure.  This address information is first* converted to the six byte destination address and type field that we* need to build a proper Ethernet frame.** The data to be sent out is held in a chain of mbufs.  This function is* passed a pointer to the head mbuf.  The data in each mbuf fragment must* be copied to the device's packet buffer.*/LOCAL STATUS enpOutput    (    IDR *pIDR,    MBUF *pMbuf,    SOCK *pDest    )    {    int         lostCarrier;    int         blen;    u_short     packetType;    u_char      *bufStart;    DRV_CTRL    *pDrvCtrl;    ENPDEVICE   *pDev;    MBUF        *pTempMbuf;    BCB         *pBCB;    u_char      *pBuf;    char        destEnetAddr [6];#ifdef ENP_DEBUG    printf ( "enp: output: pIDR=%x, pMbuf=%x, pDest=%x\n",             pIDR, pMbuf, pDest );#endif    /* 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];    pDev = (ENPDEVICE *) pDrvCtrl->enpAddr;    /* 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);    /* some boards (eg. iv3201a,hkv2f,mv133) get bus errors with 32bit access */    READLONG (&pDev->enp_stat.e_lost_carrier, &lostCarrier);    lostCarrier = ntohl (lostCarrier);    if (lostCarrier > pDrvCtrl->lostCarrier)        {        /* The test should probably be "not equal", however, roll-over         * will take a long time.  After reset pDrvCtrl->lostCarrier won't         * be in sync -- we should initialize (i.e. read) it elsewhere.         *         * Keep a separate count of lost carrier so statics don't         * get messed up.         */        pDrvCtrl->lostCarrier = lostCarrier;#ifdef ENP_DEBUG        logMsg  ("enp%d: lost carrier\n",                pDrvCtrl->idr.ac_if.if_unit, 0, 0, 0, 0, 0);#endif        }    /* If no resource available, discard packet */    if (enpringempty ((RING *) &pDev->enp_hostfree))        {        semGive (pDrvCtrl->TxSem);          /* Release exclusive access. */        m_freem (pMbuf);        return (OK);        }    pBCB = (BCB *) enpringget ((RING *)&pDev->enp_hostfree);    /* Get pointer to buffer to fill with outgoing packet */    READLONG ((&pBCB->b_addr),  &bufStart);    bufStart = (u_char *) ntohl ((int)bufStart);    /* First fill in the Ethernet header */    pBuf = bufStart;    bcopyBytes (destEnetAddr, (char *) pBuf, 6);    pBuf += 6;    bcopyBytes ((char *) pDrvCtrl->idr.ac_enaddr, (char *) pBuf, 6);    pBuf += 6;    bcopyBytes ( (char *)&packetType, (char *) pBuf, 2);    pBuf += 2;    /* copy data from mbufs to enp a word at a time.     * most other netif drivers use copy_from_mbufs() to accomplish     * this task.  we're doing this manually here because we     * need to take care of a special case (hkv2f + ENP, see below).     */    pTempMbuf = pMbuf;                      /* copy ptr */    while (pTempMbuf != NULL)        {        /* if destination adrs starts at odd byte boundary         * copy a byte at a time.  copying a word from hkv2f into ENP memory         * starting at an odd byte causes problems.         */        if (((int) pBuf & 1) == 1)            bcopyBytes  (                        mtod (pTempMbuf, char *),                        (char *) pBuf,                        (int) pTempMbuf->m_len                        );        else            {            blen = pTempMbuf->m_len >> 1;            /* copy 2 bytes at a time */            bcopyWords (mtod (pTempMbuf, char *), (char *) pBuf, blen);            /* copy the remaining byte if any */            blen <<= 1;            if (blen != pTempMbuf->m_len)                {                *((char *) (pBuf + blen)) =                    *((char *) (mtod (pTempMbuf, char *) + blen));                }            }        /* Move pointer ahead, and get next mbuf pointer */        pBuf += pTempMbuf->m_len;        pTempMbuf = pTempMbuf->m_next;        }    /* Done with mbufs, release them to system */    m_freem (pMbuf);    /* Set length of packet */    blen = max ( MINPKTSIZE, ((int) pBuf - (int) bufStart) );    pBCB->b_len = htons (blen);    /* Put the BCB on the outgoing ring, and if this is the only entry on     * the ring, generate an interrupt to the ENP by writing to the special     * location in the shared memory space.  Some boards require this     * interrupt, while others work fine without it, and still others perform     * a reset instead of the interrupt.  Go figure.     */    if ( enpringput ((RING *) & pDev->enp_toenp, pBCB) == 1 )        pDev->enp_iow.hst2enp_interrupt = ENPVAL;    /* Bump the statistic counter. */    pIDR->ac_if.if_opackets++;    /* Release exclusive access. */    semGive (pDrvCtrl->TxSem);    return (OK);    }#else/********************************************************************************* enpTxStartup - kick start the transmitter after generic ether_output**/LOCAL void enpTxStartup    (    DRV_CTRL * pDrvCtrl 	/* pointer to driver control structure */    )    {    int         lostCarrier;    int         blen;    u_char      *bufStart;    ENPDEVICE   *pDev;    MBUF        *pTempMbuf;    BCB         *pBCB;    u_char      *pBuf;    MBUF *	pMbuf;    pDev = (ENPDEVICE *) pDrvCtrl->enpAddr;    /* BSD 4.4 drivers already have exclusive access - no semaphore needed. */    /* some boards (eg. iv3201a,hkv2f,mv133) get bus errors with 32bit access */    READLONG (&pDev->enp_stat.e_lost_carrier, &lostCarrier);    lostCarrier = ntohl (lostCarrier);    if (lostCarrier > pDrvCtrl->lostCarrier)        {        /* The test should probably be "not equal", however, roll-over         * will take a long time.  After reset pDrvCtrl->lostCarrier won't         * be in sync -- we should initialize (i.e. read) it elsewhere.         *         * Keep a separate count of lost carrier so statics don't         * get messed up.         */        pDrvCtrl->lostCarrier = lostCarrier;#ifdef ENP_DEBUG        logMsg  ("enp%d: lost carrier\n",                pDrvCtrl->idr.ac_if.if_unit, 0, 0, 0, 0, 0);#endif        }    while (pDrvCtrl->idr.ac_if.if_snd.ifq_head)        {        IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf);        /* If no resource available, discard packet */        if (enpringempty ((RING *) &pDev->enp_hostfree))            {            if (pMbuf != NULL)                m_freem (pMbuf);            break;            }        pBCB = (BCB *) enpringget ((RING *)&pDev->enp_hostfree);        /* Get pointer to buffer to fill with outgoing packet */        READLONG ((&pBCB->b_addr),  &bufStart);        bufStart = (u_char *) ntohl ((int)bufStart);        pBuf = bufStart;        /* copy data from mbufs to enp a word at a time.         * most other netif drivers use copy_from_mbufs() to accomplish         * this task.  we're doing this manually here because we         * need to take care of a special case (hkv2f + ENP, see below).         */        pTempMbuf = pMbuf;                      /* copy ptr */        while (pTempMbuf != NULL)            {            /* if destination adrs starts at odd byte boundary             * copy a byte at a time.  copying a word from hkv2f into ENP memory             * starting at an odd byte causes problems.             */            if (((int) pBuf & 1) == 1)                bcopyBytes  (                            mtod (pTempMbuf, char *),                            (char *) pBuf,                            (int) pTempMbuf->m_len                            );            else                {                blen = pTempMbuf->m_len >> 1;                /* copy 2 bytes at a time */                bcopyWords (mtod (pTempMbuf, char *), (char *) pBuf, blen);                /* copy the remaining byte if any */                blen <<= 1;                if (blen != pTempMbuf->m_len)                    {                    *((char *) (pBuf + blen)) =                        *((char *) (mtod (pTempMbuf, char *) + blen));                    }                }            /* Move pointer ahead, and get next mbuf pointer */            pBuf += pTempMbuf->m_len;            pTempMbuf = pTempMbuf->m_next;            }        /* Done with mbufs, release them to system */        m_freem (pMbuf);        /* Set length of packet */        blen = max ( MINPKTSIZE, ((int) pBuf - (int) bufStart) );        pBCB->b_len = htons (blen);        /* Put the BCB on the outgoing ring, and if this is the only entry on         * the ring, generate an interrupt to the ENP by writing to the special         * location in the shared memory space.  Some boards require this         * interrupt, while others work fine without it, and still others          * perform a reset instead of the interrupt.  Go figure.         */        if ( enpringput ((RING *) & pDev->enp_toenp, pBCB) == 1 )            pDev->enp_iow.hst2enp_interrupt = ENPVAL;        /* Bump the statistic counter. */        pDrvCtrl->idr.ac_if.if_opackets++;        }    return;    }#endif/********************************************************************************* enpIoctl - ioctl for interface** RETURNS: 0, or EINVAL*/LOCAL int enpIoctl    (    IDR *pIDR,    int cmd,    caddr_t data    )    {    int error;    ENPDEVICE* pEnpDev;    DRV_CTRL* pDrvCtrl;        pDrvCtrl = & drvCtrl [pIDR->ac_if.if_unit];#ifdef ENP_DEBUG    printf ( "enp: ioctl: pIDR=%x, cmd=%x, data=%x\n", pIDR, cmd, data );#endif    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:            /* set promiscuous bit according to flags */            if (pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC)                 {                pEnpDev = pDrvCtrl->enpAddr;                pEnpDev->enp_mode |= 0x1000;                }            else                {                pEnpDev = pDrvCtrl->enpAddr;                pEnpDev->enp_mode &= ~0x1000;                }               break;            /* Just set the thing into promiscuous mode. */        case SIOCADDMULTI:        case SIOCDELMULTI:            pEnpDev = pDrvCtrl->enpAddr;            pEnpDev->enp_mode |= 0x1000;            break;        default:            error = EINVAL;        }    return (error);    }

⌨️ 快捷键说明

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