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

📄 if_elt.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
** eltBoardInit - prepare the board for operation**/static void eltBoardInit    (    int unit    )    {    ELT_CTRL * pDrvCtrl;    int port;    int index;    UINT16 transceiver;    pDrvCtrl = pEltCtrl [unit];    port = pDrvCtrl->port;    eltIntDisable (pDrvCtrl);   /* make it OK to change register window */    sysOutWord (port + ELT_COMMAND, SELECT_WINDOW | WIN_ADDRESS);    for (index = 0; index < EA_SIZE; index++)        sysOutByte (port + index, pDrvCtrl->idr.ac_enaddr [index]);    /* Select the transceiver hardware (attachment) then do whatever is     * necessary to activate the selected attachment.     * A truly complete implementation would probably check to see     * if the selected attachment were present.     */    sysOutWord (port + ELT_COMMAND, SELECT_WINDOW | WIN_CONFIG);    transceiver = sysInWord (port + ADDRESS_CONFIG);    if (pDrvCtrl->attachment == ATTACHMENT_DEFAULT)        {        switch (transceiver & AC_XCVR_MASK)            {            case AC_XCVR_TPE:                pDrvCtrl->attachment = ATTACHMENT_RJ45;                break;            case AC_XCVR_BNC:                pDrvCtrl->attachment = ATTACHMENT_BNC;                break;            case AC_XCVR_AUI:                pDrvCtrl->attachment = ATTACHMENT_AUI;                break;            default:    /* there's only one other value; it's "reserved" */                pDrvCtrl->attachment = ATTACHMENT_AUI;  /* good enough */                break;            }        }    /* Now set the selected attachment type, even if it was already selected */    transceiver &= ~AC_XCVR_MASK;    switch (pDrvCtrl->attachment)        {        case ATTACHMENT_RJ45:            sysOutWord (port + ADDRESS_CONFIG, transceiver | AC_XCVR_TPE);            sysOutWord (port + ELT_COMMAND, SELECT_WINDOW | WIN_DIAGNOSTIC);            sysOutByte (port + MEDIA_STATUS,                        sysInByte (port + MEDIA_STATUS) |                        MT_S_JABBER_ENABLE | MT_S_LINK_BEAT_ENABLE);            break;        case ATTACHMENT_BNC:            sysOutWord (port + ADDRESS_CONFIG, transceiver | AC_XCVR_BNC);            sysOutWord (port + ELT_COMMAND, START_COAX);            break;        case ATTACHMENT_AUI:        default:            sysOutWord (port + ADDRESS_CONFIG, transceiver | AC_XCVR_AUI);            break;        }    /* enable normal Ethernet address recognition */    pDrvCtrl->rxFilter = RX_F_NORMAL;    /*     * Define the set of status bits that could cause interrupts.     * There is no interrupt cause indicator separate from the board status.     * To keep the ISR from seeing status conditions we didn't want to be     * interrrupted for, we must mask the STATUS off, not the interrupt.     * This prevents the condition from interrupting and also prevents     * the ISR from seeing the condition even if it is true.     * The interrupt mask is set only once to the set of all conditions     * we might want to be interrupted by; the status mask is set and     * cleared according to which conditions we want at any particular     * time.  The intMask field in the control structure     * is named for its effect; it is really used in the status mask     * command (3Com calls it the read zero mask).     */    /* enable the status bits we currently want to cause interrupts */    eltIntMaskSet (pDrvCtrl, ADAPTER_FAILURE | TX_COMPLETE |                             RX_COMPLETE | RX_EARLY | UPDATE_STATS);    /* enable the collection of statistics */    sysOutWord (port + ELT_COMMAND, STATS_ENABLE);    /* enable the hardware to generate interrupt requests */    sysOutWord (port + ELT_COMMAND, SELECT_WINDOW | WIN_CONFIG);    sysOutWord (port + CONFIG_CONTROL, CC_ENABLE);    sysOutWord (port + ELT_COMMAND, SELECT_WINDOW | WIN_OPERATING);    eltIntEnable (pDrvCtrl);    eltRxStart (pDrvCtrl);    eltTxStart (pDrvCtrl);    }/********************************************************************************* eltMemoryInit - initialize memory structures** The only thing we allocate from system meory besides the driver control* structure is the frame buffer pool.  Here we malloc it as one big region* and divide it up into receive and transmit buffers.*/static STATUS eltMemoryInit    (    int unit    )    {    ELT_CTRL * pDrvCtrl;    ELT_FRAME * pFrame;    int         index;    pDrvCtrl = pEltCtrl [unit];    /* Initialize our data structures */    pDrvCtrl->pFrameArea = malloc ( (1 + pDrvCtrl->nRxFrames)                                    * sizeof (ELT_FRAME));    if (pDrvCtrl->pFrameArea == NULL)        return (ERROR);    pFrame = pDrvCtrl->pFrameArea;    pDrvCtrl->pTxFrame = pFrame++;              /* first allocate tx frame */    pDrvCtrl->pRxHead = pFrame;                 /* first rx frame */    for (index = pDrvCtrl->nRxFrames; index > 0; index--)        {        pFrame->count = 0;        pFrame->nextByte = pFrame->header;        pFrame->length = 0;        pFrame->lNext = pFrame + 1;        pFrame++;        }    pDrvCtrl->pRxTail = pFrame - 1;             /* last rx frame */    pDrvCtrl->pRxTail->lNext = NULL;    pDrvCtrl->pRxCurrent = pDrvCtrl->pRxHead;    pDrvCtrl->nLoanFrames = pDrvCtrl->nRxFrames - MIN_NUM_RX_FRAMES;    return (OK);    }/********************************************************************************* eltReset - reset the elt interface** Mark interface as inactive and reset the adapter.*/static void eltReset    (    int unit    )    {    ELT_CTRL * pDrvCtrl;    pDrvCtrl = pEltCtrl [unit];    eltIntDisable (pDrvCtrl);           /* prevent device from interrupting */    sysOutWord (pDrvCtrl->port + ELT_COMMAND, RX_RESET);    sysOutWord (pDrvCtrl->port + ELT_COMMAND, TX_RESET);    }/********************************************************************************* eltIoctl - interface ioctl procedure** Process an interface ioctl request.*/static int eltIoctl    (    IDR     *pIDR,    int     cmd,    caddr_t data    )    {    int unit;    ELT_CTRL * pDrvCtrl;    int error;#ifdef ELT_DEBUG    printf ("elt: ioctl: pIDR=%x cmd=%x data=%x\n", pIDR, cmd, data);#endif /* ELT_DEBUG */    unit = pIDR->ac_if.if_unit;    pDrvCtrl = pEltCtrl [unit];    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 mode according to current interface flags */            pDrvCtrl->rxFilter = ( (pIDR->ac_if.if_flags & IFF_PROMISC) != 0) ?                                   RX_F_PROMISCUOUS : RX_F_NORMAL;            sysOutWord (pDrvCtrl->port + ELT_COMMAND,                        SET_RX_FILTER | pDrvCtrl->rxFilter);            break;        default:            error = EINVAL;        }    return (error);    }#ifdef BSD43_DRIVER/********************************************************************************* eltOutput - interface output routine.** This is the entry point for packets arriving from protocols above.  This* routine merely calls our specific output routines that eventually lead* to a transmit to the network.** RETURNS: 0 or appropriate errno*/static int eltOutput    (    IDR *    pIDR,    MBUF *     pMbuf,    SOCK * pDestAddr    )    {#ifdef ELT_DEBUG    printf ("elt: output: pIDR=%x pMbuf=%x pDestAddr=%x\n",            pIDR, pMbuf, pDestAddr);#endif /* ELT_DEBUG */    return (ether_output ( (IFNET *)pIDR, pMbuf, pDestAddr,            (FUNCPTR) eltTxOutputStart, pIDR));    }#endif/********************************************************************************* eltTxOutputStart - start output on the board** This routine is called from ether_output() when a new packet is enqueued* in the interface mbuf queue.** Note that this function is ALWAYS called between an splnet() and an splx().* This is true because netTask(), and ether_output() take care of* this when calling this function. Therefore, no calls to these spl functions* are needed anywhere in this output thread.*/#ifdef BSD43_DRIVERstatic void eltTxOutputStart    (    int unit    )    {    ELT_CTRL * pDrvCtrl;    pDrvCtrl = pEltCtrl [unit];#elsestatic void eltTxOutputStart    (    ELT_CTRL * pDrvCtrl    )    {#endif    if (sysInWord (pDrvCtrl->port + TX_FREE_BYTES) >= TX_IDLE_COUNT)        {#ifdef ELT_TIMING        /* pretend we queued eltTxFlush, to keep the counts straight */        if ( (int)++pDrvCtrl->eltStat.taskQTxOuts >             (int)pDrvCtrl->eltStat.maxTxTaskQ)            pDrvCtrl->eltStat.maxTxTaskQ = pDrvCtrl->eltStat.taskQTxOuts;#endif /* ELT_TIMING */        eltTxFlush (pDrvCtrl, FALSE);   /* not called via netJobAdd() */        }    }/********************************************************************************* eltInt - entry point for handling interrupts from the EtherLink III** Most of the board's interrupting conditions must be actually handled to* clear the interrupting condition; the ACK command does nothing for them.* Where we defer handling to the task level, we mask the status conditions* to prevent a repeated interrupt.  This works everywhere except when there* are received packets waiting to be delivered to the protocols; this is* synchronized by a flag.** Note that the board manual says to acknowledge the board interrupts before* acknowledging the processor interrupt, presumably because of level-sensitive* logic somewhere.*/static void eltInt    (    ELT_CTRL * pDrvCtrl    )    {    UINT16 status;    UINT16 statusDiag;    UINT16 statusRx;    UINT16 statusRxNew;    UINT8  statusTx;    UINT16 length;    int	   ix = 0;    int    port = pDrvCtrl->port;    BOOL   needTxStart = FALSE;    volatile ELT_FRAME * pFrame;    STATUS result;#ifdef ELT_TIMING    {        int time = (int) sysInByte (pDrvCtrl->port + TIMER);        if (time> pDrvCtrl->eltStat.maxIntLatency)            pDrvCtrl->eltStat.maxIntLatency = time;         if (pDrvCtrl->interruptTime == -1)            pDrvCtrl->interruptTime = time;        else if (pDrvCtrl->interruptTime >= 0)            pDrvCtrl->interruptTime = -1;    }#endif /* ELT_TIMING */    status = sysInByte (pDrvCtrl->port + ELT_STATUS) & 0x00ff;    if ( (status & INTERRUPT_LATCH) == 0)        {        ++pDrvCtrl->eltStat.strayint;        return;        }    else        ++pDrvCtrl->eltStat.interrupts;    /* Handle adapter failure first in case other conditions mask it */    if ( (status & ADAPTER_FAILURE) != 0)        {        sysOutWord (port + ELT_COMMAND, SELECT_WINDOW | WIN_DIAGNOSTIC);        statusDiag = sysInWord (port + FIFO_DIAGNOSTIC);        sysOutWord (port + ELT_COMMAND, SELECT_WINDOW | WIN_OPERATING);        if ( (statusDiag & FD_TX_OVERRUN) != 0)            {            ++pDrvCtrl->eltStat.txoverruns;            sysOutWord (port + ELT_COMMAND, TX_RESET);            eltTxStart (pDrvCtrl);            }        if ( (status & FD_RX_UNDERRUN) != 0)            {            ++pDrvCtrl->eltStat.rxunderruns;            sysOutWord (port + ELT_COMMAND, RX_RESET);            eltRxStart (pDrvCtrl);            }        }    /* Handle receive complete interrupt */    if ( (status & (RX_COMPLETE | RX_EARLY)) != 0)        {        if ( (status & RX_EARLY) != 0)            ++pDrvCtrl->eltStat.rxearly;        if (pDrvCtrl->pRxCurrent == NULL)            ++pDrvCtrl->eltStat.rxnobuffers;#ifdef ELT_TIMING        {        int timeNow;        int timeDelta;        if (pDrvCtrl->interruptTime >= 0)            {            timeNow = (int)sysInByte (port + TIMER);            if (timeNow == 0xff)                ++pDrvCtrl->eltStat.timerOverflow;            else                {                ++pDrvCtrl->eltStat.timerUpdates;                timeDelta = timeNow - pDrvCtrl->interruptTime;                if (timeDelta > pDrvCtrl->eltStat.maxRxLatency)                    pDrvCtrl->eltStat.maxRxLatency = timeDelta;                 if ( (pDrvCtrl->eltStat.minRxLatency == 0) ||                    (timeDelta < pDrvCtrl->eltStat.minRxLatency))                    pDrvCtrl->eltStat.minRxLatency = timeDelta;

⌨️ 快捷键说明

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