📄 mbcend.c
字号:
pBd = pDrvCtrl->rxBdBase; for (counter = pDrvCtrl->rxBdNum; counter; counter--, pBd++) { char * pBuf; if (pBd->dataPointer != NULL) netClFree (pDrvCtrl->end.pNetPool, (pBd->dataPointer - pDrvCtrl->offset)); pBuf = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId); if (pBuf == NULL) { DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_ERROR, "Could not get a buffer\n", 1, 2, 3, 4, 5, 6); return (ERROR); } pBd->statusMode = (MBC_RXBD_E | MBC_RXBD_I); pBd->dataPointer = pBuf + pDrvCtrl->offset; } pBd--; pBd->statusMode |= MBC_RXBD_W; /* set the interrupt vector number */ SYS_OUT_SHORT (pDrvCtrl, MBC_IVEC, pDrvCtrl->ivec); /* set BD size and other DMA parameters */ regValue = pDrvCtrl->dmaParms | (pDrvCtrl->bdSize << MBC_EDMA_BDS_SHFT); SYS_OUT_SHORT (pDrvCtrl, MBC_EDMA, regValue); /* * set the operating mode to, no internal loopback, no full duplex, and * no hearbeat control. */ SYS_OUT_SHORT (pDrvCtrl, MBC_ECFG, 0); /* * set address control to, no hash enable, no index enable, no multicast, * no physical address rejection. */ SYS_OUT_SHORT (pDrvCtrl, MBC_AR, 0x00); /* set max receive frame size */ SYS_OUT_SHORT (pDrvCtrl, MBC_EMRBLR, FRAME_MAX); return (OK); }/******************************************************************************** mbcDeviceRestart - restart transmits** This routine re-resets the Ethernet device. Since on a transmit lock* up, the transmitter can be restarted only by resetting the device, this* routine resets, and reinitializes the device. The device reset counter will* be updated on each reset.** RETURNS: N/A** SEE ALSO: mbcInt(), mbcSend(), mbcPacketGet()** NOMANUAL*/LOCAL void mbcDeviceRestart ( MBC_DEVICE * pDrvCtrl ) { mbcReset (pDrvCtrl); mbcInit (pDrvCtrl); }/******************************************************************************** mbcConfig - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** RETURNS: N/A.** NOMANUAL*/LOCAL void mbcConfig ( MBC_DEVICE * pDrvCtrl /* device to be re-configured */ ) { int i; int numMulti; /* Number of multicast addresses */ UINT16 regValue; /* Determine the number of multicast addresses */ numMulti = END_MULTI_LST_CNT (&pDrvCtrl->end); DRV_LOG (DRV_DEBUG_LOAD, "%s%d: mbcConfig: %d multicast addresses\n", (int) DEV_NAME, pDrvCtrl->unit, numMulti, 4, 5, 6); /* install the ethernet address */ bcopy ((char *) pDrvCtrl->enetAddr, (char *) (pDrvCtrl->memAddr + MBC_ARTAB), ENET_ADDR_SIZE); /* * Setup address control w/o multicasting enabled, and write * the entire address arrray. */ regValue = MBC_AR_MULTI_00; if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) regValue |= MBC_AR_PROM; SYS_OUT_SHORT (pDrvCtrl, MBC_AR, regValue); for (i = 1; i < MBC_ARTAB_SIZE; i++) { SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + (i * 8), ~0); SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + (i * 8) + 2, ~0); SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + (i * 8) + 4, ~0); } /* Now install the multicast addresses or filter */ if ((numMulti > 0) && (numMulti <= MBC_ARTAB_SIZE-1)) { ETHER_MULTI * pCurr; /* Install the multicast addresses directly in the table */ for (i = 1, pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end); pCurr != NULL; pCurr = END_MULTI_LST_NEXT(pCurr), ++i) { bcopy ((char *) &pCurr->addr, (char *) (pDrvCtrl->memAddr + MBC_ARTAB + i*8), ENET_ADDR_SIZE); } } else if (numMulti > MBC_ARTAB_SIZE-1) { /* Setup the multicast filter */ mbcAddrFilterSet (pDrvCtrl); DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_MULTI, "Multicast Filter 0-3 %02x:%02x:%02x:%02x\n", pDrvCtrl->mcastFilter[0], pDrvCtrl->mcastFilter[1], pDrvCtrl->mcastFilter[2], pDrvCtrl->mcastFilter[3], 0, 0); DRV_LOG (DRV_DEBUG_LOAD | DRV_DEBUG_MULTI, "Multicast Filter 4-7 %02x:%02x:%02x:%02x\n", pDrvCtrl->mcastFilter[4], pDrvCtrl->mcastFilter[5], pDrvCtrl->mcastFilter[6], pDrvCtrl->mcastFilter[7], 0, 0); /* Write out multicast filter */ SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + 0x01f0, (pDrvCtrl->mcastFilter[0] << 8) | pDrvCtrl->mcastFilter[1]); SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + 0x01f2, (pDrvCtrl->mcastFilter[2] << 8) | pDrvCtrl->mcastFilter[3]); SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + 0x01f8, (pDrvCtrl->mcastFilter[4] << 8) | pDrvCtrl->mcastFilter[5]); SYS_OUT_SHORT (pDrvCtrl, MBC_ARTAB + 0x01fa, (pDrvCtrl->mcastFilter[6] << 8) | pDrvCtrl->mcastFilter[7]); /* Now enable multicast addressing */ SYS_IN_SHORT (pDrvCtrl, MBC_AR, ®Value); regValue |= MBC_AR_HASH; SYS_OUT_SHORT (pDrvCtrl, MBC_AR, regValue); } }/******************************************************************************** mbcStart - start the device** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR** NOMANUAL*/LOCAL STATUS mbcStart ( void * pObj /* device ID */ ) { STATUS result; MBC_DEVICE * pDrvCtrl = pObj; /* device to be started */ DRV_LOG (DRV_DEBUG_LOAD, "%s%d: mbcStart\n", (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6); SYS_INT_CONNECT (pDrvCtrl, mbcInt, (int)pDrvCtrl, &result); if (result == ERROR) return (ERROR); DRV_LOG (DRV_DEBUG_LOAD, "Interrupt connected.\n", 1, 2, 3, 4, 5, 6); /* enable interrupts - clear events and set mask */ SYS_OUT_SHORT (pDrvCtrl, MBC_IEVNT, 0xffff); SYS_OUT_SHORT (pDrvCtrl, MBC_IMASK, MBC_IMASK_RXF | MBC_IMASK_EBE); /* enable the device */ SYS_UPDATE_SHORT (pDrvCtrl, MBC_ECNTL, MBC_ECNTL_ENBL); DRV_LOG (DRV_DEBUG_LOAD, "interrupt enabled.\n", 1, 2, 3, 4, 5, 6); return (OK); }/******************************************************************************** mbcInt - handle controller interrupt** This routine is called at interrupt level in response to an interrupt from* the controller.** RETURNS: N/A.*/LOCAL void mbcInt ( MBC_DEVICE * pDrvCtrl /* interrupting device */ ) { UINT16 mask; UINT16 events; /* identify and acknowledge all interrupt events */ SYS_IN_SHORT (pDrvCtrl, MBC_IEVNT, &events); SYS_IN_SHORT (pDrvCtrl, MBC_IMASK, &mask); events = (events & (mask | MBC_IMASK_BSY)); SYS_OUT_SHORT (pDrvCtrl, MBC_IEVNT, events); DRV_LOG (DRV_DEBUG_INT, "%s%d: mbcInt events=%04x mask=%04x\n", (int) DEV_NAME, pDrvCtrl->unit, events, mask, 0, 0); /* handle receive events */ if (events & MBC_IEVNT_RXF) { if (pDrvCtrl->rxHandling == FALSE) { pDrvCtrl->rxHandling = TRUE; netJobAdd ((FUNCPTR)mbcHandleRcvInt, (int)pDrvCtrl, 0, 0, 0, 0); } } /* handle transmitter events - BD full condition -> ever happen ? */ if (events & MBC_IEVNT_TXF) { DRV_LOG (DRV_DEBUG_INT | DRV_DEBUG_ERROR, "%s%d: mbcInt: transmit full\n", (int) DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); wdCancel (pDrvCtrl->wdId); if (pDrvCtrl->txBlocked) /* cause a restart */ { netJobAdd ((FUNCPTR)muxTxRestart, (int) &pDrvCtrl->end, 0, 0, 0, 0); pDrvCtrl->txBlocked = FALSE; } SYS_RESET_SHORT (pDrvCtrl, MBC_IMASK, MBC_IEVNT_TXF); } /* * check for input busy condition, we don't enable this interrupt * but we check for it with each interrupt. */ if (events & MBC_IEVNT_BSY) { DRV_LOG (DRV_DEBUG_INT | DRV_DEBUG_ERROR, "%s%d: mbcInt: input busy\n", (int) DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); /* count discarded frames as errors */ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); } /* restart the transmitter on a ethernet bus error */ if (events & MBC_IEVNT_EBE) { DRV_LOG (DRV_DEBUG_INT | DRV_DEBUG_ERROR, "%s%d: mbcInt: ethernet bus error\n", (int) DEV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); netJobAdd ((FUNCPTR)mbcDeviceRestart, (int) pDrvCtrl, 0, 0, 0, 0); } if (!pDrvCtrl->txCleaning) { pDrvCtrl->txCleaning = TRUE; netJobAdd ((FUNCPTR)mbcScrubTRing, (int) pDrvCtrl, 0, 0, 0, 0); } /* ignore and reset all other events */ SYS_OUT_SHORT (pDrvCtrl, MBC_IEVNT, ~mask); }/******************************************************************************** mbcScrubTRing - clean the transmit ring** Cleans the transmit ring.** RETURNS: N/A** NOMANUAL*/LOCAL void mbcScrubTRing ( MBC_DEVICE * pDrvCtrl ) { int oldLevel; volatile MBC_BD * pTxBd; pDrvCtrl->txCleaning = TRUE; pTxBd = &pDrvCtrl->txBdBase [pDrvCtrl->txClNext]; while (pTxBd->dataPointer != NULL) { /* If the buffer is still owned by MBC, don't touch it */ if (pTxBd->statusMode & MBC_TXBD_R) break; oldLevel = intLock (); if (pDrvCtrl->freeRtn[pDrvCtrl->txClNext] != NULL) { pDrvCtrl->freeRtn[pDrvCtrl->txClNext] (pDrvCtrl->freeData[pDrvCtrl->txClNext].arg1, pDrvCtrl->freeData[pDrvCtrl->txClNext].arg2); pDrvCtrl->freeRtn[pDrvCtrl->txClNext] = NULL; pDrvCtrl->freeData[pDrvCtrl->txClNext].arg1 = NULL; pDrvCtrl->freeData[pDrvCtrl->txClNext].arg2 = NULL; } pTxBd->dataPointer = NULL; pTxBd->statusMode &= ~MBC_TXBD_ERRS; /* now bump the disposal index pointer around the ring */ pDrvCtrl->txClNext = (pDrvCtrl->txClNext + 1) % pDrvCtrl->txBdNum; pTxBd = &pDrvCtrl->txBdBase [pDrvCtrl->txClNext]; intUnlock (oldLevel); } pDrvCtrl->txCleaning = FALSE; }/******************************************************************************** mbcSend - 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.** RETURNS: OK or ERROR.*/LOCAL STATUS mbcSend ( void * pObj, /* device ptr */ M_BLK_ID pMblk /* data to send */ ) { int len; char * pBuf; char * pOrig; int oldLevel; MBC_DEVICE * pDrvCtrl = pObj; volatile MBC_BD * pTxBd; DRV_LOG (DRV_DEBUG_TX, "%s%d: mbcSend txBlocked=%d txCleaning=%d\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->txBlocked, pDrvCtrl->txCleaning, 5, 6); /* * Obtain exclusive access to transmitter. This is necessary because * we might have more than one stack transmitting at once. */ if (!(pDrvCtrl->flags & MBC_POLLING)) END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER); /* check if a transmit buffer descriptor is available */ pTxBd = &pDrvCtrl->txBdBase [pDrvCtrl->txBdNext]; if (pTxBd->statusMode & MBC_TXBD_R) { DRV_LOG (DRV_DEBUG_TX | DRV_DEBUG_ERROR, "%s%d: mbcSend: #%d still ready\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->txBdNext, 4, 5, 6); wdStart (pDrvCtrl->wdId, WD_TIMEOUT, (FUNCPTR) mbcDeviceRestart, (int) pDrvCtrl); pDrvCtrl->txBlocked = TRUE; SYS_UPDATE_SHORT (pDrvCtrl, MBC_IMASK, MBC_IEVNT_TXF); if (!(pDrvCtrl->flags & MBC_POLLING)) END_TX_SEM_GIVE (&pDrvCtrl->end); return (END_ERR_BLOCK); } if (pTxBd->dataPointer) { /* cleaning still needed, queue cleaning task */ DRV_LOG (DRV_DEBUG_TX | DRV_DEBUG_ERROR, "%s%d: mbcSend: #%d needs cleaning (cleaning=%d)\n", (int) DEV_NAME, pDrvCtrl->unit, pDrvCtrl->txBdNext, pDrvCtrl->txCleaning, 5, 6); pDrvCtrl->txBlocked = TRUE; if (pDrvCtrl->txCleaning == FALSE) { pDrvCtrl->txCleaning = TRUE; netJobAdd ((FUNCPTR)mbcScrubTRing, (int) pDrvCtrl, 0, 0, 0, 0); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -