📄 ln97xend.c
字号:
{ int level; UINT32 result; level = intLock (); SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRap, PCI_SWAP (reg)); SYS_IN_LONG (pDrvCtrl, pDrvCtrl->pBdp, result); intUnlock (level); return (PCI_SWAP (result) & 0x0000FFFF); }/********************************************************************************* ln97xRestartSetup - setup memory descriptors and turn on chip** This routine initializes all the shared memory structures and turns on* the chip.** RETURNS OK/ERROR*/LOCAL STATUS ln97xRestartSetup ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { int rsize; /* recv ring length */ int tsize; /* xmit ring length */ LN_TMD * pTmd; /* reset the device */ ln97xReset (pDrvCtrl); /* setup Rx buffer descriptors - align on 000 boundary */ rsize = pDrvCtrl->rringLen; /* * setup Tx buffer descriptors - * save unaligned location and align on 000 boundary */ pTmd = pDrvCtrl->pTring; tsize = pDrvCtrl->tringLen; /* setup the initialization block */ pDrvCtrl->ib = (LN_IB *)pDrvCtrl->pShMem; DRV_LOG (DRV_DEBUG_LOAD, "Init block @ 0x%X\n", (int)(pDrvCtrl->ib), 2, 3, 4, 5, 6); bcopy ((char *) END_HADDR(&pDrvCtrl->endObj), pDrvCtrl->ib->lnIBPadr, 6); CACHE_PIPE_FLUSH (); /* point to Rx ring */ LN_ADDR_TO_IB_RMD (pDrvCtrl->pRring, pDrvCtrl->ib, rsize); /* point to Tx ring */ LN_ADDR_TO_IB_TMD (pDrvCtrl->pTring, pDrvCtrl->ib, tsize); DRV_LOG (DRV_DEBUG_LOAD, "Memory setup complete\n", 1, 2, 3, 4, 5, 6); /* reconfigure the device */ ln97xConfig (pDrvCtrl); return (OK); }/********************************************************************************* ln97xRestart - 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.** RETURNS: N/A*/LOCAL void ln97xRestart ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { ln97xReset (pDrvCtrl); ln97xRestartSetup (pDrvCtrl); /* set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST); }/******************************************************************************** ln97xConfig - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** RETURNS: N/A*/LOCAL void ln97xConfig ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { UINT16 stat; void * pTemp; LN_RMD * pRmd; LN_TMD * pTmd; int ix; int timeoutCount = 0; /* Set promiscuous mode if it's asked for. */ if (END_FLAGS_GET (&pDrvCtrl->endObj) & 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 |= 0x00800000; } else { DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode off!\n", 1, 2, 3, 4, 5, 6); } CACHE_PIPE_FLUSH (); ln97xCsrWrite (pDrvCtrl, 0, CSR0_STOP); /* set the stop bit */ /* Set up address filter for multicasting. */ if (END_MULTI_LST_CNT (&pDrvCtrl->endObj) > 0) { ln97xAddrFilterSet (pDrvCtrl); } /* set the bus mode to little endian */ ln97xCsrWrite (pDrvCtrl, 3, pDrvCtrl->csr3B); /* set the Bus Timeout to a long time */ /* This allows other stuff to hog the bus a bit more */ ln97xCsrWrite (pDrvCtrl, 100, BUS_LATENCY_COUNT ); pRmd = pDrvCtrl->pRring; for (ix = 0; ix < pDrvCtrl->rringSize; ix++, pRmd++) { LN_CLEAN_RXD (pRmd); } pDrvCtrl->rmdIndex = 0; pTmd = pDrvCtrl->pTring; for (ix = 0; ix < pDrvCtrl->tringSize; ix++, pTmd++) { pTmd->tBufAddr = 0; /* no message byte count yet */ pTemp = (void *)(TMD1_CNST | TMD1_ENP | TMD1_STP); pTmd->tBufTmd1 = (UINT32) PCI_SWAP (pTemp); 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); pTemp = (void *)(MEM_TO_PCI_PHYS((ULONG)pTemp)); ln97xCsrWrite (pDrvCtrl, CSR(2), (((ULONG)pTemp >> 16) & 0x0000ffff)); ln97xCsrWrite (pDrvCtrl, CSR(1), ((ULONG)pTemp & 0x0000ffff)); ln97xCsrWrite (pDrvCtrl, CSR(0), CSR0_INIT); /* init chip (read IB) */ /* hang until Initialization DONe, ERRor, or timeout */ while (((stat = ln97xCsrRead (pDrvCtrl, 0)) & (CSR0_IDON | CSR0_ERR)) == 0) { if (timeoutCount++ > 0x100) break; taskDelay (2 * timeoutCount); } DRV_LOG (DRV_DEBUG_LOAD, "Timeoutcount %d\n", timeoutCount, 2, 3, 4, 5, 6); /* log chip initialization failure */ if (((stat & CSR0_ERR) == CSR0_ERR) || (timeoutCount >= 0x10000)) { DRV_LOG (DRV_DEBUG_LOAD, "%s: Device initialization failed\n", (int)END_DEV_NAME(&pDrvCtrl->endObj), 0,0,0,0,0); return; } /* Setup LED controls */ ln97xBcrWrite (pDrvCtrl, BCR(4), 0x0090); ln97xBcrWrite (pDrvCtrl, BCR(5), 0x0084); ln97xBcrWrite (pDrvCtrl, BCR(7), 0x0083); if (!(pDrvCtrl->flags & LS_POLLING)) ln97xCsrWrite (pDrvCtrl, 0, CSR0_INTMASK | CSR0_STRT); else ln97xCsrWrite (pDrvCtrl, 0, CSR0_STRT); }/******************************************************************************** ln97xAddrFilterSet - set the address filter for multicast addresses** This routine goes through all of the multicast addresses on the list* of addresses (added with the ln97xAddrAdd() routine) and sets the* device's filter correctly.** RETURNS: N/A*/LOCAL void ln97xAddrFilterSet ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { ETHER_MULTI * pCurr; LN_IB * pIb; UINT8 * pCp; UINT8 byte; UINT32 crc; int len; int count; pIb = pDrvCtrl->ib; LN_ADDRF_CLEAR (pIb); pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->endObj); while (pCurr != NULL) { pCp = (UINT8 *)&pCurr->addr; crc = 0xffffffff; for (len = LN_LA_LEN; --len >= 0;) { byte = *pCp++; for (count = 0; count < LN_LAF_LEN; count++) { if ((byte & 0x01) ^ (crc & 0x01)) { crc >>= 1; crc = crc ^ LN_CRC_POLYNOMIAL; } else { crc >>= 1; } byte >>= 1; } } /* Just want the 6 most significant bits. */ crc = LN_CRC_TO_LAF_IX (crc); /* Turn on the corresponding bit in the filter. */ LN_ADDRF_SET (pIb, crc); pCurr = END_MULTI_LST_NEXT(pCurr); } }/********************************************************************************* ln97xPollReceive - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device. This routine return OK if it is successful in getting the packet** RETURNS: OK or EAGAIN.*/LOCAL STATUS ln97xPollReceive ( LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */ M_BLK_ID pMblk ) { LN_RMD * pRmd; UINT16 stat; 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 = ln97xCsrRead (pDrvCtrl, CSR(0)); /* Check for errors */ if (stat & (CSR0_BABL | CSR0_MISS | CSR0_MERR)) { DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad error\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); /* restart chip on fatal error */ if (stat & CSR0_MERR) /* memory error */ { END_FLAGS_CLR (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); DRV_LOG (DRV_DEBUG_POLL_RX, "PRX restart\n", 1, 2, 3, 4, 5, 6); ln97xRestart (pDrvCtrl); } return (EAGAIN); } /* If no interrupt then return. */ if (!(stat & CSR0_RINT)) { DRV_LOG (DRV_DEBUG_POLL_RX, "PRX no rint\n", 1, 2, 3, 4, 5, 6); return (EAGAIN); } /* * clear receive interrupts, and clear any errors that may be set. */ ln97xCsrWrite (pDrvCtrl, 0, (stat & (CSR0_INTMASK | CSR0_STRT))); /* Packet must be checked for errors. */ pRmd = ln97xFullRMDGet (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->endObj, 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->endObj, MIB2_IN_UCAST, +1); len = LN_PKT_LEN_GET (pRmd); /* get packet length */ /* Get pointer to packet */ LN_RMD_TO_ADDR (pRmd, pPacket); 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); } 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); }/********************************************************************************* ln97xPollSend - 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 or EAGAIN.*/LOCAL STATUS ln97xPollSend ( LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */ M_BLK_ID pMblk ) { LN_TMD * pTmd; void * pTemp; int len; int oldLevel; ULONG ltmd1; UINT16 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 ((
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -