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

📄 if_egl.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    else        egl->egl_if.if_ierrors++;        /* bump error stat */#else    m = bcopy_to_mbufs (pData, len, 0, &egl->egl_if, eglMemWidth);    if (m != NULL)        do_protocol (eh, m, &egl->egl_ac, len);    else        egl->egl_if.if_ierrors++;        /* bump error stat */#endif    }/********************************************************************************* egl_reset - mark interface as inactive & reset the chip** RETURNS: 0 or -1.*/LOCAL STATUS egl_reset    (    int unit    )    {    EGL_SOFTC *egl;    volatile SHIO *shio;    struct ifnet *ifp;    int s;    if (unit < 0 || unit >= NEGL)        return (-1);    egl  = egl_softc [unit];    shio = egl->eglAddr;    ifp  = &egl->egl_if;#ifdef EGL_DEBUG    printf ("egl%d: egl_reset\n", unit, 0, 0, 0, 0, 0);#endif  /* EGL_DEBUG */    s = splimp ();    ifp->if_flags &= ~IFF_RUNNING;    if (egl_physreset (unit) != OK)        {        splx (s);#ifdef EGL_DEBUG        logMsg ("egl%d: reset failed\n", unit, 0, 0, 0, 0, 0);#endif        return (-1);        }    splx (s);    return (0);    }/********************************************************************************* egl_rint - Ethernet interface receive (& error) interrupt*/LOCAL void egl_rint    (    int unit,    EGL_SOFTC *egl,    int index,    int len    )    {    ETH_BUF *eth_buf;    if (len != -1)        {        eth_buf = egl->egl_rbinfo[index];        egl->egl_rbinfo[index] = NULL;        egl_ioflush (eth_buf);          /* definitly need on receive */        egl_recv (unit, len, eth_buf);        REL_ETH_BUF(eth_buf);        }    (void)egl_hangrcv (unit, index);    /* hang another receive request */    egl->egl_qfull = 0;                 /* at least one slot open now */    }/********************************************************************************* egl_setiopbs - setup iopb's*/LOCAL void egl_setiopbs    (    int unit    )    {    EGL_SOFTC *egl = egl_softc [unit];    volatile SHIO *shio = egl->eglAddr;    volatile IOPB *iopb;    int ix;    ETH_BUF *eth_buf;    iopb = &shio->sh_IOPB[EGL_RX_IOPBF];    for (ix = 0; ix < EGL_RX_NBUFF; ix++)        {        iopb->iopb_OPTION = M_OPT_DMA | M_OPT_IE;        iopb->iopb_CMD  = CNTR_RECEIVE;        iopb->iopb_NVCT = egl->rcv_vec;        iopb->iopb_EVCT = egl->rcverr_vec;        if (BLOCKMODE)            iopb->iopb_TOPT = EGL_TOPT_BLK | DIR_READ;        else            iopb->iopb_TOPT = EGL_TOPT | DIR_READ;        /* use the Host usable buffer region */        if ((eth_buf = egl->egl_rbinfo[ix]) == NULL)            GET_ETH_BUF(eth_buf);        /* egl_rbinfo[i] always uses iopb at index (EGL_RX_IOPBF+i) */        eth_buf->eth_len          = EGL_MTU;        egl->egl_rbinfo[ix]       = eth_buf;        egl->egl_rbinfo[ix]->iopb = (IOPB*)iopb;        egl_ioflush (eth_buf);        iopb->iopb_BUFF   = eth_buf->eth_dat_adr;        iopb->iopb_LENGTH = EGL_MTU;        iopb->iopb_HBUF   = 0;        iopb->iopb_PTLF   = 0;        bzero ((char*)iopb->iopb_NODE, sizeof(iopb->iopb_NODE));        iopb->iopb_SGEC = 0;        iopb->iopb_LAN1 = 0;        iopb->iopb_LAN3 = 0;        iopb++;        }    iopb = &shio->sh_IOPB[EGL_TX_IOPBF];    for (ix = 0; ix < EGL_TX_NBUFF; ix++)        {        iopb->iopb_CMD = CNTR_TRANSMIT;        iopb->iopb_OPTION = M_OPT_DMA | M_OPT_IE;        iopb->iopb_NVCT = egl->xmit_vec;        iopb->iopb_EVCT = egl->xmiterr_vec;        /* We need to recover any hung transmit buffers if         * initialization is due to a HW reset after an error         * such as a transmit timeout.         */        if ((eth_buf = egl->egl_tbinfo[ix]) != NULL)            {            egl->egl_tbinfo[ix] = NULL;            egl_ioflush (eth_buf);            REL_ETH_BUF(eth_buf);            }        if (BLOCKMODE)            iopb->iopb_TOPT = EGL_TOPT_BLK | DIR_WRITE;        else            iopb->iopb_TOPT = EGL_TOPT | DIR_WRITE;        iopb->iopb_HBUF = 0;        iopb->iopb_SGEC = 0;        iopb->iopb_LAN1 = 0;        iopb->iopb_LAN3 = 0;        iopb++;        }    egl->egl_txadd  = egl->egl_txrem = EGL_TX_NBUFF-1;    egl->egl_quecnt = egl->egl_txcnt = 0;    egl->egl_cqe    = (CQE *)&shio->sh_CQE[0];    }/********************************************************************************* egl_start - start or re-start output on interface** Get another datagram to send off of the interface queue,* and add it to the transmit packet queue for the interface.*/#ifdef BSD43_DRIVERLOCAL void egl_start    (    int unit    )    {    EGL_SOFTC *egl      = egl_softc [unit];#elseLOCAL void egl_start    (    EGL_SOFTC * 	egl    )    {#ifdef EGL_DEBUG    int unit = egl->egl_if.if_unit;#endif#endif    volatile SHIO *shio = egl->eglAddr;    volatile IOPB *iopb;    volatile CQE *cqe;    u_char *bufStart;    struct mbuf *m;    struct ether_header *eh;    ETH_BUF *eth_buf;    int len;    int index;    int s;    if (TXFULL(egl->egl_txcnt + egl->egl_quecnt))        {#ifdef EGL_DEBUG        logMsg ("egl%d: egl_start - packet queue full\n", unit, 0, 0, 0, 0, 0);#endif  /* EGL_DEBUG */        return; /* packet queue is full, can't send anything */        }    s = splimp ();    IF_DEQUEUE(&egl->egl_if.if_snd, m);    if (m == 0)        {        splx (s);        return;        }    TXINC(egl->egl_txadd);    egl->egl_txcnt++;    index = egl->egl_txadd;    iopb  = (IOPB *)&shio->sh_IOPB[EGL_TX_IOPBF + index];    GET_ETH_BUF(eth_buf);    bufStart = &eth_buf->eth_dat[0];    copy_from_mbufs (bufStart, m, len);    /* call output hook if any */    if ((etherOutputHookRtn != NULL) &&        (* etherOutputHookRtn) (&egl->egl_if, bufStart, len))        {        REL_ETH_BUF(eth_buf);        splx (s);        return;                 /* output hook has processed this packet */        }    eh = (struct ether_header *)bufStart;    if ((len - SIZEOF_ETHERHEADER) < ETHERMIN)        len = ETHERMIN + SIZEOF_ETHERHEADER;    /* must be modulo 4 in order to use block mode transfers */    iopb->iopb_LENGTH = (len + 3) & ~0x3;    iopb->iopb_BUFF        = eth_buf->eth_dat_adr;    eth_buf->eth_len       = len;    egl->egl_tbinfo[index] = eth_buf;    egl_ioflush (eth_buf);    if (BLOCKMODE)        {        /* we can (try and) use block mode transfer,         * must be aligned on a long-word boundary         */        if (!(iopb->iopb_BUFF & 0x2))            iopb->iopb_TOPT = EGL_TOPT_BLK | DIR_WRITE;        else            iopb->iopb_TOPT = EGL_TOPT | DIR_WRITE; /* put back to non-block */        }    iopb->iopb_PTLF = eh->ether_type;    /*     * Following code performs an efficient copy of the Ethernet     * destination address when the src & dst are word aligned.     * This avoids a sequence of 6 one byte writes on the VMEbus.     */    if (((ULONG)eh->ether_dhost & 0x3) == 0)        {        *(int *)iopb->iopb_NODE       = *(int *)eh->ether_dhost;        *(short *)(iopb->iopb_NODE+4) = *(short *)(eh->ether_dhost+4);        }    else        {        bcopy ((char*)eh->ether_dhost, (char*)iopb->iopb_NODE,                sizeof(iopb->iopb_NODE));        }    bcopy ((char*)egl->egl_enaddr, (char*)eh->ether_shost,            sizeof(eh->ether_shost));    /* send */    if (egl->egl_txcnt == 0)        {#ifdef EGL_DEBUG        logMsg ("egl%d: egl_txcnt is null\n", unit, 0, 0, 0, 0, 0);#endif        splx (s);        return;                 /* this should never happen */        }    if (egl->egl_qfull != 0)        {        splx (s);        return;        }    cqe = egl->egl_cqe;    if (CQE_BUSY(cqe->cqe_QECR))        {        egl->egl_qfull++;       /* feed queue is full */        splx (s);        return;        }    TXINC(egl->egl_txrem);    egl->egl_txcnt--;    index = egl->egl_txrem;    cqe->cqe_CTAG = index;    cqe->cqe_IOPB_ADDR = (caddr_t)(&shio->sh_IOPB[EGL_TX_IOPBF] + index) -                         (caddr_t)shio;    cqe->cqe_WORK_QUEUE = EGL_XMTQN(0); /* TX work queue 0 */    CQE_GO(cqe->cqe_QECR);    egl->egl_quecnt++;    if (++egl->egl_cqe == &shio->sh_CQE[MAX_CQE])        egl->egl_cqe = (CQE *)&shio->sh_CQE[0];#ifndef BSD43_DRIVER    /* BSD 4.4 ether_output() doesn't bump statistic. */    egl->egl_if.if_opackets++;#endif    splx (s);    }/********************************************************************************* eglShow - display per unit Eagle driver info** RETURNS: 0 or -1 if unit not present.** NOMANUAL*/int eglShow    (    int unit,   /* interface unit */    BOOL zap    /* zero totals */    )    {    static char *e_message [] = {    "transmit attempts",    "   \"     DMA completions",    "   \"     LANCE interrupts",    "   \"     good",    "   \"     errors",    "   \"     dones",    "receive attempts",    "   \"    starvations",    "   \"    interrupts",    "   \"    good",    "   \"    errors",    "   \"    DMA completions",    "   \"    dones",    "Miscellaneous DMA interrupts",    "Total LANCE Interrupts",    "LANCE Inits",    "CSR0 Babble",    " \"   Collisions",    " \"   Misses",    " \"   Memory Errors"    };    int ix;    volatile SHIO *shio;    EGL_SOFTC *egl;    if (unit < 0 || unit >= NEGL || (egl = egl_softc [unit]) == NULL)        {#ifdef EGL_DEBUG        printf ("egl%d: no Eagle driver initialized for unit\n", unit);#endif        return (-1);        }    shio = egl->eglAddr;    printf ("egl%d: Firmware revision: ", unit);    for (ix = 0; ix < 3; ix++)        printf ("%c", shio->sh_CSTB.cstb_FREV [ix]);    printf ("  Release date: ");    for (ix = 0; ix < 8; ix++)        printf ("%c", shio->sh_CSTB.cstb_FDATE [ix]);    printf ("\n");    for (ix = 0; ix < NELEMENTS(e_message); ix++)        {        printf ("    %-30.30s  %4ld\n", e_message [ix],                shio->sh_CSB.csb_stat [ix] - egl->CSBstats.csb_stat [ix]);        if (zap)            egl->CSBstats.csb_stat [ix] = shio->sh_CSB.csb_stat [ix];        }    return (0);    }/********************************************************************************* egl_tint - Ethernet interface transmit (& error) interrupt*/LOCAL void egl_tint    (    int unit,    EGL_SOFTC *egl,    int index    )    {    ETH_BUF *eth_buf;    eth_buf = egl->egl_tbinfo[index];    egl_ioflush (eth_buf);              /* do we need on transmit? */    egl->egl_tbinfo[index] = NULL;    REL_ETH_BUF(eth_buf);    egl->egl_quecnt--;    egl->egl_qfull = 0;         /* at least one slot open now */#ifdef BSD43_DRIVER    egl_start (unit);#else    egl_start (egl);#endif    }/********************************************************************************* egl_wait -*/LOCAL int egl_wait    (    volatile CRB *crb    )    {    volatile USHORT *lcrsw = &crb->crb_CRSW;    int ix;    for (ix = 0; ix < 8000; ix++)        {        if (*lcrsw & M_CRSW_CRBV)            break;        DELAY(1000);        }    /* Check for the Command Response Block Valid bit.  Sometimes     * the Eagle turns on "Queue Mode Started" just before completing     * a command (don't know why, but has been observed).     */    if (*lcrsw & M_CRSW_CRBV)        {        /* Eagle has completed an operation? */        CRB_CLR_DONE(*lcrsw);   /* release Eagle */        }    if (ix == 0)        return (0x1000); /* indicate a timeout occurred */    return (*lcrsw);    }#if     FALSEvoid egl_delay (int x)    {    /* use with timexN() from shell for tuning */    DELAY(x);    }#endif  /* FALSE */

⌨️ 快捷键说明

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