📄 elt3c509end.c
字号:
} 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 ( void * pEnd, /* device pointer */ M_BLK_ID pMblk /* packet to send */ ) { int len; int * pLenMask; char * pBuf; ELT3C509_DEVICE * pDrvCtrl; UINT16 txStatus; VOID_TO_DRVCTRL (pEnd, pDrvCtrl); SYS_IN_WORD (pDrvCtrl, pDrvCtrl->port + TX_FREE_BYTES, txStatus); if (txStatus >= TX_IDLE_COUNT) { pBuf = pDrvCtrl->pTxCluster; /* pointer to the transmit cluster */ pLenMask = (UINT32 *)pBuf; /* allow space for the preamble the trasmit buffer is 1520 */ pBuf += sizeof(UINT32); len = netMblkToBufCopy(pMblk, pBuf, NULL); len = max(len, ETHERSMALL); /* set the packet size */ *pLenMask = len | TX_F_INTERRUPT; /* set the preamble */ len = (len + TX_F_PREAMBLE_SIZE + 3) & TX_F_DWORD_MASK; /* place a transmit request */ SYS_OUT_WORD_STRING (pDrvCtrl, pDrvCtrl->port + DATA_REGISTER, (short *)pLenMask, len / 2); /* read the tranmsit status */ SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->port + TX_STATUS, txStatus); /* wait until tramit is complete */ while (!(txStatus & TX_S_COMPLETE)) { SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->port + TX_STATUS, txStatus); } /* clear old status */ SYS_OUT_BYTE (pDrvCtrl, pDrvCtrl->port + TX_STATUS, 0); } else { ENDLOGMSG(("Error in Send, not enough TxFreeBytes\n",1,2,3,4,5,6)); return (EAGAIN); } /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); ENDLOGMSG (("Poll Send complete\n",1,2,3,4,5,6)); return (OK); }/********************************************************************************* elt3c509PollStart - start polled mode operations** This function starts polled mode operation.** The device interrupts are disabled, the current mode flag is switched* to indicate Polled mode and the device is reconfigured.** RETURNS: OK or ERROR.*/LOCAL STATUS elt3c509PollStart ( ELT3C509_DEVICE * pDrvCtrl /* device to be polled */ ) { int oldLevel; oldLevel = intLock (); /* disable ints during update */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -