📄 ln7990end.c
字号:
/********************************************************************************* ln7990RestartSetup - setup memory descriptors and turn on chip** Initializes all the shared memory structures and turns on the chip.*/LOCAL STATUS ln7990RestartSetup ( LN7990END_DEVICE *pDrvCtrl ) { int rsize; int tsize; ln_tmd * pTmd; void * pTemp; /* reset the device */ ln7990Reset (pDrvCtrl); /* setup Rx buffer descriptors - align on 000 boundary */ rsize = pDrvCtrl->rringLen; pDrvCtrl->pRring = (ln_rmd *) ( ( (int)pDrvCtrl->pRring + 7) & ~7); /* * setup Tx buffer descriptors - * save unaligned location and align on 000 boundary */ pTmd = pDrvCtrl->pTring; tsize = pDrvCtrl->tringLen; pDrvCtrl->pTring = (ln_tmd *) ( ( (int)pDrvCtrl->pTring + 7) & ~7); /* setup the initialization block */ pDrvCtrl->ib = (ln_ib *)pDrvCtrl->pShMem; /* HELP */ swab ((char *) END_HADDR(&pDrvCtrl->end), pDrvCtrl->ib->lnIBPadr, 6); CACHE_PIPE_FLUSH (); pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->pRring); /* point to Rx ring */ LN_ADDR_TO_IB_RMD (pTemp, pDrvCtrl->ib, rsize); pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->pTring); /* point to Tx ring */ LN_ADDR_TO_IB_TMD (pTemp, pDrvCtrl->ib, tsize); DRV_LOG (DRV_DEBUG_LOAD, "Memory setup complete\n", 1, 2, 3, 4, 5, 6); /* reconfigure the device */ ln7990Config (pDrvCtrl); return (OK); } /********************************************************************************* ln7990Restart - restart the device after a fatal error** This routine takes care of all the messy details of a restart. The device* is reset and re-initialized. The driver state is re-synchronized.*/LOCAL void ln7990Restart ( LN7990END_DEVICE *pDrvCtrl ) { ln7990Reset (pDrvCtrl); ln7990RestartSetup (pDrvCtrl); /* set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->end, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST); }/******************************************************************************** ln7990Config - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** NOMANUAL*/LOCAL void ln7990Config ( LN7990END_DEVICE *pDrvCtrl ) { u_short stat; void* pTemp; int timeoutCount = 0; ln_rmd *pRmd; ln_tmd *pTmd; int ix; /* Set promiscuous mode if it's asked for. */ if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) { DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode on!\n", 1, 2, 3, 4, 5, 6); /* chip will be in promiscuous mode */ pDrvCtrl->ib->lnIBMode = 0x8000; } else { DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode off!\n", 1, 2, 3, 4, 5, 6); pDrvCtrl->ib->lnIBMode = 0; /* chip will be in normal receive mode */ } CACHE_PIPE_FLUSH (); ln7990CsrWrite (pDrvCtrl, 0, lncsr_STOP); /* set the stop bit */ /* Set up address filter for multicasting. */ if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0) { ln7990AddrFilterSet (pDrvCtrl); } ln7990CsrWrite (pDrvCtrl, 3, pDrvCtrl->csr3B); pRmd = pDrvCtrl->pRring; for (ix = 0; ix < pDrvCtrl->rringSize; ix++, pRmd++) { pRmd->rbuf_bcnt = -(LN_BUFSIZ); /* neg of buffer byte count */ LN_CLEAN_RXD (pRmd); } pDrvCtrl->rmdIndex = 0; pTmd = pDrvCtrl->pTring; for (ix = 0; ix < pDrvCtrl->tringSize; ix++, pTmd++) { pTmd->tbuf_bcnt = 0; /* no message byte count yet */ pTmd->tbuf_err = 0; /* no error status yet */ LN_TMD_CLR_ERR (pTmd); } pDrvCtrl->tmdIndex = 0; pDrvCtrl->tmdIndexC = 0; /* Point the device to the initialization block */ pTemp = LN_CACHE_VIRT_TO_PHYS (pDrvCtrl->ib); ln7990CsrWrite (pDrvCtrl, 2, (u_short)(((u_long)pTemp >> 16) & 0x000000ff)); ln7990CsrWrite (pDrvCtrl, 1, (u_long) pTemp); ln7990CsrWrite (pDrvCtrl, 0, lncsr_INIT); /* init chip (read IB) */ /* hang until Initialization DONe, ERRor, or timeout */ while (((stat = ln7990Csr0Read (pDrvCtrl)) & (lncsr_IDON | lncsr_ERR)) == 0) { if (timeoutCount++ > 0x10000) break; DELAY (1000 * timeoutCount); } DRV_LOG (DRV_DEBUG_LOAD, "Timeoutcount %d\n", timeoutCount, 2, 3, 4, 5, 6); /* log chip initialization failure */ if ((stat & lncsr_ERR) || (timeoutCount >= 0x10000)) { DRV_LOG (DRV_DEBUG_LOAD, "%s: Device initialization failed\n", (int)END_DEV_NAME(&pDrvCtrl->end), 0,0,0,0,0); return; } if (!(pDrvCtrl->flags & LS_POLLING)) { ln7990CsrWrite (pDrvCtrl, 0, lncsr_INEA | lncsr_STRT); } else { ln7990CsrWrite (pDrvCtrl, 0, lncsr_STRT); } }/******************************************************************************** ln7990AddrFilterSet - set the address filter for multicast addresses** This routine goes through all of the multicast addresses on the list* of addresses (added with the ln7990AddrAdd() routine) and sets the* device's filter correctly.** NOMANUAL*/LOCAL void ln7990AddrFilterSet ( LN7990END_DEVICE *pDrvCtrl ) { ETHER_MULTI* pCurr; ln_ib *pIb; u_char *pCp; u_char c; u_long crc; int len; int count; pIb = pDrvCtrl->ib; LN_ADDRF_CLEAR (pIb); pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end); while (pCurr != NULL) { /* * One would think, given the AM7990 document's polynomial * of 0x04c11db6, that this should be 0x6db88320 (the bit * reversal of the AMD value), but that is not right. See * the BASIC listing: bit 0 (our bit 31) must then be set. */ pCp = (unsigned char *)&pCurr->addr; crc = 0xffffffff; for (len = 6; --len >= 0;) { c = *pCp++; for (count = 0; count < 8; count++) { if ((c & 0x01) ^ (crc & 0x01)) { crc >>= 1; crc = crc ^ 0xedb88320; } else { crc >>= 1; } c >>= 1; } } /* Just want the 6 most significant bits. */ crc = crc >> 26; /* Turn on the corresponding bit in the filter. */ LN_ADDRF_SET (pIb, crc); pCurr = END_MULTI_LST_NEXT(pCurr); } }/********************************************************************************* ln7990PollReceive - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device.*/LOCAL STATUS ln7990PollReceive ( LN7990END_DEVICE *pDrvCtrl, M_BLK_ID pMblk ) { ln_rmd *pRmd; u_short stat; u_long phys; char* pPacket; int len; DRV_LOG (DRV_DEBUG_POLL_RX, "PRX b\n", 1, 2, 3, 4, 5, 6); /* Read the device status register */ stat = ln7990Csr0Read (pDrvCtrl); /* Check for errors */ if (stat & (lncsr_BABL | lncsr_MISS | lncsr_MERR)) { ++pDrvCtrl->csr0Errs; DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad error\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); /* restart chip on fatal error */ if (stat & lncsr_MERR) /* memory error */ { END_FLAGS_CLR (&pDrvCtrl->end, (IFF_UP | IFF_RUNNING)); DRV_LOG (DRV_DEBUG_POLL_RX, "PRX restart\n", 1, 2, 3, 4, 5, 6); ln7990Restart (pDrvCtrl); return (EAGAIN); } } /* * clear receive interrupts, and clear any errors that may be set. */ ln7990CsrWrite (pDrvCtrl, 0, ((stat & (lncsr_BABL|lncsr_CERR|lncsr_MISS|lncsr_MERR| lncsr_RINT)))); /* Packet must be checked for errors. */ pRmd = ln7990FullRMDGet (pDrvCtrl); if (pRmd == NULL) { DRV_LOG (DRV_DEBUG_POLL_RX, "PRX no rmd\n", 1, 2, 3, 4, 5, 6); return (EAGAIN); } if (LN_RMD_ERR (pRmd)) { END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad rmd\n", 1, 2, 3, 4, 5, 6); goto cleanRXD; } END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); len = LN_PKT_LEN_GET (pRmd); /* get packet length */ /* Get pointer to packet */ LN_RMD_TO_ADDR (pDrvCtrl->memBase, pRmd, phys); pPacket = (char *) LN_CACHE_PHYS_TO_VIRT (phys); LN_CACHE_INVALIDATE (pPacket, len); /* make the packet coherent */ /* Upper layer provides the buffer. */ if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT))) { DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad mblk len:%d flags:%d\n", pMblk->mBlkHdr.mLen, pMblk->mBlkHdr.mFlags, 3, 4, 5, 6); return (EAGAIN); } pMblk->mBlkHdr.mData += pDrvCtrl->offset; bcopy (pPacket, pMblk->mBlkHdr.mData, len); pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len; /* Done with descriptor, clean up and give it to the device. */ cleanRXD: LN_CLEAN_RXD (pRmd); /* Flush the write pipe */ CACHE_PIPE_FLUSH (); /* Advance our management index */ pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1); DRV_LOG (DRV_DEBUG_POLL_RX, "PRX ok\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* ln7990PollSend - routine to send a packet in polled mode.** This routine is called by a user to try and send a packet on the* device.*/LOCAL STATUS ln7990PollSend ( LN7990END_DEVICE* pDrvCtrl, M_BLK_ID pMblk ) { ln_tmd* pTmd; void* pTemp; int len; int oldLevel; u_short stat; char* pBuf = NULL; char* pOrig = NULL; DRV_LOG (DRV_DEBUG_POLL_TX, "PTX b\n", 1, 2, 3, 4, 5, 6); /* See if next TXD is available */ pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndex; LN_CACHE_INVALIDATE (pTmd, TMD_SIZ); if ((pTmd->tbuf_stat & lntmd1_OWN) || (((pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1)) == pDrvCtrl->tmdIndexC)) { DRV_LOG (DRV_DEBUG_POLL_TX, "Out of tmds.\n", 1, 2, 3, 4, 5, 6); if (!pDrvCtrl->txCleaning) netJobAdd ((FUNCPTR)ln7990ScrubTRing, (int) pDrvCtrl, 0, 0, 0, 0); return (EAGAIN); } /* * If we don't have alignment issues then we can transmit * directly from the M_BLK otherwise we have to copy. */ if ((pDrvCtrl->offset == 0) && (pMblk->mBlkHdr.mNext == NULL)) { len = max (ETHERSMALL, pMblk->m_len); LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pMblk->m_data); DRV_LOG (DRV_DEBUG_POLL_TX, "offset == 0.\n", 1, 2, 3, 4, 5, 6); } else { DRV_LOG (DRV_DEBUG_POLL_TX, "offset != 0.\n", 1, 2, 3, 4, 5, 6); pOrig = pBuf = netClusterGet(pDrvCtrl->end.pNetPool,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -