📄 ibmemacend.c
字号:
else isrClear = EMAC_ISR_TX_INTS | EMAC_ISR_DB0; EMAC_REG_WRITE(pDrvCtrl, EMAC_ISR, isrClear); } /* * Check to see if there was a RX error. Clear the status bits for the * RX error. Keep count of these errors in the main device structure. * * Note that non-zero values of EMAC_ISR_RX_INTS are used primarily * for debugging. When EMAC_ISR_RX_INTS is zero, some compilers * may warn about an always-false conditional expression. */ if (isrReg & EMAC_ISR_RX_INTS) { pDrvCtrl->intErrorRX++; EMAC_REG_WRITE(pDrvCtrl, EMAC_ISR, EMAC_ISR_RX_INTS); } return; }/********************************************************************************* ibmEmacTxeobInt - handle controller TX end-of-buffer interrupt** This routine is called at interrupt level in response to an interrupt from* the MAL.*/LOCAL void ibmEmacTxeobInt ( EMAC_DRV_CTRL * pDrvCtrl ) { DRV_LOG (DRV_DEBUG_TX, "EMAC TX EOB int\n", 1, 2, 3, 4, 5, 6); /* Start the cleanup job */ if ((pDrvCtrl->localFlags & EMAC_TX_CLEAN_RUNNING) == 0) { if (netTaskId && netTaskId != ERROR) { pDrvCtrl->localFlags |= EMAC_TX_CLEAN_RUNNING; netJobAdd((FUNCPTR)ibmEmacSendCleanup, (int)pDrvCtrl, 0, 0, 0, 0); } else ibmEmacSendCleanup(pDrvCtrl); } if (pDrvCtrl->localFlags & EMAC_TX_BLOCKED) { DRV_LOG (DRV_DEBUG_ERROR, "TX blocked. Call muxRestart\n", 1 , 2, 3, 4, 5, 6); pDrvCtrl->localFlags &= ~EMAC_TX_BLOCKED; if (netTaskId && netTaskId != ERROR) netJobAdd((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->end, 0, 0, 0, 0); else muxTxRestart(&pDrvCtrl->end); } return; }/********************************************************************************* ibmEmacWdRestart - handle restart in case MUX blocks or driver fails** This routine is called at interrupt level (WatchDog) in case the MUX is blocked* or the hardware fails.*/LOCAL void ibmEmacWdRestart ( EMAC_DRV_CTRL * pDrvCtrl ){ DRV_LOG(DRV_DEBUG_ERROR, "INFO: RestartWatchdog kicks driver\n", 1, 2, 3, 4, 5, 6); /* Now that status from the packet just transmitted has been copied back * to the main TX ring, it is safe to allow another TX operation. */ /* semGive (pDrvCtrl->txSem2nd); */ /* Start the cleanup job */ if ((pDrvCtrl->localFlags & EMAC_TX_CLEAN_RUNNING) == 0) { pDrvCtrl->localFlags |= EMAC_TX_CLEAN_RUNNING; if ( netJobAdd((FUNCPTR)ibmEmacSendCleanup, (int)pDrvCtrl, 0, 0, 0, 0) == ERROR ) DRV_LOG (DRV_DEBUG_ERROR, "FATAL: netJobAdd ibmEmacSendCleanup failed\n",1,2,3,4,5,6); } /* check if TX is/was blocked, unblock it*/ if (pDrvCtrl->localFlags & EMAC_TX_BLOCKED) { DRV_LOG (DRV_DEBUG_ERROR, "INFO: Watchdog expired: MUX blocked, unblocking, calling muxRestart\n",1,2,3,4,5,6); pDrvCtrl->localFlags &= ~EMAC_TX_BLOCKED; if ( netJobAdd((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->end, 0, 0, 0, 0) == ERROR ) DRV_LOG (DRV_DEBUG_ERROR, "FATAL: netJobAdd muxTxRestart failed\n",1,2,3,4,5,6); } return;}/********************************************************************************* ibmEmacRxeobInt - handle controller RX end-of-buffer interrupt** This routine is called at interrupt level in response to an interrupt from* the MAL.*/LOCAL void ibmEmacRxeobInt ( EMAC_DRV_CTRL * pDrvCtrl ) { DRV_LOG (DRV_DEBUG_INT, "EMAC RX EOB int: 0x%x 0x%x\n", pDrvCtrl->indexRxD, (pDrvCtrl->pRxDesc + pDrvCtrl->indexRxD)->statusControl, 3, 4, 5, 6); /* * If tnetTask is running and not already handling received packets * for this interface, arrange to process the received packets at * task level. */ if (!(pDrvCtrl->localFlags & EMAC_HANDLE_RX_RUNNING)) { if (netTaskId && netTaskId != ERROR) { pDrvCtrl->localFlags |= EMAC_HANDLE_RX_RUNNING; netJobAdd((FUNCPTR)ibmEmacHandleRecvInt, (int)pDrvCtrl,FALSE,0,0,0); } else ibmEmacHandleRecvInt(pDrvCtrl, FALSE); } return; }/********************************************************************************* ibmEmacTxdeInt - handle TX descriptor error interrupt** This routine is called at interrupt level in response to an interrupt from* the MAL.*/LOCAL void ibmEmacTxdeInt ( EMAC_DRV_CTRL * pDrvCtrl ) { DRV_LOG (DRV_DEBUG_ERROR, "EMAC TX DE int\n", 1, 2, 3, 4, 5, 6); /* * The send routines check to be sure that enough TX descriptors are * available to send a packet, and initialize all descriptors required * to transmit the packet before kicking the transmitter. * This interrupt should never occur. If it does, restart. */ ibmEmacRestart(pDrvCtrl); return; }/********************************************************************************* ibmEmacRxdeInt - handle RX descriptor error interrupt** This routine is called at interrupt level in response to an interrupt from* the MAL.*/LOCAL void ibmEmacRxdeInt ( EMAC_DRV_CTRL * pDrvCtrl ) { DRV_LOG (DRV_DEBUG_ERROR, "EMAC RX DE int\n", 1, 2, 3, 4, 5, 6); /* * Start ibmEmacHandleRecvInt running (at task level if tnetTask * is available), and tell it to restart the RX channel when it is * finished because MAL automatically disables the channel when * this interrupt occurred. */ if (netTaskId && netTaskId != ERROR) { pDrvCtrl->localFlags |= EMAC_HANDLE_RX_RUNNING; netJobAdd((FUNCPTR)ibmEmacHandleRecvInt, (int)pDrvCtrl, TRUE,0,0,0); } else ibmEmacHandleRecvInt(pDrvCtrl, TRUE); return; }/********************************************************************************* ibmEmacMalSerrInt - handle MAL SERR (system error) interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.*/LOCAL void ibmEmacMalSerrInt ( EMAC_DRV_CTRL * pDrvCtrl ) { DRV_LOG (DRV_DEBUG_ERROR, "EMAC-MAL SERR int\n", 1, 2, 3, 4, 5, 6); /* MAL should have already reset the channel */ /* SERR is fatal, just restart the EMAC */ pDrvCtrl->lastError.errCode = END_ERR_RESET; pDrvCtrl->lastError.pMesg = "MAL System Error."; if (netTaskId && netTaskId != ERROR) netJobAdd ((FUNCPTR)muxError, (int)&pDrvCtrl->end, (int)&pDrvCtrl->lastError, 0, 0, 0); else muxError (&pDrvCtrl->end, &pDrvCtrl->lastError); END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING)); ibmEmacRestart(pDrvCtrl); return; }/********************************************************************************* ibmEmacHandleRecvInt - task level interrupt service for received packets** This routine is called at task level indirectly by the interrupt* service routine to process received messages.** The double loop is to protect against a race condition where the interrupt* code sees EMAC_HANDLE_RX_RUNNING as TRUE, but it is then turned off by the* task code.*/LOCAL void ibmEmacHandleRecvInt ( EMAC_DRV_CTRL * pDrvCtrl, int resetChan ) { MAL_BD * pRxDesc; /* * Keep getting RX descriptors and calling the receive function until * there are no more ready to handle. */ pRxDesc = (MAL_BD *)NULL; do { pDrvCtrl->localFlags |= EMAC_HANDLE_RX_RUNNING; while ((pRxDesc = ibmEmacRecvDescGet(pDrvCtrl)) != (MAL_BD *)NULL) { ibmEmacRecv(pDrvCtrl, pRxDesc); }; pDrvCtrl->localFlags &= ~EMAC_HANDLE_RX_RUNNING; } while (ibmEmacRecvDescGet(pDrvCtrl) != NULL); /* * This function may have been run as a result of an RX descriptor error * interrupt (RXDE). If so, the RX channel was disabled by MAL and must * be re-activated for RX operation to continue. When a channel is * reactivated, it begins to process descriptors from the beginning of the * descriptor table, so the current RX descriptor index must be reset. */ if (resetChan == TRUE) { pDrvCtrl->indexRxD = 0; malChannelActivate(pDrvCtrl->pMalData, MAL_RX_TYPE, pDrvCtrl->rxChn0MalChannel); } }/********************************************************************************* ibmEmacRecvDescGet - get the next receive descriptor** Returns a ptr to next RX descriptor to process, or NULL if none are ready.*/LOCAL MAL_BD * ibmEmacRecvDescGet ( EMAC_DRV_CTRL * pDrvCtrl ) { volatile MAL_BD * pRxDesc; /* Point to the next RX descriptor */ pRxDesc = pDrvCtrl->pRxDesc + pDrvCtrl->indexRxD; /* * If the descriptor says the buffer is no longer empty, return the * pointer to the descriptor, else return NULL (buffer is still empty). */ if ((pRxDesc->statusControl & MAL_RX_CTRL_EMPTY) == 0) { DRV_LOG (DRV_DEBUG_RX, "RX desc got data\n", 1, 2, 3, 4, 5, 6); return((MAL_BD *)pRxDesc); } else { DRV_LOG (DRV_DEBUG_RX, "RX desc no data yet\n", 1, 2, 3, 4, 5, 6); return ((MAL_BD *)NULL); } }/********************************************************************************* ibmEmacRecv - process the next incoming packet** RETURNS: OK/ERROR*/LOCAL STATUS ibmEmacRecv ( EMAC_DRV_CTRL * pDrvCtrl, MAL_BD * pRxDesc ) { int len; char * pCluster; char * pNewCluster = NULL; CL_BLK_ID pClBlk; M_BLK_ID pMblk; USHORT statusRx; int index; DRV_LOG (DRV_DEBUG_RECV, "->ibmEmacRecv \n", 1, 2, 3, 4, 5, 6); index = pDrvCtrl->indexRxD; /* Bump the RX descriptor ring placeholder to the next position. */ pDrvCtrl->indexRxD = (index + 1) % pDrvCtrl->numRxD; /* Check packet for errors */ statusRx = pRxDesc->statusControl; DRV_LOG (DRV_DEBUG_RX, "EmacRecv : RxDesc = %X index = %d\n", statusRx, index, 3, 4, 5, 6); /* If any of the error bits are set in the RX descriptor bump error count */ if (statusRx & EMAC_RX_ERRORS) { DRV_LOG (DRV_DEBUG_ERROR, "Status in RX Desc = 0x%x\n", statusRx, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); /* Toss the packet, but reuse the cluster */ goto cleanRXD; } /* If the packet spans more than one buffer, this is also an error. */ if ((statusRx & MAL_RX_ONE_BUFFER) != MAL_RX_ONE_BUFFER) { DRV_LOG (DRV_DEBUG_ERROR, "RX packet spans >1 buffer\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); /* Toss the packet, but reuse the cluster */ goto cleanRXD; } /* If we cannot get a new cluster to replace the full one, then bail out. */ pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -