📄 el3c90xend.c
字号:
return (OK); }/********************************************************************************* el3c90xPollRcv - 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 el3c90xPollRcv ( void * pEnd, /* device pointer */ M_BLK_ID pMblk /* pointer to the mBlk chain */ ) { EL_SIMPLE_DESC_CHAIN * pRxUpd; EL3C90X_DEVICE * pDrvCtrl; M_BLK_ID pMblkTemp; /* pointer to the mBlk */ int len; DRV_LOG (DRV_DEBUG_POLL_RX, "PRX b\n", 1, 2, 3, 4, 5, 6); VOID_TO_DRVCTRL (pEnd, pDrvCtrl); el3c90xRxUnStall (pDrvCtrl); /* get the next upload descriptor */ if ((pRxUpd = el3c90xNextUpdFetch (pDrvCtrl)) == NULL) { DRV_LOG (DRV_DEBUG_POLL_RX, "PRX no upd\n", 1, 2, 3, 4, 5, 6); return (EAGAIN); } /* get the mBlk associated with the upd */ if ((pMblkTemp = el3c90xNextPktFetch (pDrvCtrl, pRxUpd)) == NULL) return (EAGAIN); /* copy the data into the given buffer */ len = netMblkToBufCopy (pMblkTemp, pMblk->mBlkHdr.mData, NULL); netMblkClChainFree (pMblkTemp); 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.mLen = len; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len; DRV_LOG (DRV_DEBUG_POLL_RX, "PRX ok\n", 1, 2, 3, 4, 5, 6); return (OK); }/********************************************************************************* el3c90xInit - initialize the device** This routine initializes device and enables the device interrupts. It* initializes the descriptor rings** RETURNS: N/A*/LOCAL void el3c90xInit ( EL3C90X_DEVICE * pDrvCtrl /* pointer to the device control structure */ ) { int ix; UINT16 rxFilt = 0; UINT16 phyBMCR = 0; int flags; /* * hack for the 3c905B: the built-in autoneg logic's state * gets reset by el3c90xInit() when we don't want it to. Try * to preserve it. (For 3c905 cards with real external PHYs, * the BMCR register doesn't change, but this doesn't hurt.) */ if (pDrvCtrl->pPhyDevType != NULL) phyBMCR = el3c90xPhyRegRead(pDrvCtrl, PHY_BMCR); /* cancel pending I/O and free all RX/TX buffers. */ el3c90xDevStop(pDrvCtrl); el3c90xWait(pDrvCtrl); /* get the MAC address */ for (ix = 0; ix < EA_SIZE; ix++) { el3c90xCsrWriteByte (pDrvCtrl, EL_W2_STATION_ADDR_LO + ix, pDrvCtrl->enetAddr [ix], EL_WIN_2); } /* clear the station mask */ for (ix = 0; ix < 3; ix++) el3c90xCsrWriteWord (pDrvCtrl, EL_W2_STATION_MASK_LO + (ix * 2), 0, EL_WIN_2); /* reset TX and RX */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_RX_RESET, NONE); el3c90xWait(pDrvCtrl); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_RESET, NONE); el3c90xWait(pDrvCtrl); /* init circular upload descriptor list */ if (el3c90xUpdInit(pDrvCtrl) == ENOBUFS) { DRV_LOG (DRV_DEBUG_LOAD, "elPci%d: initialization failed: no " "memory for rx buffers\n", pDrvCtrl->unit, 2, 3, 4, 5, 6); el3c90xDevStop(pDrvCtrl); return; } /* init download descriptors list */ el3c90xDndInit(pDrvCtrl); /* * set the TX freethresh value. * note that this has no effect on 3c905B "cyclone" * cards but is required for 3c900/3c905 "boomerang" * cards in order to enable the download engine. */ el3c90xCsrWriteByte (pDrvCtrl, EL_TX_FREETHRESH, (EL3C90X_BUFSIZ >> 8), NONE); /* * If this is a 3c905B, also set the tx reclaim threshold. * This helps cut down on the number of tx reclaim errors * that could happen on a busy network. The chip multiplies * the register value by 16 to obtain the actual threshold * in bytes, so we divide by 16 when setting the value here. * The existing threshold value can be examined by reading * the register at offset 9 in window 5. */ if (pDrvCtrl->devType == EL_TYPE_905B) { el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_SET_TX_RECLAIM | (EL3C90X_BUFSIZ >> 4)), NONE); } /* set RX filter bits. */ rxFilt = el3c90xCsrReadByte (pDrvCtrl, EL_W5_RX_FILTER, EL_WIN_5); /* set the individual bit to receive frames for this host only. */ rxFilt |= EL_RXFILTER_INDIVIDUAL; flags = END_FLAGS_GET (&pDrvCtrl->endObj); /* if we want promiscuous mode, set the allframes bit. */ if (flags & IFF_PROMISC) { rxFilt |= EL_RXFILTER_ALLFRAMES; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); } else { rxFilt &= ~EL_RXFILTER_ALLFRAMES; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); } /* set capture broadcast bit to capture broadcast frames. */ if (flags & IFF_BROADCAST) { rxFilt |= EL_RXFILTER_BROADCAST; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); } else { rxFilt &= ~EL_RXFILTER_BROADCAST; el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_FILT | rxFilt), NONE); } /* set the multicast filter etc */ el3c90xMcastConfig (pDrvCtrl); /* * load the upload descriptor pointer and start the upload engine * Note that we have to do this after any RX resets have completed * since the uplist register is cleared by a reset. */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_UP_STALL, NONE); el3c90xWait(pDrvCtrl); el3c90xCsrWriteLong (pDrvCtrl, EL_UPLIST_PTR, (UINT32) EL3C90X_CACHE_VIRT_TO_PHYS (&pDrvCtrl->pDescBlk->rxDescs[0]), NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_UP_UNSTALL, NONE); /* * if the coax transceiver is on, make sure to enable the DC-DC converter. */ if (pDrvCtrl->xCvr == EL_XCVR_COAX) el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_COAX_START, NONE); else el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_COAX_STOP, NONE); /* Clear out the stats counters. */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_STATS_DISABLE, NONE); el3c90xStatUpdate(pDrvCtrl); el3c90xCsrWriteWord (pDrvCtrl, EL_W4_NET_DIAG, EL_NETDIAG_UPPER_BYTES_ENABLE, EL_WIN_4); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_STATS_ENABLE, NONE); /* enable device interrupts */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_INTR_ACK|0xFF, NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_STAT_ENB|EL_INTRS, NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_INTR_ENB|EL_INTRS, NONE); /* Set the RX early threshold */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, (EL_CMD_RX_SET_THRESH | (EL3C90X_BUFSIZ >>2)), NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_DMACTL, EL_DMACTL_UP_RX_EARLY, NONE); /* Enable receiver and transmitter. */ el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_RX_ENABLE, NONE); el3c90xCsrWriteWord (pDrvCtrl, EL_COMMAND, EL_CMD_TX_ENABLE, NONE); /* Restore state of BMCR */ if (pDrvCtrl->pPhyDevType != NULL) el3c90xPhyRegWrite(pDrvCtrl, PHY_BMCR, phyBMCR); return; }/********************************************************************************* el3c90xMemInit - initialize memory for the device** This function initiailizes memory for the device** RETURNS: OK or ERROR**/LOCAL STATUS el3c90xMemInit ( EL3C90X_DEVICE * pDrvCtrl /* device to be initialized */ ) { int memSize = 0; memSize += (sizeof(EL_DESC_BLK) + 16); if (pDrvCtrl->bufMtplr == NONE) pDrvCtrl->bufMtplr = 2; else if (pDrvCtrl->bufMtplr <= 0) printf ( "elPci: invalid buffer multiplier\n"); pDrvCtrl->clDesc.clNum = (EL_UPD_CNT + EL_DND_CNT) * pDrvCtrl->bufMtplr; pDrvCtrl->mClCfg.clBlkNum = pDrvCtrl->clDesc.clNum; pDrvCtrl->mClCfg.mBlkNum = pDrvCtrl->mClCfg.clBlkNum * 2; /* total memory size for mBlks and clBlks */ pDrvCtrl->mClCfg.memSize = (pDrvCtrl->mClCfg.mBlkNum * (MSIZE + sizeof (long))) + (pDrvCtrl->mClCfg.clBlkNum * (CL_BLK_SZ + sizeof (long))); memSize += pDrvCtrl->mClCfg.memSize; /* total memory size for all clusters */ pDrvCtrl->clDesc.clSize = EL3C90X_BUFSIZ; pDrvCtrl->clDesc.memSize = (pDrvCtrl->clDesc.clNum * (pDrvCtrl->clDesc.clSize + 8)) + sizeof(int); memSize += pDrvCtrl->clDesc.memSize; if ((int)pDrvCtrl->memAdrs != NONE) { /* check if the give memory size if enough */ if (pDrvCtrl->memSize < memSize) { printf ( "elPci: memory size too small\n" ); return (ERROR); } pDrvCtrl->pDescMem = (char *)pDrvCtrl->memAdrs; pDrvCtrl->mClCfg.memArea = (char *)((UINT32)(pDrvCtrl->pDescMem) + sizeof(EL_DESC_BLK) + 16); pDrvCtrl->clDesc.memArea = (pDrvCtrl->mClCfg.memArea + pDrvCtrl->mClCfg.memSize); /* assume pool is cache coherent, copy null structure */ pDrvCtrl->cacheFuncs = cacheNullFuncs; DRV_LOG (DRV_DEBUG_LOAD, "Memory checks out\n", 1, 2, 3, 4, 5, 6); } else /* allocate our own memory */ { pDrvCtrl->flags |= EL_MEM_ALLOC_FLAG; if (!CACHE_DMA_IS_WRITE_COHERENT ()) { printf ( "elPci: device requires cache coherent memory\n" ); return (ERROR); } /* allocate memory for upload and download descriptors */ pDrvCtrl->pDescMem = (char *) cacheDmaMalloc (sizeof(EL_DESC_BLK) + 16); if (pDrvCtrl->pDescMem == NULL) { printf ( "elPci: system memory unavailable\n" ); return (ERROR); } /* allocate memory for mBlks and clBlks */ if ((pDrvCtrl->mClCfg.memArea = (char *) memalign (sizeof(long), pDrvCtrl->mClCfg.memSize)) == NULL) { printf ( "elPci: system memory unavailable\n" ); goto elMemInitFail; } /* allocate memory for clusters */ pDrvCtrl->clDesc.memArea = cacheDmaMalloc (pDrvCtrl->clDesc.memSize); if ((int)pDrvCtrl->clDesc.memArea == NULL) { printf ( "elPci: system memory unavailable\n" ); goto elMemInitFail; } /* copy the DMA structure */ pDrvCtrl->cacheFuncs = cacheDmaFuncs; } pDrvCtrl->pDescBlk = (EL_DESC_BLK *)(((int)pDrvCtrl->pDescMem + 0x0f) & ~0x0f); bzero ((char*)pDrvCtrl->pDescBlk, sizeof(EL_DESC_BLK)); /* allocate memory for net pool */ if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL) { printf ( "elPci: system memory unavailable\n" ); goto elMemInitFail; }#ifdef DRV_DEBUG pElXlPool = pDrvCtrl->endObj.pNetPool;#endif /* initialize the device net pool */ if (netPoolInit (pDrvCtrl->endObj.pNetPool, &pDrvCtrl->mClCfg, &pDrvCtrl->clDesc, 1, NULL) == ERROR) { DRV_LOG (DRV_DEBUG_LOAD, "Could not init buffering\n", 1, 2, 3, 4, 5, 6); goto elMemInitFail; } /* Store the cluster pool id as others need it later. */ pDrvCtrl->pClPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool, EL3C90X_BUFSIZ, FALSE); return (OK); elMemInitFail: { if (pDrvCtrl->flags & EL_MEM_ALLOC_FLAG) { /* free the memory allocated for descriptors */ if (pDrvCtrl->pDescMem != NULL) cacheDmaFree (pDrvCtrl->pDescMem); /* Free the memory allocated for mBlks and clBlks */ if (pDrvCtrl->mClCfg.memArea != NULL) free (pDrvCtrl->mClCfg.memArea); /* free the memory allocated for clusters */ if (pDrvCtrl->clDesc.memArea != NULL) cacheDmaFree (pDrvCtrl->clDesc.memArea); } if (pDrvCtrl->endObj.pNetPool != NULL) free (pDrvCtrl->endObj.pNetPool); return (ERROR); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -