?? esmcend.c
字號:
pBuf = (unsigned char *) pNode->pCluster; /* Fetch an mBlk */ pMblk = mBlkGet(pDev->endObj.pNetPool, M_DONTWAIT, MT_DATA); if (!pMblk) { DRV_LOG(DRV_DEBUG_RX, "%s%d: esmcHandleRcvInt: Out of M blocks!\n", (int) DEV_NAME, pDev->unit, 3, 4, 5, 6); /* Save the cluster node and reschedule ourselves */ oldLevel = intLock(); lstInsert(&pDev->busyClusters, NULL, (NODE *) pNode); intUnlock(oldLevel); netJobAdd((FUNCPTR) esmcHandleRcvInt, (int) pDev, 0, 0, 0, 0); goto exit; } /* Fetch a ClBlk */ pClBlk = netClBlkGet(pDev->endObj.pNetPool, M_DONTWAIT); if (!pClBlk) { DRV_LOG(DRV_DEBUG_RX, "%s%d: esmcHandleRcvInt: Out of CL blocks!\n", (int) DEV_NAME, pDev->unit, 3, 4, 5, 6); /* Free the Mblk */ netMblkFree(pDev->endObj.pNetPool, (M_BLK_ID) pMblk); /* Save the cluster node and reschedule ourselves */ oldLevel = intLock(); lstInsert(&pDev->busyClusters, NULL, (NODE *) pNode); intUnlock(oldLevel); netJobAdd((FUNCPTR) esmcHandleRcvInt, (int) pDev, 0, 0, 0, 0); goto exit; } /* Join ClBlk to cluster */ netClBlkJoin(pClBlk, pBuf, ESMC_BUFSIZ, NULL, 0, 0, 0); /* Join the mBlk and ClBlk */ netMblkClJoin(pMblk, pClBlk); /* Complete the mBlk header */ pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mLen = pNode->length; pMblk->mBlkPktHdr.len = pMblk->mBlkHdr.mLen; pMblk->mBlkHdr.mData += pDev->offset; /* Bump input packet counter */ END_ERR_ADD(&pDev->endObj, MIB2_IN_UCAST, +1); /* Send up to protocol */ END_RCV_RTN_CALL(&pDev->endObj, pMblk); /* Fetch another cluster to replace the one just loaned */ while ((pNode->pCluster = netClusterGet(pDev->endObj.pNetPool, pDev->clPoolId)) == NULL) { DRV_LOG(DRV_DEBUG_RX, "Could not reallocate cluster; retrying\n", 1, 2, 3, 4, 5, 6); taskDelay(1); } /* Place cluster node back into free list */ oldLevel = intLock(); lstAdd(&pDev->freeClusters, (NODE *) pNode); intUnlock(oldLevel); } oldLevel = intLock(); pDev->flags &= ~ESMC_RCV_HANDLING_FLAG; intUnlock(oldLevel); return;exit: /* Bump the error counter */ END_ERR_ADD(&pDev->endObj, MIB2_IN_ERRS, +1); oldLevel = intLock(); pDev->flags &= ~ESMC_RCV_HANDLING_FLAG; intUnlock(oldLevel); return;#else oldLevel = intLock(); ESMC_SWITCH_BANK (pDev, 2); WRITE_WORD(pDev,ESMC_INTERRUPT_, 0); /* mask all interrupts */ intUnlock(oldLevel); while (!((packetNo = READ_WORD(pDev,ESMC_FIFO)) & ESMC_FIFO_REMPTY)) { ESMC_SWITCH_BANK (pDev, 2); WRITE_WORD (pDev,ESMC_PTR, ESMC_PTR_READ | ESMC_PTR_RCV | ESMC_PTR_AUTOINC); ldata = sysInLong(pDev->base + ESMC_DATA_1); statusRx = ldata & 0x0000FFFF; len = (ldata >> 16) & 0x0000FFFF; DRV_LOG (DRV_DEBUG_RX, "%s%d: esmcHandleRcvInt: statusRx = 0x%0x len = 0x%0x\n", (int) DEV_NAME, pDev->unit, statusRx, len, 0, 0); /* check for receive errors */ if (statusRx & ESMC_RS_ERROR_MASK) { /* increment appropriate error counter */ if(statusRx & ESMC_RS_ALGNERR) pDev->alignErr++; if(statusRx & ESMC_RS_BADCRC) pDev->badCrc++; if(statusRx & ESMC_RS_TOOLONG) pDev->tooLong++; if(statusRx & ESMC_RS_TOOSHORT) pDev->tooShort++; do { val = READ_WORD(pDev, ESMC_MMU); } while (val & ESMC_MMU_BUSY); WRITE_WORD(pDev, ESMC_MMU, ESMC_MMU_RX_RELEASE); /* release */ } else { pBuf = netClusterGet (pDev->endObj.pNetPool, pDev->clPoolId); if (!pBuf) { DRV_LOG (DRV_DEBUG_RX, "%s%d: esmcHandleRcvInt: Out of clusters!\n", (int) DEV_NAME, pDev->unit, 0, 0, 0, 0); /* re-schedule ourselves */ netJobAdd((FUNCPTR) esmcHandleRcvInt,(int) pDev, 0, 0, 0, 0); goto exit; } pMblk = mBlkGet (pDev->endObj.pNetPool, M_DONTWAIT, MT_DATA); if (!pMblk) { netClFree (pDev->endObj.pNetPool, (UCHAR *) pBuf); DRV_LOG (DRV_DEBUG_RX, "%s%d: esmcHandleRcvInt: Out of M blocks!\n", (int) DEV_NAME, pDev->unit, 0, 0, 0, 0); /* re-schedule ourselves */ netJobAdd((FUNCPTR) esmcHandleRcvInt,(int) pDev, 0, 0, 0, 0); goto exit; } pClBlk = netClBlkGet (pDev->endObj.pNetPool, M_DONTWAIT); if (!pClBlk) { netMblkFree (pDev->endObj.pNetPool, (M_BLK_ID)pMblk); netClFree (pDev->endObj.pNetPool, (UCHAR *) pBuf); DRV_LOG (DRV_DEBUG_RX, "%s%d: esmcHandleRcvInt: Out of CL blocks!\n", (int) DEV_NAME, pDev->unit, 0, 0, 0, 0); /* re-schedule ourselves */ netJobAdd((FUNCPTR) esmcHandleRcvInt,(int) pDev, 0, 0, 0, 0); goto exit; } /* Associate the data pointer with the MBLK */ netClBlkJoin (pClBlk, pBuf, ESMC_BUFSIZ, NULL, 0, 0, 0); /* Associate the data pointer with the MBLK */ netMblkClJoin (pMblk, pClBlk); /* finally - read in the packet */ pCur = (unsigned short *) (pBuf + pDev->offset); /* adjust len for first 4 bytes read */ len -=4; for(i = 0 ; i < (len >> 1) ; i++) { ldata = sysInLong(pDev->base + ESMC_DATA_1); val = ldata & 0x0000FFFF; pCur[i++] = SWAP_BYTES_IF_NECESSARY(val); val = (ldata >> 16) & 0x0000FFFF; pCur[i] = SWAP_BYTES_IF_NECESSARY(val); } /* adjust length for control byte and odd byte */ if (statusRx & ESMC_RS_ODDFRM) len -= 1; else len -= 2; do { val = READ_WORD(pDev, ESMC_MMU); } while (val & ESMC_MMU_BUSY); WRITE_WORD(pDev,ESMC_MMU, ESMC_MMU_RX_RELEASE); /* release */ pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mLen = len; pMblk->mBlkPktHdr.len = len; pMblk->mBlkHdr.mData += pDev->offset; /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL (&pDev->endObj, pMblk); /* Record received packet */ END_ERR_ADD (&pDev->endObj, MIB2_IN_UCAST, +1); } } /* re-enable receive interrupt */ oldLevel = intLock(); pDev->flags &= ~ESMC_RCV_HANDLING_FLAG; pDev->imask |= (ESMC_INT_RCV << 8); intUnlock(oldLevel);exit: oldLevel = intLock(); WRITE_WORD(pDev, ESMC_INTERRUPT_, pDev->imask); intUnlock(oldLevel); DRV_LOG (DRV_DEBUG_RX, "%s%d: esmcHandleRcvInt: imask = %0x\n", (int) DEV_NAME, pDev->unit, pDev->imask, 0,0,0); return;#endif /* ESMC_USE_ISR_COPY */ }#ifdef ESMC_USE_ISR_COPY/******************************************************************************** esmcIsrCopy - copy received frames from FIFO to preallocated clusters** This routine is called by the ISR to copy received frames from the FIFO* to preallocated clusters. This should free FIFO frames more quickly,* but will increase interrupt latency. The ESMC device register bank is* assumed to be set to 2 on entry.** RETURNS: N/A.*/LOCAL void esmcIsrCopy( ESMC_DEVICE *pDev){ unsigned short packetNo = 0; unsigned long ldata; unsigned short val; int length; unsigned short statusRx; CLUSTER_NODE *pNode; BOOL released; unsigned short *pCur; int i; /* Read packet number from RX fifo */ while (!((packetNo = READ_WORD(pDev, ESMC_FIFO)) & ESMC_FIFO_REMPTY)) { /* Obtain a free preallocated cluster */ released = FALSE; if ((pNode = (CLUSTER_NODE *) lstGet(&pDev->freeClusters)) != NULL) { /* Program the MMU to read the frame */ WRITE_WORD(pDev, ESMC_PTR, ESMC_PTR_READ | ESMC_PTR_RCV | ESMC_PTR_AUTOINC); /* Read packet status and length */ ldata = sysInLong(pDev->base + ESMC_DATA_1); statusRx = ldata & 0x0000FFFF; length = (ldata >> 16) & 0x0000FFFF; DRV_LOG (DRV_DEBUG_FN_TRACE, "YK:%s%d: esmcIsrCopy statusRx 0x%x length %d\n",(int) DEV_NAME, pDev->unit,statusRx, length, 5, 6); /* If no error indicated, fetch the packet */ if (statusRx & ESMC_RS_ERROR_MASK) { /* Increment appropriate error counters */ if (statusRx & ESMC_RS_ALGNERR) pDev->alignErr++; if (statusRx & ESMC_RS_BADCRC) pDev->badCrc++; if (statusRx & ESMC_RS_TOOLONG) pDev->tooLong++; if (statusRx & ESMC_RS_TOOSHORT) pDev->tooShort++; END_ERR_ADD(&pDev->endObj, MIB2_IN_ERRS, +1); /* Add the node back to the free list */ lstAdd(&pDev->freeClusters, (NODE *) pNode); } else { /* Point to cluster */ pCur = (unsigned short *) ((char *) pNode->pCluster + pDev->offset); /* Adjust length for bytes already read */ length -= 4; /* Copy the data from FIFO to cluster */ for (i = 0 ; i < (length >> 1) ; i++) { ldata = sysInLong(pDev->base + ESMC_DATA_1); val = ldata & 0x0000FFFF; pCur[i++] = SWAP_BYTES_IF_NECESSARY(val); val = (ldata >> 16) & 0x0000FFFF; pCur[i] = SWAP_BYTES_IF_NECESSARY(val); } /* Adjust length for control byte and odd byte */ if (statusRx & ESMC_RS_ODDFRM) length -= 1; else length -= 2; /* Wait until MMU is free */ do { val = READ_WORD(pDev, ESMC_MMU); } while (val & ESMC_MMU_BUSY); /* Release the memory associated with the packet ASAP */ WRITE_WORD(pDev, ESMC_MMU, ESMC_MMU_RX_RELEASE); released = TRUE; /* Complete the cluster node and queue it to the busy list */ pNode->length = length; pNode->packetNo = packetNo; pNode->statusRx = statusRx; lstAdd(&pDev->busyClusters, (NODE *) pNode); } } else { /* Bump the error counter */ END_ERR_ADD(&pDev->endObj, MIB2_IN_ERRS, +1); } if (!released) { /* Wait until MMU is free */ do { val = READ_WORD(pDev, ESMC_MMU); } while (val & ESMC_MMU_BUSY); /* Release the memory associated with the packet */ WRITE_WORD(pDev, ESMC_MMU, ESMC_MMU_RX_RELEASE); } }}#endif /* ESMC_USE_ISR_COPY *//******************************************************************************** esmcIsr - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A.*/LOCAL void esmcIsr( ESMC_DEVICE *pDev){ unsigned short bank; unsigned short savedPointer; unsigned short savedPacket; unsigned short val; unsigned char status; bank = READ_WORD(pDev,ESMC_BANK_SELECT); /* save bank */ if((bank & 0x03) != 2) ESMC_SWITCH_BANK (pDev,2); val = READ_WORD(pDev, ESMC_INTERRUPT_); DRV_ASSERT(((val & 0xff00) & ~pDev->imask) == 0); WRITE_WORD(pDev,ESMC_INTERRUPT_, 0); /* mask all interrupts */ DRV_ASSERT((READ_WORD(pDev,ESMC_BANK_SELECT) & 0x03) == 2); DRV_LOG (DRV_DEBUG_FN_TRACE, "%s%d: esmcIsr status=%x\n", (int) DEV_NAME, pDev->unit, val, 4, 5, 6); status = LO_BYTE(val) & HI_BYTE(val); if(status == 0) goto exit; if (status & (ESMC_INT_RCV | ESMC_INT_RX_OVRN)) /* RX done */ {#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); /* failed netJobAdd causes panic */ goto exit; } else { pDev->flags |= ESMC_RCV_HANDLING_FLAG;#ifndef ESMC_USE_ISR_COPY pDev->imask &= ~(ESMC_INT_RCV << 8); /* disable further receive interrupts */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -