📄 if_mbc.c
字号:
MBC_REG_WRITE (pDrvCtrl->ether.pDevBase, MBC_IEVNT, MBC_IEVNT_GRA); MBC_REG_UPDATE (pDrvCtrl->ether.pDevBase, MBC_ECNTL, MBC_ECNTL_GTS); /* wait for graceful stop to register */ while ((counter--) && (! (MBC_IEVNT_READ (pDrvCtrl->ether.pDevBase) & MBC_IEVNT_GRA))); /* disable the receiver and transmitter. */ MBC_REG_RESET (pDrvCtrl->ether.pDevBase, MBC_ECNTL, MBC_ECNTL_ENBL); /* mark the driver as down */ pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING); /* mark the driver as no longer initialized */ pDrvCtrl->initialized = FALSE; pDrvCtrl->resetCounter++; }/********************************************************************************* mbcIntr - network interface interrupt handler** This routine is called at interrupt level. It handles work that * requires minimal processing. Interrupt processing that is more * extensive gets handled at task level. The network task, netTask(), is * provided for this function. Routines get added to the netTask() work * queue via the netJobAdd() command.** RETURNS: N/A*/void mbcIntr ( int unit /* unit number */ ) { DRV_CTRL * pDrvCtrl = & drvCtrl[unit]; volatile char * pDevBase = pDrvCtrl->ether.pDevBase; int events; /* identify and acknowledge all interrupt events */ events = (MBC_IEVNT_READ (pDevBase) & (MBC_IMASK_READ (pDevBase) | MBC_IMASK_BSY)); MBC_INTR_ACK (pDevBase, events); /* check for spurious interrupt -> driver initialized ? */ if (! pDrvCtrl->initialized) { MBC_INTR_ACK (pDevBase, 0xffff); return; } /* handle receive events */ if (events & MBC_IEVNT_RXF) { (void) netJobAdd ((FUNCPTR) mbcHandleInt, (int) pDrvCtrl, 0,0,0,0); /* turn off receive interrupts - mbcHandleInt turns back on */ MBC_INTR_DISABLE (pDevBase, MBC_IEVNT_RXF); } /* handle transmitter events - BD full condition -> ever happen ? */ if (events & MBC_IEVNT_TXF) { wdCancel (pDrvCtrl->wdId);#ifdef BSD43_DRIVER (void) netJobAdd ((FUNCPTR) mbcStartOutput, unit, 0, 0, 0, 0); #else (void) netJobAdd ((FUNCPTR) mbcStartOutput, (int)pDrvCtrl, 0, 0, 0, 0); #endif MBC_INTR_DISABLE (pDevBase, 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) { /* count discarded frames as errors */ pDrvCtrl->idr.ac_if.if_ierrors += 1; } /* restart the transmitter on a ethernet bus error */ if (events & MBC_IEVNT_EBE) { (void) netJobAdd ((FUNCPTR) mbcDeviceRestart, unit, 0,0,0,0); MBC_INTR_ACK (pDevBase, MBC_IEVNT_EBE); } /* ignore and reset all other events */ MBC_INTR_ACK (pDevBase, ~(MBC_IMASK_READ(pDevBase))); return; }/********************************************************************************* mbcHandleInt - task-level interrupt handler** This is the task-level interrupt handler, which is called from * netTask(). mbcHandleInt() gets input frames from the device and then calls * mbcRecv() to process each frame. mbcRecv() only gets called if no error* stats were reported in the buffer descriptor. Data chaining is not* supported.** This routine should be called with MBC receive interrupts masked so that* more netJobAdds of this routine are not performed by mbcIntr().* Receive interrupts are turned back on by this routine before exiting.** RETURNS: N/A*/LOCAL void mbcHandleInt ( DRV_CTRL * pDrvCtrl /* pointer to DRV_CTRL structure */ ) { volatile char * pDevBase = pDrvCtrl->ether.pDevBase; MBC_BD * pRxBd; pRxBd = & pDrvCtrl->ether.rxBdBase[pDrvCtrl->ether.rxBdNext]; while (!(pRxBd->statusMode & MBC_RXBD_E)) { /* data chaining is not supported - check all error conditions */ if (((pRxBd->statusMode & (MBC_RXBD_F | MBC_RXBD_L)) == (MBC_RXBD_F | MBC_RXBD_L)) && !(pRxBd->statusMode & (MBC_RXBD_CL | MBC_RXBD_OV | MBC_RXBD_CR | MBC_RXBD_SH | MBC_RXBD_NO | MBC_RXBD_LG))) mbcRecv (pDrvCtrl, pRxBd); else { pDrvCtrl->idr.ac_if.if_ierrors++; /* * Fix for errata #9 -- Device Errata, Feb 20, 1997. * Ethernet frames may be incorrectly received after a rx FIFO * overflow. */ if ((pRxBd->statusMode & MBC_RXBD_L) && ! (pRxBd->statusMode & MBC_RXBD_F)) { mbcDeviceRestart (pDrvCtrl->ether.mbcNum); return; } } /* reset buffer descriptor as empty */ pRxBd->statusMode |= MBC_RXBD_E; /* incr BD count */ pDrvCtrl->ether.rxBdNext = (pDrvCtrl->ether.rxBdNext + 1) % pDrvCtrl->ether.rxBdNum; pRxBd = & pDrvCtrl->ether.rxBdBase[pDrvCtrl->ether.rxBdNext]; /* clear Rx events */ MBC_INTR_ACK (pDevBase, MBC_IEVNT_RXF); } /* re-enable Rx interrupts */ MBC_INTR_ENABLE (pDevBase, MBC_IEVNT_RXF); }/********************************************************************************* mbcRecv - process an input frame** This routine processes an input frame, then passes it up to the higher * level in a form it expects. Buffer loaning, promiscuous mode, and* etherInputHookRtns are all supported. Trailer protocols is not supported.** RETURNS: N/A*/LOCAL void mbcRecv ( DRV_CTRL * pDrvCtrl, /* pointer to DRV_CTRL structure */ MBC_BD * pRxBd /* receive buffer descriptor */ ) { MBUF * pMbuf = NULL; /* MBUF pointer */ UINT8 * pData; int length;#ifdef BSD43_DRIVER UINT16 type;#else struct ether_header * pEh;#endif /* bump input packet counter */ pDrvCtrl->idr.ac_if.if_ipackets++; /* call hook if one is connected */ if ((etherInputHookRtn != NULL) && ((*etherInputHookRtn) (& pDrvCtrl->idr.ac_if, pRxBd->dataPointer, pRxBd->dataLength) != 0)) return; /* check the M bit, to filter frames not destined for this station. */ if (pRxBd->statusMode & MBC_RXBD_M) return; /* adjust length to data only */ length = pRxBd->dataLength - SIZEOF_ETHERHEADER; if (length <= 0) { pDrvCtrl->idr.ac_if.if_ierrors++; return; } /* point to data */ pData = pRxBd->dataPointer + SIZEOF_ETHERHEADER;#ifdef BSD43_DRIVER /* save type - build_cluster trashes the type field */ type = ((ETH_HDR *) pRxBd->dataPointer)->ether_type;#else /* BSD 4.4 uses Ethernet header */ pEh = (struct ether_header *) pRxBd->dataPointer;#endif /* OK to loan out buffer ? -> build a mbuf cluster */ if ((pDrvCtrl->nLoan > 0) && (USE_CLUSTER (length))) pMbuf = build_cluster (pData, length, & pDrvCtrl->idr, MC_MBC, pDrvCtrl->pRefCnt[(pDrvCtrl->nLoan - 1)], mbcLoanFree, (int) pDrvCtrl, (int) pRxBd->dataPointer, (int) pDrvCtrl->pRefCnt[(pDrvCtrl->nLoan - 1)]); /* if buffer was successfully turned into mbuf cluster */ if (pMbuf != NULL) pRxBd->dataPointer = pDrvCtrl->lPool[--pDrvCtrl->nLoan]; else { /* else do same ol' copy to mbuf */ pMbuf = copy_to_mbufs (pData, length, 0, & pDrvCtrl->idr.ac_if); if (pMbuf == NULL) { pDrvCtrl->idr.ac_if.if_ierrors++; return; } } /* send up to protocol */#ifdef BSD43_DRIVER do_protocol_with_type (type, pMbuf, & pDrvCtrl->idr, length);#else do_protocol (pEh, pMbuf, & pDrvCtrl->idr, length);#endif }/********************************************************************************* mbcDeviceRestart - restart transmits** This routine re-resets the Ethernet device. It is called by the watchdog* timer which expires when transmit BDs are all full, and a transmit frame* interrupt does not occur with in 20 clock ticks. 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, and can be examined with mbcShow().** RETURNS: N/A** SEE ALSO: mbcIntr(), mbcShow(), mbcStartOutput()*/LOCAL void mbcDeviceRestart ( int unit ) { mbcReset (unit); mbcInit (unit); }/********************************************************************************* mbcLoanFree - return the given buffer to loaner pool** This routine returns <pRxBuf> to the pool of available loaner buffers.* It also returns <pRef> to the pool of available loaner reference counters,* then zeroes the reference count.** RETURNS: N/A*/LOCAL void mbcLoanFree ( DRV_CTRL * pDrvCtrl, UINT8 * pRxBuf, UINT8 * pRefCnt ) { /* return loaned buffer to pool */ pDrvCtrl->lPool[pDrvCtrl->nLoan] = pRxBuf; /* return loaned reference count to pool */ pDrvCtrl->pRefCnt[pDrvCtrl->nLoan++] = pRefCnt; /* reset reference count - should have been done from above, but... */ *pRefCnt = 0; }/********************************************************************************* mbcShow - displays the internal state of an Ethernet unit** This routine prints the following information about the device unit,* .iP* - txBdNum, the number of transmit buffer descriptors * .iP* - rxBdNum, the number of receive buffer descriptors* .iP* - txBdNext, the next transmit buffer descriptor index* .iP* - rxBdNext, the next receive buffer descriptor index* .iP* - all the Ethernet configuration registers* .LP** RETURNS: N/A.** NOMANUAL*/void mbcShow ( int unit /* unit number */ ) { DRV_CTRL * pDrvCtrl; volatile char * pDevBase; if (unit < 0 || unit >= MAX_UNITS) return; pDrvCtrl = & drvCtrl[unit]; pDevBase = pDrvCtrl->ether.pDevBase; printf ("mbc (unit %d):\n", unit); printf (" 0x%x Resets\n", pDrvCtrl->resetCounter); printf (" %d transmit BDs, %d receive BDs, %d loaner buffers\n", pDrvCtrl->ether.txBdNum, pDrvCtrl->ether.rxBdNum, pDrvCtrl->nLoan); printf (" Next transmit BD is %d, Next receive BD is %d\n", pDrvCtrl->ether.txBdNext, pDrvCtrl->ether.rxBdNext); printf (" Registers: ectrl (0x%x), edma (0x%x), mrbl (0x%x)\n", MBC_REG_READ (pDevBase, MBC_ECNTL), MBC_REG_READ (pDevBase, MBC_EDMA), MBC_REG_READ (pDevBase, MBC_EMRBLR)); printf (" ivec (0x%x), ievent (0x%x), imask (0x%x)\n", MBC_REG_READ (pDevBase, MBC_IVEC), MBC_REG_READ (pDevBase, MBC_IEVNT), MBC_REG_READ (pDevBase, MBC_IMASK)); printf (" ecnfg (0x%x), etest (0x%x), ar(0x%x)\n", MBC_REG_READ (pDevBase, MBC_ECFG), MBC_REG_READ (pDevBase, MBC_TEST), MBC_REG_READ (pDevBase, MBC_AR)); }/********************************************************************************* mbcBdShow - display buffer descriptors** This routine displays the flags, len, and the buffer pointer fields of each* buffer descriptor in the requested range. The parameter <start> is the* beginning buffer descriptor, and <count> is number of buffer descriptors to* display.** RETURNS: N/A.** NOMANUAL*/void mbcBdShow ( int unit, /* unit number */ int start, /* starting BD */ int count /* number of BDs */ ) { DRV_CTRL * pDrvCtrl; volatile MBC_BD * pBd; /* buffer descriptor pointer */ if (unit < 0 || unit >= MAX_UNITS) return; pDrvCtrl = & drvCtrl[unit]; pBd = pDrvCtrl->ether.txBdBase; while (start < 128 && count) { printf ("BD %d: flags=0x%x, len=0x%x, pBuf=0x%xn", start, pBd[start].statusMode, pBd[start].dataLength, (UINT32) pBd[start].dataPointer); start++; count--; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -