📄 elt3c509end.c
字号:
/* Handle adapter failure first in case other conditions mask it */ if ((status & ADAPTER_FAILURE) != 0) { SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, SELECT_WINDOW | WIN_DIAGNOSTIC); SYS_IN_WORD (pDrvCtrl, port + FIFO_DIAGNOSTIC, statusDiag); SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, SELECT_WINDOW | WIN_OPERATING); if ((statusDiag & FD_TX_OVERRUN) != 0) { ++pDrvCtrl->elt3c509Stat.txoverruns; SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, TX_RESET); elt3c509TxStart (pDrvCtrl); } if ((status & FD_RX_UNDERRUN) != 0) { ++pDrvCtrl->elt3c509Stat.rxunderruns; SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, RX_RESET); elt3c509RxStart (pDrvCtrl); } } if (status & (RX_COMPLETE | RX_EARLY)) { if ((status & RX_EARLY) != 0) ++pDrvCtrl->elt3c509Stat.rxearly; if (netJobAdd ((FUNCPTR)elt3c509HandlePktsRcv, (int) pDrvCtrl, 0, 0, 0, 0) == OK) { pDrvCtrl->intMask &= ~(RX_COMPLETE | RX_EARLY); #ifdef ELT_TIMING if((int)++pDrvCtrl->elt3c509Stat.taskQRxOuts > (int)pDrvCtrl->elt3c509Stat.maxRxTaskQ) { pDrvCtrl->elt3c509Stat.maxRxTaskQ = pDrvCtrl->elt3c509Stat.taskQRxOuts; }#endif /* ELT_TIMING */ } else logMsg ("elt: netJobAdd (elt3c509HandlePktsRcv) failed\n", 0, 0, 0, 0, 0, 0); } /* Handle transmitter interrupts */ if ((status & TX_COMPLETE) != 0) { SYS_IN_BYTE (pDrvCtrl, port+TX_STATUS, statusTx); if ((statusTx & TX_S_COMPLETE) != 0) { SYS_OUT_BYTE (pDrvCtrl,port + TX_STATUS, 0); /* clear old status */ /* * other errors are tabulated by reading the statistics registers */ if ((statusTx & TX_S_MAX_COLL) != 0) END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +16); if ((statusTx & TX_S_JABBER) != 0) END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); if ((statusTx & (TX_S_JABBER | TX_S_MAX_COLL | TX_S_UNDERRUN)) != 0) { needTxStart = TRUE; /* restart transmitter */ /* packet not sent */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1); } if ((statusTx & (TX_S_JABBER | TX_S_UNDERRUN)) != 0) { /* Must reset transmitter; this clears the tx FIFO */ SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, TX_RESET); } } if (needTxStart) /* check flag */ elt3c509TxStart (pDrvCtrl); if (pDrvCtrl->txBlocked) { pDrvCtrl->txBlocked = FALSE; /* restart the transmit flow */ netJobAdd ((FUNCPTR) muxTxRestart, (int) &pDrvCtrl->endObj, 0, 0, 0, 0);#ifdef ELT_TIMING if ((int)++pDrvCtrl->elt3c509Stat.taskQTxOuts > (int)pDrvCtrl->elt3c509Stat.maxTxTaskQ) pDrvCtrl->elt3c509Stat.maxTxTaskQ = pDrvCtrl->elt3c509Stat.taskQTxOuts;#endif /* ELT_TIMING */ } } /* Handle update statistics interrupt */ if ((status & UPDATE_STATS) != 0) elt3c509StatFlush (pDrvCtrl); /* mask and ack the events we've just handled or queued handlers for */ SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, MASK_STATUS | pDrvCtrl->intMask); SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, ACK_INTERRUPT | status); sysBusIntAck (pDrvCtrl->intLevel); }/********************************************************************************* elt3c509HandlePktsRcv - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.** RETURNS: N/A.*/LOCAL void elt3c509HandlePktsRcv ( ELT3C509_DEVICE * pDrvCtrl /* interrupting device */ ) { M_BLK_ID pMblk; /* pointer to the mBlk */ CL_BLK_ID pClBlk; /* pointer to the clBlk */ char * pCluster; /* pointer to the cluster */ int port; /* IO port to read */ STATUS result = OK; /* Tracks result of Cluster Alloc */ port = pDrvCtrl->port; /* loop for more frames */ while (TRUE) { /* get a cluster */ pCluster = netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId); if (pCluster == NULL) { ENDLOGMSG (("Cannot loan!\n", 1, 2, 3, 4, 5, 6)); ++pDrvCtrl->elt3c509Stat.rxnobuffers; END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); result = ERROR; break; } /* get a cluster block */ if ((pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT)) == NULL) { netClFree (pDrvCtrl->endObj.pNetPool, pCluster); ENDLOGMSG (("Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6)); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); result = ERROR; break; } /* get an mBlk */ if ((pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk); netClFree (pDrvCtrl->endObj.pNetPool, pCluster); ENDLOGMSG (("Out of M Blocks!\n", 1, 2, 3, 4, 5, 6)); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); result = ERROR; break; } /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, pCluster, ELT3C509_BUFSIZ, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); if (elt3c509PollRcv ((void *)pDrvCtrl, pMblk) == OK) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); ENDLOGMSG (("Calling upper layer's recv rtn\n", 1, 2, 3, 4, 5, 6)); /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk); } else { ENDLOGMSG (("EAGAIN\n", 1, 2, 3, 4, 5, 6)); netMblkClFree (pMblk); result = ERROR; break; } } /* Discard the packet in the FIFO here of there was an error */ if (result == ERROR) { /* discard packet */ SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, RX_DISCARD); } /* enable the recv interrupt */ elt3c509IntMaskSet (pDrvCtrl, (RX_COMPLETE | RX_EARLY)); }/********************************************************************************* elt3c509PollRcv - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device.** RETURNS: EGAIN or OK*/LOCAL STATUS elt3c509PollRcv ( void * pEnd, /* device pointer */ M_BLK_ID pMblk /* pointer to the mBlk chain */ ) { UINT16 statusRx; UINT16 statusRxNew; UINT16 length; int port; int ix = 0; int status = OK; ELT3C509_DEVICE * pDrvCtrl; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); port = pDrvCtrl->port; SYS_IN_WORD (pDrvCtrl, port + RX_STATUS, statusRx); if (statusRx & RX_S_INCOMPLETE) /* incomplete */ { if (statusRx == RX_S_INCOMPLETE) /* no bytes available */ { ENDLOGMSG (("no more packets\n", 1, 2, 3, 4, 5, 6)); return (EAGAIN); } while (ix < 10000) { SYS_IN_WORD (pDrvCtrl, port + RX_STATUS, statusRxNew); if (statusRx == statusRxNew) { break; } else { statusRx = statusRxNew; ix++; } } if (statusRx & RX_S_INCOMPLETE) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); ENDLOGMSG (("status quo\n", 1, 2, 3, 4, 5, 6)); status = EAGAIN; goto PollRcvErrHandle; } } /* Check for errors in completed packet */ if (statusRx & RX_S_ERROR) { switch (statusRx & RX_S_CODE_MASK) { case RX_S_OVERRUN: /* handled by statistics registers */ break; case RX_S_RUNT: ++pDrvCtrl->elt3c509Stat.shortPacket; break; case RX_S_ALIGN: ++pDrvCtrl->elt3c509Stat.aligns; break; case RX_S_CRC: ++pDrvCtrl->elt3c509Stat.crcs; break; case RX_S_OVERSIZE: ++pDrvCtrl->elt3c509Stat.badPacket; break; default: /* no other codes are defined */ break; } END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); ENDLOGMSG (("recv error\n", 1, 2, 3, 4, 5, 6)); status = EAGAIN; goto PollRcvErrHandle; } /* length of the buffer in the FIFO */ length = statusRx & RX_S_CNT_MASK; /* discard packet if received frame is bigger than MAX_FRAME_SIZE */ if (length > MAX_FRAME_SIZE) { ENDLOGMSG (("pktlen>MAX_FRAME_SIZE\n", 1, 2, 3, 4, 5, 6)); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); status = EAGAIN; goto PollRcvErrHandle; } /* if given mBlk does not have enough space */ if ((!(pMblk->mBlkHdr.mFlags & M_EXT)) || (pMblk->pClBlk->clSize < length)) { ENDLOGMSG (("PRX bad mblk len:%d flags:%d\n", pMblk->mBlkHdr.mLen, pMblk->mBlkHdr.mFlags, 3, 4, 5, 6)); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); status = EAGAIN; goto PollRcvErrHandle; } /* read the packet from the FIFO into the cluster */ SYS_IN_WORD_STRING (pDrvCtrl, port + DATA_REGISTER, (short *) pMblk->mBlkHdr.mData, (length + 1) / 2); /* update the mBlk fields */ pMblk->mBlkHdr.mLen = length; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = length; status = OK; PollRcvErrHandle: { /* discard packet */ SYS_OUT_WORD (pDrvCtrl, port + ELT3C509_COMMAND, RX_DISCARD); /* wait for command to finish */ statusRxNew = ERROR; while ((statusRxNew & COMMAND_IN_PROGRESS) != 0) { SYS_IN_WORD (pDrvCtrl, port + ELT3C509_STATUS, statusRxNew); } } return (status); }/******************************************************************************** elt3c509Config - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** RETURNS: N/A.*/LOCAL void elt3c509Config ( ELT3C509_DEVICE * pDrvCtrl /* device to be re-configured */ ) { /* Set promiscuous mode if it's asked for. */ if (END_FLAGS_GET (&pDrvCtrl->endObj) & IFF_PROMISC) { ENDLOGMSG (("Setting promiscuous mode on!\n", 1, 2, 3, 4, 5, 6)); pDrvCtrl->rxFilter |= RX_F_PROMISCUOUS; SYS_OUT_WORD(pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, SET_RX_FILTER | pDrvCtrl->rxFilter); } else { ENDLOGMSG (("Setting promiscuous mode off!\n", 1, 2, 3, 4, 5, 6)); pDrvCtrl->rxFilter &= ~RX_F_PROMISCUOUS; SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, SET_RX_FILTER | pDrvCtrl->rxFilter); } /* Set up address filter for multicasting. * Multicast bit is set if the address list has one or more entries * Multicasting is disabled if the address list is empty */ if (END_MULTI_LST_CNT (&pDrvCtrl->endObj) > 0 || (END_FLAGS_GET (&pDrvCtrl->endObj) & IFF_MULTICAST)) { ENDLOGMSG (("Setting multicast mode on!\n", 1, 2, 3, 4, 5, 6)); pDrvCtrl->rxFilter |= RX_F_MULTICAST; SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, SET_RX_FILTER | pDrvCtrl->rxFilter); } else { ENDLOGMSG (("Setting multcast mode off!\n", 1, 2, 3, 4, 5, 6)); pDrvCtrl->rxFilter &= ~RX_F_MULTICAST; SYS_OUT_WORD (pDrvCtrl, pDrvCtrl->port + ELT3C509_COMMAND, SET_RX_FILTER | pDrvCtrl->rxFilter); } return; }/********************************************************************************* elt3c509PollSend - routine to send a packet in polled mode.** This routine is called by a user to try and send a packet on the* device.** RETURNS: OK upon success. EAGAIN if device is busy.*/LOCAL STATUS elt3c509PollSend
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -