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

📄 esmcend.c

📁 基于嵌入式操作系统VxWorks的lan91c111的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif /* !ESMC_USE_ISR_COPY */             }        }        if (status & ESMC_INT_RX_OVRN)        {            pDev->rxOverrun++;            /* acknowledge the interrupt */            WRITE_WORD(pDev,ESMC_INTERRUPT_, ESMC_INT_RX_OVRN);        }    }    if (status & ESMC_INT_ERCV) /* early receive */    {#ifdef ESMC_USE_ISR_COPY                    /* Copy and release all available received frames */                    esmcIsrCopy(pDev);            #endif /* ESMC_USE_ISR_COPY */        if(!(pDev->flags & ESMC_RCV_HANDLING_FLAG))        {            if (netJobAdd ((FUNCPTR) esmcHandleRcvInt,                    (int) pDev, 0, 0, 0, 0) == ERROR)            {                logMsg ("%s%d: failed to queue esmcHandleRcvInt\n",                        (int) DEV_NAME, pDev->unit, 3, 4, 5, 6);                /* disable further receive interrupts */                pDev->imask &= ~(ESMC_INT_RCV << 8);                  goto exit;             }             else             {                 pDev->flags |= ESMC_RCV_HANDLING_FLAG;#ifndef ESMC_USE_ISR_COPY                 /* disable further receive interrupts */                 pDev->imask &= ~(ESMC_INT_RCV << 8);  #endif /* !ESMC_USE_ISR_COPY */              }        }        /* acknowledge the interrupt */        WRITE_WORD(pDev,ESMC_INTERRUPT_, ESMC_INT_ERCV);    }    if (status & ESMC_INT_TX_EMPTY) /* transmit que empty */    {        /* could signal a semaphore here - or something */        /* disable further interrupts */        pDev->imask &= ~(ESMC_INT_TX_EMPTY << 8);        /* acknowledge the interrupt */        WRITE_WORD(pDev,ESMC_INTERRUPT_, ESMC_INT_TX_EMPTY);    }    if (status & ESMC_INT_TX) /* transmit complete */    {        /* save point and packet */        savedPointer = READ_WORD(pDev, ESMC_PTR);        savedPacket  = READ_WORD(pDev, ESMC_PNR) & 0x00ff;                 /* set pointer to tx  packet */        val = READ_WORD(pDev, ESMC_FIFO);        WRITE_WORD(pDev, ESMC_PNR, val);        WRITE_WORD(pDev,ESMC_PTR, ESMC_PTR_AUTOINC | ESMC_PTR_READ);        /* get status */        val = READ_WORD(pDev, ESMC_DATA_1);        /* check for fatal errors */        if(val & ESMC_TS_LATCOL)        {            pDev->lateCollisions++;        }        else if(val & ESMC_TS_16COL)        {            pDev->_16Collisions++;        }        else if(val & ESMC_TS_SQET)        {            pDev->sqet++;        }        else if(val & ESMC_TS_TXUNRN)        {            pDev->fifoTxUnderrun++;        }        else if(val & ESMC_TS_LOST_CARR)        {            pDev->lostCarrier++;        }        /* release packet */        WRITE_WORD(pDev, ESMC_MMU, ESMC_MMU_TX_RELEASE);        /* re-enable transmitter */        ESMC_SWITCH_BANK (pDev, 0);        val = READ_WORD(pDev, ESMC_TCR);        WRITE_WORD(pDev, ESMC_TCR, val | ESMC_TCR_TXEN);        ESMC_SWITCH_BANK (pDev,2);        /* restore pointers */        WRITE_WORD(pDev, ESMC_PTR, savedPointer);        WRITE_WORD(pDev, ESMC_PNR, savedPacket);        /* acknowledge the interrupt */        WRITE_WORD(pDev,ESMC_INTERRUPT_, ESMC_INT_TX);    }   exit:        /* do cleanup if necessary */    ON_EXIT_ISR(pDev);    /* restore mask and bank */    WRITE_WORD(pDev, ESMC_INTERRUPT_, pDev->imask);    ESMC_SWITCH_BANK (pDev,bank);    return;}/******************************************************************************** esmcStart - start the device** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR**/LOCAL STATUS esmcStart    (    END_OBJ *pObj        /* device ID */    )    {    STATUS result;    int    oldLevel;    ESMC_DEVICE * pDev = (ESMC_DEVICE *)pObj;        DRV_LOG (DRV_DEBUG_LOAD, "%s%d: esmcStart\n",         (int) DEV_NAME, pDev->unit, 3, 4, 5, 6);  #ifdef DEBUG_NET_TASK    /* turn off VX_UNBREAKABLE on net task */    {        int tid;        tid = taskNameToId("tNetTask");        if(tid != ERROR)        {            taskOptionsSet(tid, VX_UNBREAKABLE, 0);        }    }#endif        oldLevel = intLock();    SYS_INT_CONNECT (pDev, esmcIsr, (int)pDev, &result);    intUnlock(oldLevel);        if (result == ERROR)    {    DRV_LOG (DRV_DEBUG_LOAD,         "%s%d: esmcStart: could not attach interrupt\n",         (int) DEV_NAME, pDev->unit, 3, 4, 5, 6);    return (ERROR);    }    /* reset error counters */    pDev->rxOverrun = 0;    pDev->lateCollisions = 0;    pDev->_16Collisions = 0;    pDev->fifoTxUnderrun = 0;    pDev->sqet = 0;    pDev->lostCarrier = 0;    pDev->alignErr = 0;    pDev->badCrc = 0;    pDev->tooLong = 0;    pDev->tooShort = 0;    ESMC_SWITCH_BANK (pDev,0);    WRITE_WORD (pDev, ESMC_TCR, ESMC_TCR_PAD | ESMC_TCR_TXEN); /* TXenable */    WRITE_WORD (pDev, ESMC_RCR, ESMC_RCR_RXEN);                /* RX enable */    /* Enable interrupts on the chip:     *     * ERCV: (Early Receive Interrupt) set whenever a packet is beeing     *     received, and the number of bytes received into memory exeeds     *     the value programmed as ERCV_THRESHOLD.     * EPH: (Ethernet protocol Handler) is the result of the merge of     *     several possible conditions.     * RX_OVRN: The receiver aborts due to an overrun due to failed     *     memory allocation.     * TX_EMPTY: set if the TX FIFO goes empty, normally after a     *     succesful transmission.     * TX: set when at least one packet transmission was     *     completed. After servicing a packet in the FIFO the TX is set.     * RCV: set when a receive interrupt has been genetated, the first     *     packet received can be read from FIFO.     */    /* mark the interface as up and running */    END_FLAGS_SET (&pDev->endObj, (IFF_UP | IFF_RUNNING));         pDev->imask =  ( /*ESMC_INT_RX_OVRN | */ ESMC_INT_RCV |  /*ESMC_INT_ERCV | */ ESMC_INT_TX) << 8;        oldLevel = intLock();        ESMC_SWITCH_BANK (pDev,2);    /* int enable */    WRITE_WORD(pDev, ESMC_INTERRUPT_, pDev->imask);    SYS_INT_ENABLE(pDev);    intUnlock(oldLevel);    return (OK);    }/********************************************************************************* esmcStop - stop the device** This function calls BSP functions to disconnect interrupts and stop* the device from operating in interrupt mode.** RETURNS: OK or ERROR.*/LOCAL STATUS esmcStop    (    END_OBJ *pObj    /* device to be stopped */    )    {    ESMC_DEVICE *pDev = (ESMC_DEVICE *)pObj;    STATUS result = OK;    USHORT val;    DRV_LOG (DRV_DEBUG_LOAD, "%s%d: esmcStop\n",         (int) DEV_NAME, pDev->unit, 3, 4, 5, 6);    END_FLAGS_CLR (&pDev->endObj, IFF_UP | IFF_RUNNING);    /* stop/disable the device. */    ESMC_SWITCH_BANK (pDev, 2);    WRITE_WORD(pDev,ESMC_INTERRUPT_, 0);        /* mask all interrupts INT */    ESMC_SWITCH_BANK (pDev,0);    val = READ_WORD(pDev, ESMC_TCR);    WRITE_WORD (pDev, ESMC_TCR, val & ~ESMC_TCR_TXEN);  /* TX disable */    val = READ_WORD(pDev, ESMC_RCR);    WRITE_WORD (pDev, ESMC_RCR, val & ~ESMC_RCR_RXEN);  /* RX disable */    SYS_INT_DISCONNECT (pDev, (FUNCPTR)esmcIsr, (int)pDev, &result);    if (result == ERROR)    {    DRV_LOG (DRV_DEBUG_LOAD, "Could not disconnect interrupt!\n",        1, 2, 3, 4, 5, 6);    }    ESMC_SWITCH_BANK (pDev, 2);    return (result);    }/******************************************************************************** esmcUnload - unload a driver from the system** This function first brings down the device, and then frees any* stuff that was allocated by the driver in the load function.** RETURNS: OK or ERROR.*/LOCAL STATUS esmcUnload    (    END_OBJ *pObj    /* device to be unloaded */    )    {    ESMC_DEVICE *pDev = (ESMC_DEVICE *)pObj;    DRV_LOG (DRV_DEBUG_LOAD, "%s%d: esmcUnload\n",         (int) DEV_NAME, pDev->unit, 3, 4, 5, 6);    END_OBJECT_UNLOAD (&pDev->endObj);#ifdef ESMC_USE_ISR_COPY    /* Free preallocated resources */    while (lstCount(&pDev->busyClusters))        taskDelay(1);    lstFree(&pDev->freeClusters);    lstFree(&pDev->busyClusters);#endif /* ESMC_USE_ISR_COPY */                 netPoolDelete (pDev->endObj.pNetPool);    free(pDev->endObj.pNetPool);    pDev->endObj.pNetPool = NULL;    return OK;    }/********************************************************************************* esmcSend - the driver send routine** This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it.  This is done by a higher layer.  The last arguments are a free* routine to be called when the device is done with the buffer and a pointer* to the argument to pass to the free routine.** RETURNS: OK, ERROR, or END_ERR_BLOCK.*/LOCAL STATUS esmcSend    (    END_OBJ *pObj,    M_BLK_ID     pMblk        /* data to send */    )    {    unsigned int    pages;    unsigned short  packetNo;    unsigned short  val;       unsigned int    ndx;    unsigned int    len;     unsigned int    writeOut;    int             oldLevel;    unsigned int    i;    STATUS          erCode;    M_BLK_ID        pCur = pMblk;        ESMC_DEVICE *pDev = (ESMC_DEVICE *)pObj;    DRV_LOG (DRV_DEBUG_FN_TRACE, "%s%d: esmcSend\n",         (int) DEV_NAME, pDev->unit, 3, 4, 5, 6);    /*     * Obtain exclusive access to transmitter.  This is necessary because     * we might have more than one stack transmitting at once.     */       END_TX_SEM_TAKE (&pDev->endObj, WAIT_FOREVER);    /*     * Delay up to 5 ticks if free pages are exhausted, which is true     * all too often on the Mainstone.     */    ESMC_SWITCH_BANK(pDev, 0);    i = 0;    do     {        val = READ_WORD(pDev, ESMC_MIR);        val = (val >> 8) & 0xFF;        if (val == 0)        {            taskDelay(1);        }    } while ((val == 0) && (i++ < 5));        /* get length from mblks */    len = 0;    while(pCur != NULL)    {        len += pCur->mBlkHdr.mLen;        pCur = pCur->mBlkHdr.mNext;    }    /* allocate transmit memory */    pages = len / 256;    oldLevel = intLock();    ESMC_SWITCH_BANK (pDev, 2);    WRITE_WORD(pDev,ESMC_INTERRUPT_, 0);        /* lock INT */    intUnlock(oldLevel);    WRITE_WORD(pDev, ESMC_MMU, ESMC_MMU_ALLOC | pages);  /* alloc mem */    for(i = 0 ; i < 10 ; i++)    {            val = READ_WORD(pDev, ESMC_INTERRUPT_);        if(val &  ESMC_INT_ALLOC)            break;    }        /*     * If no buffers are available,     * release the semaphore and return END_ERR_BLOCK.     * Do not free packet     */    packetNo = READ_WORD(pDev, ESMC_PNR) >> 8;    if(packetNo & 0x80) /* check for valid packet number */    {        erCode = END_ERR_BLOCK;        goto exit;    }    sysOutByte(pDev->base + ESMC_PNR, packetNo);  /* set the tx packet */    WRITE_WORD(pDev, ESMC_PTR, ESMC_PTR_AUTOINC); /* set the pointer */    /* copy the data to the device */    WRITE_WORD(pDev, ESMC_DATA_1, 0);             /* status */    WRITE_WORD(pDev, ESMC_DATA_1, (len + 6));     /* byte count */    pCur = pMblk;    writeOut = 0;     val = 0;    while(pCur)    {        len = pCur->mBlkHdr.mLen;        for(ndx = 0 ; ndx < pCur->mBlkHdr.mLen; ndx++)        {            if(writeOut == 1)            {                writeOut = 0;                val |= ((unsigned char)(pCur->mBlkHdr.mData[ndx]) << 8);                WRITE_WORD(pDev,ESMC_DATA_1, val);            }            else            {                writeOut = 1;                val = (unsigned char )pCur->mBlkHdr.mData[ndx];            }        }        pCur = pCur->mBlkHdr.mNext;    }    /* check for odd number of bytes */    if(writeOut == 1)    {        /*         * For odd size frames, write the last data byte         * and the Control byte as 0x20 (ODD=1).         */        WRITE_WORD(pDev,ESMC_DATA_1, 0x2000 | val);    }    else    {        /*         * For even size frames, write the last data byte as zero

⌨️ 快捷键说明

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