?? esmcend.c
字號:
#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 + -