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

📄 if_eex.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        }    }/********************************************************************************* eexCommand - deliver a command to the 82586 via SCB** This function causes the device to execute a command. It should be called* with interrupts from the device disabled. An error status is returned if* the command field does not return to zero, from a previous command, in a* reasonable amount of time.*/static STATUS eexCommand    (    DRV_CTRL *pDrvCtrl,    UINT16    cmd    )    {    int loopy;    for (loopy = 0x8000; loopy--;)        {        /* wait for cmd zero */        if (sysInWord (pDrvCtrl->port + SCB_COMMAND) == 0)            break;        }    if (loopy > 0)        {        /* fill in command */        sysOutWord (pDrvCtrl->port + SCB_COMMAND, cmd);        eex586ChanAtn (pDrvCtrl);    /* channel attention */        return (OK);        }    else        {        logMsg("eex driver: command field frozen\n", 0, 0, 0, 0, 0, 0);        return (ERROR);        }    }/********************************************************************************* eexTxQPut - place a transmit frame on the transmit queue** The TFD has been filled in with the network pertinent data. This* routine will enqueue the TFD for transmission and attempt to feed* the queue to the device.*/static void eexTxQPut    (    DRV_CTRL *pDrvCtrl,    EEX_SHORTLINK tfdOffset    )    {    int unit;    unit = pDrvCtrl->idr.ac_if.if_unit;    eex586IntDisable (pDrvCtrl->idr.ac_if.if_unit);  /* disable dev ints */    if (pDrvCtrl->txQueue.head != NULL)        {        /* Clear EL bit on previous tail frame */        sysOutWord (pDrvCtrl->port + WRPTR,                    pDrvCtrl->txQueue.tail + TF_COMMAND);        sysOutWord (pDrvCtrl->port + DXREG, CFD_C_XMIT);        }            /* enqueue the TFD */    eexQPut (pDrvCtrl, (EEX_LIST *)&pDrvCtrl->txQueue, tfdOffset);    sysOutWord (pDrvCtrl->port + WRPTR, pDrvCtrl->txQueue.tail + TF_COMMAND);    sysOutWord (pDrvCtrl->port + DXREG, CFD_C_XMIT | CFD_C_EL);    if (pDrvCtrl->txIdle)                             /* transmitter idle */        eexTxQFlush (pDrvCtrl);                        /* flush txQueue */    eex586IntEnable (pDrvCtrl->idr.ac_if.if_unit);  /* enable dev ints */    }/********************************************************************************* eexTxQFlush - make cmd unit of device start processing cmds** This routine flushes the contents of the txQ to the cblQ and starts the* device transmitting the cblQ. Called only if transmit queue is not empty.* Sometimes called from interrupt handler.*/static void eexTxQFlush    (    DRV_CTRL *pDrvCtrl    )    {    extern int sysClkRateGet();     /* we call this */    pDrvCtrl->cblQueue.head = pDrvCtrl->txQueue.head;   /* remember cbl head */    pDrvCtrl->cblQueue.tail = pDrvCtrl->txQueue.tail;   /* remember cbl tail */    eexQInit ( (EEX_LIST *)&pDrvCtrl->txQueue);         /* tx queue now empty */    sysOutWord(pDrvCtrl->port + SCB_CBL, pDrvCtrl->cblQueue.head);    pDrvCtrl->txIdle = FALSE;                   /* transmitter busy */    /* start watchdog */    wdStart (            pDrvCtrl->wid,            (int) (sysClkRateGet() >> 1),            (FUNCPTR) eexWatchDog,            pDrvCtrl->idr.ac_if.if_unit            );    /* start command unit */    eexCommand (pDrvCtrl, SCB_C_CUSTART);    }/********************************************************************************* eexRxQPut - return a RFD to the receive queue for use by the device*/static void eexRxQPut    (    DRV_CTRL *pDrvCtrl,    EEX_SHORTLINK rfdOffset    )    {    EEX_SHORTLINK rxTail;    UINT16 status;    EEX_SHORTLINK rbdOffset;    /* dhe 10/24/94 */    sysOutWord (pDrvCtrl->port + WRPTR, rfdOffset);    sysOutWord (pDrvCtrl->port + DXREG, 0);     /* clear status */    sysOutWord (pDrvCtrl->port + DXREG, CFD_C_EL); /* new end of list */    /* dhe 10/24/94 get the buffer pointer */    sysOutWord(pDrvCtrl->port + RDPTR, rfdOffset + RB_OFFSET);    rbdOffset = sysInWord(pDrvCtrl->port + DXREG);    /* dhe 10/24/94 TEST TEST zero the actual count of the buffer */    sysOutWord(pDrvCtrl->port + WRPTR, rbdOffset);    sysOutWord(pDrvCtrl->port + DXREG, 0);    rxTail = pDrvCtrl->rxQueue.tail;         /* remember tail */    /* Put the RFD on the list */    eexQPut (pDrvCtrl, (EEX_LIST *) & pDrvCtrl->rxQueue, rfdOffset);    if (rxTail != NULL)        {        sysOutWord (pDrvCtrl->port + WRPTR, rxTail + RF_COMMAND);        sysOutWord (pDrvCtrl->port + DXREG, 0); /* clear old tail EL */        sysOutWord (pDrvCtrl->port + RDPTR, rxTail);        status = sysInWord (pDrvCtrl->port + DXREG);        if (status & (CFD_S_COMPLETE | CFD_S_BUSY))            {            pDrvCtrl->freeRfd = rfdOffset;       /* link questionable */            }        else if (!(sysInWord (pDrvCtrl->port + SCB_STATUS) & SCB_S_RUREADY))            /* receiver dormant */            {            eexRxStartup (pDrvCtrl);             /* start receive unit */            }        }    else        {        pDrvCtrl->freeRfd = rfdOffset;           /* first free RFD */        }    }/********************************************************************************* eexRxQGet - get a successfully received frame from the receive queue** RETURNS: ptr to valid RFD, or NULL if none available*/static EEX_SHORTLINK eexRxQGet    (    DRV_CTRL *pDrvCtrl    )    {    EEX_SHORTLINK rfdOffset = NULL;    if (eexRxQFull (pDrvCtrl))        rfdOffset = eexQGet (pDrvCtrl, (EEX_LIST *)&pDrvCtrl->rxQueue);    return (rfdOffset);    }/********************************************************************************* eexRxQFull - boolean function to determine fullness of receive queue** RETURNS: TRUE if completely received frame is available, FALSE otherwise.*/static BOOL eexRxQFull    (    DRV_CTRL *pDrvCtrl    )    {    return (        (pDrvCtrl->rxQueue.head != NULL) &&        (        sysOutWord (pDrvCtrl->port + RDPTR, pDrvCtrl->rxQueue.head),        sysInWord (pDrvCtrl->port + DXREG) & CFD_S_COMPLETE        )        );    }/********************************************************************************* eexQInit - initialize a singly linked node queue*/static void eexQInit    (    EEX_LIST *pQueue    )    {    pQueue->head = pQueue->tail = NULL;         /* init head & tail */    }/********************************************************************************* eexQGet - get a node from the head of a node queue** RETURNS: ptr to useable node, or NULL ptr if none available* Since we never alter links, we are taking the last node when head==tail.*/static EEX_SHORTLINK eexQGet    (    DRV_CTRL *pDrvCtrl,    EEX_LIST *pQueue    )    {    EEX_SHORTLINK pNode;    if ( (pNode = (EEX_SHORTLINK) pQueue->head) != NULL) /* if list not empty */        {        if (pQueue->head == pQueue->tail)            pQueue->head =                              /* list now empty */            pQueue->tail = NULL;        else            pQueue->head = SUCC_FD (pNode);             /* advance ptr */        }    return (pNode);    }/********************************************************************************* eexQPut - put a node on the tail of a node queue*/static void eexQPut    (    DRV_CTRL *pDrvCtrl,    EEX_LIST *pQueue,    EEX_SHORTLINK pNode    )    {    /* assert (SUCC_FD (pQueue->tail) == pNode); */    if (pQueue->head == NULL)                   /* if list empty */        pQueue->head = pNode;                   /* new element is head */    pQueue->tail = pNode;                       /* update tail ptr */    }/********************************************************************************* eexWatchDog - if the watchdog timer fired off, we've hung during a transmit** Check the scb command to verify and if so, reinit.*/static void eexWatchDog    (    int unit        /* unit number */    )    {    DRV_CTRL *pDrvCtrl;    pDrvCtrl = & drvCtrl [unit];    /* sanity check.     * If the scb status indicates that CU (transmit) is active     * It might make sense to loop through the cfd's to look for     * a complete bit as a sanity check , but given that we are     * here and that transmit was active, we will go ahead and do     * a reset.     */    if (sysInWord (pDrvCtrl->port + SCB_STATUS) & SCB_S_CUACTIVE)        {        pDrvCtrl->transLocks++;                     /* local failure count */        pDrvCtrl->idr.ac_if.if_oerrors++;           /* incr err count */        pDrvCtrl->idr.ac_if.if_opackets--;          /* decr sent count */        DUMMY(unit);        }    }/********************************************************************************* eex586Init - Initialize board features** Does pretty much everything to initialize the 82586 and its memory* structures, either in this routine or in called routines.*/static STATUS eex586Init    (    int unit    )    {    DRV_CTRL *pDrvCtrl;    int ix;    int port;    EEX_SHORTLINK currentFd;    /**** dhe 10/26/94 moved to global for reassigning during restart    EEX_SHORTLINK lastFd;    ****/    int connValue;    pDrvCtrl = & drvCtrl [unit];    port = pDrvCtrl->port;    eex586IntDisable (unit);            /* disable device interrupts */    /* extract setup information from the board's EEPROM */    /* Remember that readEEPROM() sets the 82586 reset condition. */    pDrvCtrl->setup = eexReadEEPROM (pDrvCtrl, EEX_EEPROM_SETUP);    pDrvCtrl->tpeBit = eexReadEEPROM (pDrvCtrl, EEX_EEPROM_TPE_BIT);    pDrvCtrl->memSetup.wordView.memPage =                eexReadEEPROM (pDrvCtrl, EEX_EEPROM_MEMPAGE);    pDrvCtrl->memSetup.wordView.memDecode =                eexReadEEPROM (pDrvCtrl, EEX_EEPROM_MEMDECODE);    if (pDrvCtrl->attachment == ATTACHMENT_DEFAULT)        if ( (pDrvCtrl->memSetup.wordView.memPage & MEMPAGE_AUTODETECT) != 0)            {            /* Here we would figure out which connector is in use;             * "auto-detect" relies on software to do the actual detection.             */            }        else            {            if ( (pDrvCtrl->setup & SETUP_BNC) == 0)                pDrvCtrl->attachment = ATTACHMENT_AUI;            else if ( (pDrvCtrl->tpeBit & TPE_BIT) == 0)                pDrvCtrl->attachment = ATTACHMENT_BNC;            else                pDrvCtrl->attachment = ATTACHMENT_RJ45;            }    /* Tell the board hardware which connector we're using */    connValue = sysInByte (port + ECR1) & ~(CONN_INTEGRITY | CONN_TRANSCEIVER);    switch (pDrvCtrl->attachment)        {        case ATTACHMENT_AUI:            break;        case ATTACHMENT_BNC:            connValue |= CONN_TRANSCEIVER;            break;        case ATTACHMENT_RJ45:            connValue |= CONN_TRANSCEIVER | CONN_INTEGRITY;            break;        }    /* 17jan95  jag     * Only send the connector selection command if the board is     * NOT in "auto-detect" mode.  (If the board is in     * "auto-detect" mode, another command might disrupt the     * auto-detected mode).     */    if ( (pDrvCtrl->memSetup.wordView.memPage & MEMPAGE_AUTODETECT) == 0)        sysOutByte (port + ECR1, connValue);    /* get our enet addr */    if (eexEnetAddrGet (pDrvCtrl, (char *)pDrvCtrl->idr.ac_enaddr) == ERROR)        {        errnoSet (S_iosLib_INVALID_ETHERNET_ADDRESS);        return (ERROR);        }    /* Connect the interrupt handler */

⌨️ 快捷键说明

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