📄 ultraend.c
字号:
SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_PS1 | CMD_STP); /* Program wait states (0) */ SYS_OUT_BYTE (pDrvCtrl, LAN_ENH, 0x00); /* put the Ultra in START mode */ SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_STA); /* Take interface out of loopback */ SYS_OUT_BYTE (pDrvCtrl, LAN_TCON, 0x00); if (!(pDrvCtrl->flags & ULTRA_POLLING)) { SYS_OUT_BYTE (pDrvCtrl, CTRL_INT, INT_ENABLE); SYS_OUT_BYTE (pDrvCtrl, LAN_INTMASK, IM_OVWE | IM_TXEE | IM_PTXE | IM_PRXE); } }/******************************************************************************** ultraInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A.*/LOCAL void ultraInt ( ULTRA_DEVICE * pDrvCtrl /* interrupting device */ ) { UCHAR istat; /* Acknowledge interrupt, get Transmit/Receive status */ pDrvCtrl->istat = 0; do { SYS_IN_BYTE (pDrvCtrl, LAN_INTSTAT, &istat); SYS_OUT_BYTE (pDrvCtrl, LAN_INTSTAT, istat); pDrvCtrl->istat |= istat; } while (istat != 0); SYS_IN_BYTE (pDrvCtrl, LAN_TSTAT, &pDrvCtrl->tstat); SYS_IN_BYTE (pDrvCtrl, LAN_RSTAT, &pDrvCtrl->rstat); DRV_LOG (DRV_DEBUG_INT, "%s%d: istat %x tstat %x rstat %x flags %x\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->istat, pDrvCtrl->tstat, pDrvCtrl->rstat, pDrvCtrl->flags); /* Receive-error */ if (pDrvCtrl->istat & ISTAT_RXE) END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); /* Receive, Overwrite */ if (pDrvCtrl->istat & (ISTAT_PRX | ISTAT_OVW)) { if (pDrvCtrl->istat & ISTAT_OVW) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_INT | DRV_DEBUG_ERR, "%s%d: overwrite error\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); } if (!(pDrvCtrl->flags & ULTRA_RCV_HANDLING_FLAG)) { if (netJobAdd ((FUNCPTR) ultraHandleRcvInt, (int) pDrvCtrl, 0, 0, 0, 0) == ERROR) { /* Error - will have to wait until next RX interrupt recv'd */ logMsg ("%s%d: failed to queue ultraHandleRcvInt\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); /* failed netJobAdd causes panic, stop device */ SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_STP); return; } pDrvCtrl->flags |= ULTRA_RCV_HANDLING_FLAG; SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_PS0); SYS_IN_BYTE (pDrvCtrl, LAN_CURR, &pDrvCtrl->current); SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, 0); DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_INT, "%s%d: queued ultraHandleRcvInt: curr=%x next=%x\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->current, pDrvCtrl->nextPacket, 5, 6); } } /* Transmit-error, Transmit */ if (pDrvCtrl->istat & (ISTAT_TXE | ISTAT_PTX)) { if (pDrvCtrl->istat & ISTAT_TXE) END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, -1); if ((pDrvCtrl->istat & ISTAT_TXE) || (pDrvCtrl->tstat & (TSTAT_ABORT | TSTAT_UNDER | TSTAT_CDH | TSTAT_OWC | TSTAT_PTX))) END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); pDrvCtrl->flags &= ~ULTRA_TX_IN_PROGRESS; if (pDrvCtrl->flags & ULTRA_TX_BLOCKED) { DRV_LOG (DRV_DEBUG_TX | DRV_DEBUG_INT, "%s%d: queuing muxTxRestart\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); if (netJobAdd ((FUNCPTR)muxTxRestart, (int) &pDrvCtrl->endObj, 0, 0, 0, 0) == ERROR) { /* Error - can't queue, transmitter is hung. */ logMsg ("%s%d: failed to queue muxTxRestart\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); /* failed netJobAdd causes panic, stop device */ SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_STP); return; } pDrvCtrl->flags &= ~ULTRA_TX_BLOCKED; } } }/******************************************************************************** ultraPacketGet - get next received message** Get next received packet into the supplied buffer.** RETURNS: length of the next packet, or a negative number if none available.*/LOCAL int ultraPacketGet ( ULTRA_DEVICE * pDrvCtrl, UCHAR * pDst ) { int len; char * pSrc; int wrapSize = 0; UINT packetSize; int oldLevel; ULTRA_HEADER * pH; if (pDrvCtrl->nextPacket == pDrvCtrl->current) return (0); /* Invalidate cache and get pointer to header */ ULTRA_CACHE_INVALIDATE ((UCHAR *)(pDrvCtrl->memAddr + (ULTRA_PSTART << 8)), (pDrvCtrl->memSize - (ULTRA_PSTART << 8))); pH = (ULTRA_HEADER *)(pDrvCtrl->memAddr + (pDrvCtrl->nextPacket << 8)); DRV_LOG (DRV_DEBUG_RX, "%s%d: ultraPacketGet: %02x/%d/%02x/%02x\n", (int) DEV_NAME, pDrvCtrl->unit, pH->next, (((UINT)pH->uppByteCnt << 8) + pH->lowByteCnt), pDrvCtrl->nextPacket, pDrvCtrl->uppByteCnt); if ((pH->next < ULTRA_PSTART) || (pH->next >= ULTRA_PSTOP)) { pH->next = pDrvCtrl->nextPacket + pDrvCtrl->uppByteCnt + 1; DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERR, "%s%d: ultraPacketGet: fix pH->next (%x)\n", (int) DEV_NAME, pDrvCtrl->unit, pH->next, 4, 5, 6); if (pH->next >= ULTRA_PSTOP) pH->next = ULTRA_PSTART + (pH->next - ULTRA_PSTOP); } if (pH->rstat & RSTAT_PRX) { /* 3Com says this status marks a packet bit-shifted in memory; * the data cannot be trusted but the NIC header is OK. */ if (pH->rstat & (RSTAT_DFR | RSTAT_DIS)) { DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERR, "%s%d: ultraPacketGet: bit-shifted packet\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); packetSize = -2; goto doneGet; } } else { DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERR, "%s%d: ultraPacketGet: corrupted packet\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); packetSize = -2; goto doneGet; } /* Compute packet size, excluding Ultra header */ pSrc = ((char *)pH) + sizeof(ULTRA_HEADER); packetSize = (((UINT)pH->uppByteCnt << 8) + pH->lowByteCnt - sizeof(ULTRA_HEADER)); if ((packetSize < ULTRA_MIN_SIZE) || (packetSize > ULTRA_MAX_SIZE)) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERR, "%s%d: ultraPacketGet: bad size packet %d\n", (int) DEV_NAME, pDrvCtrl->unit, packetSize, 4, 5, 6); packetSize = -2; goto doneGet; } /* copy separated frame to network buffer */ len = packetSize; if ((pSrc+packetSize) > (char *)(pDrvCtrl->memAddr + (ULTRA_PSTOP << 8))) { wrapSize = (char *)(pDrvCtrl->memAddr + (ULTRA_PSTOP << 8)) - pSrc; bcopy (pSrc, pDst, wrapSize); len -= wrapSize; pSrc = (char *) (pDrvCtrl->memAddr + (ULTRA_PSTART << 8)); pDst += wrapSize; } bcopy (pSrc, pDst, len); DRV_LOG (DRV_DEBUG_RX, "%s%d: ultraPacketGet: c/n=%x/%x len/next=%d/%x\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->current, pDrvCtrl->nextPacket, (((UINT)pH->uppByteCnt << 8) + pH->lowByteCnt), pH->next); doneGet: /* Mark packet as received. */ oldLevel = intLock (); pDrvCtrl->nextPacket = pH->next; pDrvCtrl->uppByteCnt = pH->uppByteCnt; if (pDrvCtrl->nextPacket != ULTRA_PSTART) SYS_OUT_BYTE (pDrvCtrl, LAN_BOUND, pDrvCtrl->nextPacket - 1); else SYS_OUT_BYTE (pDrvCtrl, LAN_BOUND, ULTRA_PSTOP - 1); intUnlock (oldLevel); return (packetSize); }/******************************************************************************** ultraRecv - process the next incoming packet.** Handle one incoming packet. The packet is checked for errors.** RETURNS: OK or ERROR.*/LOCAL STATUS ultraRecv ( ULTRA_DEVICE * pDrvCtrl /* interrupting device */ ) { int len; char * pBuf; CL_BLK_ID pClBlk; M_BLK_ID pMblk; /* MBLK to send upstream */ /* Allocate an MBLK, and a replacement buffer */ pBuf = netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->clPoolId); if (!pBuf) { DRV_LOG (DRV_DEBUG_RX, "%s%d: ultraRecv: Out of clusters!\n", (int) DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "out of clusters"; muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError); return (ERROR); } /* Read in offset packet so IP header is long-aligned */ len = ultraPacketGet (pDrvCtrl, pBuf + pDrvCtrl->offset); if (len <= 0) { DRV_LOG (DRV_DEBUG_RX, "%s%d: ultraRecv: bad packet (%d)\n", (int) DEV_NAME, pDrvCtrl->unit, len, 0, 0, 0); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *) pBuf); return (OK); } pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA); if (!pMblk) { DRV_LOG (DRV_DEBUG_RX, "%s%d: ultraRecv: out of M blocks\n", (int) DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "out of M blocks."; muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *) pBuf); return (OK); } pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT); if (!pClBlk) { DRV_LOG (DRV_DEBUG_RX, "%s%d: ultraRecv: out of CL blocks\n", (int) DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); pDrvCtrl->lastError.errCode = END_ERR_WARN; pDrvCtrl->lastError.pMesg = "out of CL blocks."; muxError (&pDrvCtrl->endObj, &pDrvCtrl->lastError); netMblkFree (pDrvCtrl->endObj.pNetPool, (M_BLK_ID)pMblk); netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *) pBuf); return (OK); } /* Associate the data pointer with the MBLK */ netClBlkJoin (pClBlk, pBuf, ULTRA_BUFSIZ, NULL, 0, 0, 0); /* Associate the data pointer with the MBLK */ netMblkClJoin (pMblk, pClBlk); pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mLen = len; pMblk->mBlkPktHdr.len = len; pMblk->mBlkHdr.mData += pDrvCtrl->offset; /* match ultraPacketGet */ /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk); /* Record received packet */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); return (OK); }/******************************************************************************** ultraHandleRcvInt - 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 ultraHandleRcvInt ( ULTRA_DEVICE * pDrvCtrl /* interrupting device */ ) { DRV_LOG (DRV_DEBUG_RX, "%s%d: ultraHandleRcvInt: begin, flags=%x curr=%x next=%x\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->flags, pDrvCtrl->current, pDrvCtrl->nextPacket, 6); while (TRUE) { int oldLevel; /* Refresh the current pointer, and check if done. */ oldLevel = intLock (); SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, CMD_PS0); SYS_IN_BYTE (pDrvCtrl, LAN_CURR, &pDrvCtrl->current); SYS_OUT_BYTE (pDrvCtrl, LAN_CMD, 0); if (pDrvCtrl->nextPacket == pDrvCtrl->current) { /* all packets consumed. */ pDrvCtrl->flags &= ~ULTRA_RCV_HANDLING_FLAG; intUnlock (oldLevel); break; } intUnlock (oldLevel); if (ultraRecv (pDrvCtrl) == ERROR) { /* * ultraRecv only errors if out of clusters or the like. We * need to exit this loop and let the netTask run for a bit * in order for it to clean up its memory. */ oldLevel = intLock (); pDrvCtrl->flags &= ~ULTRA_RCV_HANDLING_FLAG; intUnlock (oldLevel); break; } } DRV_LOG (DRV_DEBUG_RX, "%s%d: ultraHandleRcvInt: done, flags=%x curr=%x next=%x\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->flags, pDrvCtrl->current, pDrvCtrl->nextPacket, 6); }/******************************************************************************** ultraSend - 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 or ERROR.*/LOCAL STATUS ultraSend ( void * pObj, /* device ptr */ M_BLK_ID pMblk /* data to send */ ) { int oldLevel; int len; UINT transmitPage; UCHAR * pBuf; ULTRA_DEVICE * pDrvCtrl = (ULTRA_DEVICE *) pObj; /* * Obtain exclusive access to transmitter. This is necessary because * we might have more than one stack transmitting at once. */ if (!(pDrvCtrl->flags & ULTRA_POLLING)) END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); if (pDrvCtrl->flags & ULTRA_TX_IN_PROGRESS) { int cnt; /* * Wait up to 1 second. Testing on a slow 486 pc platform this * loop never waited more than 2 ticks at 60/sec. */ cnt = sysClkRateGet (); while ((pDrvCtrl->flags & ULTRA_TX_IN_PROGRESS) && (cnt-- > 0)) taskDelay (1); DRV_LOG (DRV_DEBUG_TX, "%s%d: ultraSend: TX_IN_PROGRESS: waited %d ticks\n", (int) DEV_NAME, pDrvCtrl->unit, sysClkRateGet() - cnt, 0, 0, 0); } /* If TX still in progress, note blocked and return ERROR */ oldLevel = intLock (); if (pDrvCtrl->flags & ULTRA_TX_IN_PROGRESS) { DRV_LOG (DRV_DEBUG_TX, "%s%d: ultraSend: TX_IN_PROGRESS (flags=%x)\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->flags, 4, 5, 6); pDrvCtrl->flags |= ULTRA_TX_BLOCKED; if (!(pDrvCtrl->flags & ULTRA_POLLING)) END_TX_SEM_GIVE (&pDrvCtrl->endObj); intUnlock (oldLevel); return (END_ERR_BLOCK); } intUnlock (oldLevel); /* Copy and free the MBLK */ transmitPage = pDrvCtrl->transmitPage [pDrvCtrl->transmitCnt & 1]; pBuf = (UCHAR *)(pDrvCtrl->memAddr + (transmitPage << 8)); len = netMblkToBufCopy (pMblk, pBuf, NULL); len = max (len, ETHERSMALL); netMblkClChainFree (pMblk); DRV_LOG (DRV_DEBUG_TX, "%s%d: ultraSend, packet %d, len=%d\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->transmitCnt, len, 5, 6);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -