📄 if_seeq.c
字号:
{ /* write direction: wait until buffer writing is complete. */ if (seeqFlushFIFO (pDrvCtrl) != OK) return (ERROR); } /* Set DMA address */ SEEQ_WRITE (pDev->pDma, addr); return (OK); }/******************************************************************************** seeqChipReset - hardware reset of chip (stop it)** NOMANUAL*/void seeqChipReset ( int unit ) { int i; int oldLevel; DRV_CTRL *pDrvCtrl = &drvCtrl[unit]; SEEQ_DEVICE *pDev; volatile UCHAR *bwind; /* Sanity check the unit number */ if (unit < 0 || unit >= MAX_UNITS) return;#ifdef DEBUG if (seeqDebug) logMsg ("seeqChipReset(%d)\n", unit, 0, 0, 0, 0, 0);#endif pDrvCtrl->flags = 0; pDrvCtrl->txCount = 0; /* Reset the chip */ pDev = pDrvCtrl->devAdrs; SEEQ_WRITE (pDev->pCfg1, 0); SEEQ_WRITE (pDev->pCfg2, SEEQ_CONF2_RESET); /* Delay at least 4us */ taskDelay (1); /* Check status register for 0x5800 */ if (SEEQ_READ(pDev->pStat) != 0x5800) { logMsg ("seeq: probe at 0x%x failed, got 0x%04x\n", (int) pDrvCtrl->devAdrs->pCmd, SEEQ_READ(pDev->pStat), 0, 0, 0, 0); } /* lock interrupts */ oldLevel = intLock (); /* Program the interrupt vector */ SEEQ_WRITE (pDev->pCfg1, ((SEEQ_READ(pDev->pCfg1) & 0xfff0) | SEEQ_CONF1_IVEC)); SEEQ_WRITE (pDev->pBwind, pDrvCtrl->inum); /* Program station addr 0 w/ our e-net addr */ /* Turn Tx, Rx and DMA off, then ack any interrupts */ SEEQ_WRITE (pDev->pCmd, (SEEQ_CMD_FIFO_WRITE | SEEQ_CMD_ALL_OFF)); SEEQ_WRITE (pDev->pCmd, (SEEQ_CMD_FIFO_WRITE | SEEQ_CMD_ALL_OFF | SEEQ_CMD_ALL_ACK)); /* Select address 0 */ SEEQ_WRITE (pDev->pCfg1, ((SEEQ_READ(pDev->pCfg1) & 0xfff0) | 0)); /* Get byte pointer to buffer window */ bwind = ((volatile UCHAR *) pDev->pBwind) + SEEQ_LSB_OFFSET; /* Program the ethernet address */ for (i = 0; i < 6; ++i) SEEQ_WRITE_BYTE (bwind, ((UCHAR *)pDrvCtrl->idr.ac_enaddr)[i]); /* * Configure the local memory buffer to allow half of the * space for transmit and half for receive. */ pDrvCtrl->tea = 0x7f; pDrvCtrl->rea = 0xffff; pDrvCtrl->rxNext = (pDrvCtrl->tea + 1) << 8; pDrvCtrl->txEnd = ((pDrvCtrl->tea + 1) << 8) - 1; pDrvCtrl->txNext = 0; pDrvCtrl->txCurr = 0; pDrvCtrl->txLow = 0; SEEQ_WRITE(pDev->pCfg1, (*pDev->pCfg1 & 0xfff0) | SEEQ_CONF1_TXEND); SEEQ_WRITE(pDev->pBwind, pDrvCtrl->tea); SEEQ_WRITE(pDev->pTxptr, pDrvCtrl->txNext); SEEQ_WRITE(pDev->pRxptr, pDrvCtrl->rxNext); SEEQ_WRITE(pDev->pRxend, pDrvCtrl->rea); /* * Config1 register setup: * * Specific Addr 0: Enabled * Specific Addr 1: Disabled * Specific Addr 2: Disabled * Specific Addr 3: Disabled * Specific Addr 4: Disabled * Specific Addr 5: Disabled * DMA Burst Length: 1 byte * DMA Burst Interval: continuous * MatchMode: Specific Addresses + Broadcast Addr */ *pDev->pCfg1 = SEEQ_CONF1_ADDR0_EN | SEEQ_CONF1_RX_SPEC_BROAD | SEEQ_CONF1_DMA_BURST_INTERVAL_0; /* * Config2 register setup: * * select byte swapping, or not. Yes for BIG_ENDIAN * AutoUpdate REA: Disabled. * Receive While Transmitting: Enabled. * CRC ErrorEnable: CRC Error packets not accepted. * Dribble Error Enable: Dribble packets not accepted. * Pass Long/Short Enable: Neither long or short packets accepted. * Preamble Select: Std 802.3 64 bit preamble selected. * RecCRC: CRC is stripped from incoming packets. * XmitNoCRC: Outgoing packets have CRC appended. * Loopback: Loopback disabled. * CTRLO: CTRL0 pin is low. * RESET: Not asserted. */ SEEQ_WRITE (pDev->pCfg2, SEEQ_CFG2_BSWAP); /* * Configure for RX and TX off and interrupts disabled. * Ack any pending interrupts. */ SEEQ_WRITE (pDev->pCmd, (SEEQ_CMD_RX_OFF | SEEQ_CMD_TX_OFF | SEEQ_CMD_ALL_ACK)); intUnlock (oldLevel); }/******************************************************************************** seeqTxReset - Reset the TX** NOMANUAL*/void seeqTxReset ( int unit ) { int oldLevel; DRV_CTRL *pDrvCtrl = &drvCtrl[unit]; SEEQ_DEVICE *pDev; /* Sanity check the unit number */ if (unit < 0 || unit >= MAX_UNITS) return;#ifdef DEBUG if (seeqDebug) logMsg ("seeqTxReset(%d)\n", unit, 0, 0, 0, 0, 0);#endif pDev = pDrvCtrl->devAdrs; oldLevel = intLock (); /* Report an error */ ++pDrvCtrl->idr.ac_if.if_oerrors; /* Recover - disable the TX */ SEEQ_WRITE (pDev->pCmd, ((SEEQ_READ(pDev->pStat) & SEEQ_STAT_CMD_MASK) | SEEQ_CMD_TX_OFF)); pDrvCtrl->txNext = 0; pDrvCtrl->txCurr = 0; pDrvCtrl->txCount = 0; SEEQ_WRITE (pDev->pTxptr, 0); /* Ack the buffer and TX interrupts */ SEEQ_WRITE (pDev->pCmd, ((SEEQ_READ(pDev->pStat) & SEEQ_STAT_CMD_MASK) | SEEQ_CMD_TX_ACK | SEEQ_CMD_BUF_ACK)); intUnlock (oldLevel); }/******************************************************************************** seeqRxReset - Reset the RX** NOMANUAL*/void seeqRxReset ( int unit ) { int oldLevel; DRV_CTRL *pDrvCtrl = &drvCtrl[unit]; SEEQ_DEVICE *pDev; /* Sanity check the unit number */ if (unit < 0 || unit >= MAX_UNITS) return;#ifdef DEBUG if (seeqDebug) logMsg ("seeqRxReset(%d)\n", unit, 0, 0, 0, 0, 0);#endif pDev = pDrvCtrl->devAdrs; oldLevel = intLock (); /* Report an error */ ++pDrvCtrl->idr.ac_if.if_ierrors; /* Recover - disable the RX */ SEEQ_WRITE (pDev->pCmd, ((SEEQ_READ(pDev->pStat) & SEEQ_STAT_CMD_MASK) | SEEQ_CMD_RX_OFF)); pDrvCtrl->rxNext = (pDrvCtrl->tea + 1) << 8; SEEQ_WRITE (pDev->pRxptr, pDrvCtrl->rxNext); /* Ack the buffer and RX interrupts */ SEEQ_WRITE (pDev->pCmd, ((SEEQ_READ(pDev->pStat) & SEEQ_STAT_CMD_MASK) | SEEQ_CMD_RX_ACK | SEEQ_CMD_BUF_ACK | SEEQ_CMD_RX_ON )); intUnlock (oldLevel); }/******************************************************************************** seeqReset - reset the interface** Mark interface as inactive & reset the chip** NOMANUAL*/LOCAL void seeqReset ( int unit ) { int oldLevel; DRV_CTRL *pDrvCtrl = &drvCtrl[unit]; /* Sanity check the unit number */ if (unit < 0 || unit >= MAX_UNITS) return; oldLevel = intLock (); /* Reset the chip */ SEEQ_WRITE (pDrvCtrl->devAdrs->pCfg1, 0); SEEQ_WRITE (pDrvCtrl->devAdrs->pCfg2, SEEQ_CONF2_RESET); /* Mark the interface as down */ pDrvCtrl->idr.ac_if.if_flags = 0; intUnlock (oldLevel); }/******************************************************************************** seeqReceive - handle receiving packets.** NOMANUAL*/LOCAL void seeqReceive ( int unit ) { USHORT nextFrame; USHORT headerStatus; int pktByteCnt = 0; DRV_CTRL *pDrvCtrl = &drvCtrl[unit]; SEEQ_DEVICE *pDev = pDrvCtrl->devAdrs; /* If interface was shutdown, abort service request */ if (!(pDrvCtrl->idr.ac_if.if_flags & IFF_UP)) { pDrvCtrl->flags &= ~SEEQ_RX_OUTSTANDING; return; } if (!(pDrvCtrl->flags & SEEQ_RX_OUTSTANDING)) {#ifdef DEBUG if (seeqDebug) logMsg ("seeq: no RX request outstanding\n", 0, 0, 0, 0, 0, 0);#endif return; } pDrvCtrl->flags &= ~SEEQ_RX_OUTSTANDING; do { int i; USHORT frameStatus; USHORT frameLength; USHORT tmp; if (seeqSetDMARead(pDrvCtrl, pDrvCtrl->rxNext) != OK) { /* re-queue for later processing. */#ifdef DEBUG if (seeqDebug) logMsg ("RX: Set DMA failed\n", 0, 0, 0, 0, 0, 0);#endif seeqRxReset (pDrvCtrl->unit); pDrvCtrl->flags |= SEEQ_RX_OUTSTANDING; netJobAdd ((FUNCPTR) seeqReceive, unit, 0, 0, 0, 0); break; } nextFrame = SEEQ_READ (pDev->pBwind); /* Get the header and frame status */ tmp = SEEQ_READ (pDev->pBwind); headerStatus = tmp >> 8; frameStatus = tmp & 0x00ff; /* * Stop under any of the following conditions: * The packet isn't done * The next packet is this packet (looped back). */ if (!(frameStatus & SEEQ_RX_PSTAT_DONE) || (nextFrame == pDrvCtrl->rxNext)) break; if (nextFrame < pDrvCtrl->rxNext) { /* The receiver wrapped around */ frameLength = (pDrvCtrl->rea+1) - pDrvCtrl->rxNext - 4 + (nextFrame - (int)((pDrvCtrl->tea + 1)<<8)); } else { /* The frame is sequential, not wrapped */ frameLength = nextFrame - pDrvCtrl->rxNext - 4; } /* account for space consumed in the buffer. */ pktByteCnt += frameLength + 4; if (pktByteCnt > 0x8000) {#ifdef DEBUG if (seeqDebug) logMsg ("RX packet overflows\n", 0, 0, 0, 0, 0, 0);#endif seeqRxReset (pDrvCtrl->unit); break; }#ifdef DEBUG if (seeqDebug) logMsg ("RX pkt: @ 0x%04x Frame 0x%02x Header 0x%02x len %4d nxt 0x%04x\n", pDrvCtrl->rxNext, frameStatus, headerStatus, frameLength, nextFrame, 0);#endif if (frameStatus != SEEQ_RX_PSTAT_DONE) { /* one of the errors */ if (frameStatus & SEEQ_RX_PSTAT_OVERSIZE) ++pDrvCtrl->idr.ac_if.if_ierrors; if (frameStatus & SEEQ_RX_PSTAT_CRC) ++pDrvCtrl->idr.ac_if.if_ierrors; if (frameStatus & SEEQ_RX_PSTAT_DRIBBLE) ++pDrvCtrl->idr.ac_if.if_ierrors; if (frameStatus & SEEQ_RX_PSTAT_SHORT) ++pDrvCtrl->idr.ac_if.if_ierrors; } else { ETH_HDR *pHdr = (ETH_HDR *) pDrvCtrl->rxBuf; char *bufp = (char *) pDrvCtrl->rxBuf; /* Read in the entire packet */ for (i = 0; i < frameLength/2; ++i) { ((USHORT *) bufp)[i] = SEEQ_READ (pDev->pBwind); } /* Get the last odd byte */ if (frameLength & 1) { bufp[frameLength-1] = SEEQ_READ_BYTE (pDev->pBwind); } /* call input hook if any */ if ((etherInputHookRtn == NULL) || !(*etherInputHookRtn) (&pDrvCtrl->idr.ac_if, bufp, frameLength)) { MBUF *pMbuf; bufp += SIZEOF_ETHERHEADER; frameLength -= SIZEOF_ETHERHEADER; pMbuf = copy_to_mbufs (bufp, frameLength, 0, (IFNET *) &pDrvCtrl->idr.ac_if); if (pMbuf != NULL) { do_protocol_with_type (ntohs (pHdr->ether_type), pMbuf, &pDrvCtrl->idr, frameLength); pDrvCtrl->idr.ac_if.if_ipackets++; } } } /* adjust circular buffer */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -