📄 if_nicevb.c
字号:
nicWriteReg (pNic, &pNic->nic_pg1.mar5, 0xff, RPAGE1); nicWriteReg (pNic, &pNic->nic_pg1.mar6, 0xff, RPAGE1); nicWriteReg (pNic, &pNic->nic_pg1.mar7, 0xff, RPAGE1); nicWriteReg (pNic, &pNic->Curr, CURR, RPAGE1); nicWriteCr (pNic, RPAGE0 | ABORT | STA); /* back to page 0 */ nicWriteReg (pNic, &pNic->Tcr, MODE0, RPAGE0); /* Tx normal mode */ }/********************************************************************************* nicPktBufRead - read data from the NIC receive ring buffer** This routine gets exclusive access to the remote DMA, and calls* nicReceive() to get data from the NIC's receive ring buffer.** RETURNS: OK, or ERROR if obtaining the requested bytes encountered an error.*/LOCAL STATUS nicPktBufRead ( DRV_CTRL * pDrvCtrl, UINT32 nicBufAddr, UINT32 len, char * pData ) { STATUS status = OK; /* avoid starting DMA if device is down to to fatal error */ if ((pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) != (IFF_UP | IFF_RUNNING)) return (ERROR); if (semTake (pDrvCtrl->dmaSem, 100) == ERROR) /* get DMA */ { if (_func_logMsg != NULL) _func_logMsg ("nicPktBufRead: can't obtain dmaSem\n",0,0,0,0,0,0); semTake (pDrvCtrl->dmaSem, WAIT_FOREVER); } status = nicReceive (pDrvCtrl, nicBufAddr, pData, len); /* goto ring */ semGive(pDrvCtrl->dmaSem); return (status); }/********************************************************************************* nicWriteCr - write to the NIC command register** RETURNS: N/A.*/LOCAL void nicWriteCr ( NIC_DEVICE *pNic, UINT8 value ) { int level = intLock (); do { pNic->Cr = value; } while (!((*(volatile UINT8 *)NIC_DMA) & ACC_MASK)); intUnlock (level); }/********************************************************************************* nicWriteReg - write to a NIC register** RETURNS: N/A.*/LOCAL void nicWriteReg ( NIC_DEVICE * pNic, volatile UINT8 * pReg, UINT8 value, UINT8 page ) { volatile UINT8 * nicDma = (volatile UINT8 *) NIC_DMA; UINT8 cr; int level = intLock (); do { cr = pNic->Cr; } while (!((*nicDma) & ACC_MASK)); if ((cr & PBMASK) != page) do { pNic->Cr = (cr & 0x3f) | page; } while (!((*nicDma) & ACC_MASK)); do { *pReg = value; } while (!((*nicDma) & ACC_MASK)); intUnlock (level); }/********************************************************************************* nicReadReg - read from a NIC register** RETURNS: the register value.*/LOCAL UINT8 nicReadReg ( NIC_DEVICE * pNic, volatile UINT8 * pReg, char page ) { volatile UINT8 * nicDma = (volatile UINT8 *) NIC_DMA; UINT8 cr; int level = intLock (); do { cr = pNic->Cr; } while (!((*nicDma) & ACC_MASK)); if ((cr & PBMASK) != page) do { pNic->Cr = (cr & 0x3f) | page; } while (!((*nicDma) & ACC_MASK)); do { cr = *pReg; } while (!((*nicDma) & ACC_MASK)); intUnlock (level); return (cr); }/********************************************************************************* nicWritePort - write to the DMA port** RETURNS: N/A.*/LOCAL void nicWritePort ( UINT8 value ) {#ifndef NIC_FASTER int level = intLock ();#endif do { *(volatile char *) NIC_PORT = value; } while (!((*(volatile UINT8 *) NIC_DMA) & ACC_MASK));#ifndef NIC_FASTER intUnlock (level);#endif }/********************************************************************************* nicReadPort - read from the DMA port** RETURNS: the DMA port value.*/LOCAL UINT8 nicReadPort (void) { UINT8 value;#ifndef NIC_FASTER int level = intLock ();#endif do { value = *(volatile UINT8 *) NIC_PORT; } while (!((*(volatile UINT8 *) NIC_DMA) & ACC_MASK));#ifndef NIC_FASTER intUnlock (level);#endif return (value); }/********************************************************************************* nicTransmit - send data over the NIC network interface** This routine transfers data to the NIC device via the remote DMA, and* then signal for a transmission.** RETURNS: OK, or ERROR if the transmitter signalled an error.*/LOCAL STATUS nicTransmit ( DRV_CTRL * pDrvCtrl, MBUF * pMbuf, int len, BOOL waitFlag ) { NIC_DEVICE * pNic = pDrvCtrl->nicAddr; UINT8 cr; UINT8 isr; UINT8 * buf; int status = OK; int count; int ix; int tranxLen = max (len, MINPKTSIZE);#ifdef NIC_FASTER nicWriteReg(pNic, &pNic->Imr, 0, RPAGE0); /* disable all interrupts */#endif nicWriteReg (pNic, &pNic->Rbcr0, 0x10, RPAGE0); nicWriteCr (pNic, RREAD); nicWriteReg (pNic, &pNic->Rbcr0, (tranxLen & 0x00ff), RPAGE0); nicWriteReg (pNic, &pNic->Rbcr1, (tranxLen & 0xff00) >> 8, RPAGE0); nicWriteReg (pNic, &pNic->Rsar0, 0x00, RPAGE0); nicWriteReg (pNic, &pNic->Rsar1, 0x00, RPAGE0); nicWriteCr (pNic, RWRITE); count = 0; for (; pMbuf != NULL; pMbuf = m_free (pMbuf)) for (ix = 0, buf = mtod (pMbuf, UINT8 *); ix < pMbuf->m_len; ix++) { count++; nicWritePort (*buf++); } for (; count < tranxLen; count ++) /* pad out if too short */ nicWritePort (0); nicWriteReg (pNic, &pNic->Tpsr, 0x00, RPAGE0); nicWriteReg (pNic, &pNic->Tbcr0, (tranxLen & 0x000000ff), RPAGE0); nicWriteReg (pNic, &pNic->Tbcr1, ((tranxLen & 0x0000ff00) >> 8), RPAGE0); cr = nicReadReg (pNic, &pNic->Cr, RPAGE0); nicWriteReg(pNic, &pNic->Isr, (PTX | TXE), RPAGE0); nicWriteCr (pNic, TXP | (cr & (RWRITE | RREAD))); /* start Tx */ count = 0; if (waitFlag) /* wait for Tx to end ? */ { while (count++ < TRANS_TIMEOUT) /* only poll a few times */ { isr = nicReadReg (pNic, &pNic->Isr, RPAGE0); if (isr & TXE) /* error encountered */ { status = ERROR; break; } if (isr & PTX) /* Tx done */ break; } if (count >= TRANS_TIMEOUT) /* error ? */ { status = ERROR;#ifdef NIC_INSTRUMENT nicTxTimeout++;#endif#ifdef NIC_DEBUG if (_func_logMsg != NULL) _func_logMsg("nicTransmit TRANS_TIMEOUT %d\n", nicTxTimeout,0,0,0,0,0);#endif } }#ifdef NIC_FASTER nicWriteReg(pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* re-enable intr. */#endif return (status); }/********************************************************************************* nicReceive - receive data from the NIC network interface** This routine transfers data from the NIC device ring buffers via the* remote DMA.** RETURNS: OK, always.*/LOCAL STATUS nicReceive ( DRV_CTRL * pDrvCtrl, UINT32 nicBufAddr, char * pData, int len ) { NIC_DEVICE * pNic = pDrvCtrl->nicAddr; int residual; int dmaCnt; int ix;#ifdef NIC_FASTER nicWriteReg(pNic, &pNic->Imr, 0, RPAGE0); /* disable all interrupts */#endif if ((nicBufAddr + len) < (PSTOP * PACKET_SIZE)) { nicWriteReg (pNic, &pNic->Rbcr0, (len & 0xff), RPAGE0); nicWriteReg (pNic, &pNic->Rbcr1, ((len & 0xff00) >> 8), RPAGE0); nicWriteReg (pNic, &pNic->Rsar0, (nicBufAddr & 0xff), RPAGE0); nicWriteReg (pNic, &pNic->Rsar1, (((nicBufAddr & 0xff00)>> 8)), RPAGE0); nicWriteCr (pNic, RREAD); for (ix = 0; ix < len; ix ++) *pData++ = nicReadPort (); } else { residual = (nicBufAddr + len) - (PSTOP * PACKET_SIZE); dmaCnt = len - residual; nicWriteReg (pNic, &pNic->Rbcr0, (dmaCnt & 0xff), RPAGE0); nicWriteReg (pNic, &pNic->Rbcr1, ((dmaCnt & 0xff00) >> 8), RPAGE0); nicWriteReg (pNic, &pNic->Rsar0, (nicBufAddr & 0xff), RPAGE0); nicWriteReg (pNic, &pNic->Rsar1, (((nicBufAddr & 0xff00)>> 8)), RPAGE0); nicWriteCr (pNic, RREAD); for (ix = 0; ix < dmaCnt; ix++) *pData++ = nicReadPort (); nicWriteReg (pNic, &pNic->Rbcr0, (residual & 0xff), RPAGE0); nicWriteReg (pNic, &pNic->Rbcr1, ((residual & 0xff00) >> 8), RPAGE0); nicWriteReg (pNic, &pNic->Rsar0, 0x00, RPAGE0); nicWriteReg (pNic, &pNic->Rsar1, PSTART, RPAGE0); nicWriteCr (pNic, RREAD); for (ix = 0; ix < residual; ix++) *pData++ = nicReadPort (); }#ifdef NIC_FASTER nicWriteReg(pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* re-enable intr. */#endif return (OK); } /********************************************************************************* nicLoanFree - return a buffer to the Rx loaner pool** RETURNS: N/A.*/LOCAL void nicLoanFree ( DRV_CTRL * pDrvCtrl, RX_FRAME * pRx ) { pDrvCtrl->lPool [pDrvCtrl->lIndex++] = pRx; }/********************************************************************************* nicPagePtrUpdate - updates receive buffer/page pointers** This routine updates the receive buffer/page pointer and the receive* boundary register (BNRY). The chip is re-initialized if the receive next * packet pointer recorded in the current packet header is out of range.** RETURNS: TRUE, or FALSE if next packet pointer is out of range.*/ LOCAL BOOL nicPagePtrUpdate ( DRV_CTRL * pDrvCtrl ) { RX_FRAME * pRx = pDrvCtrl->pRxFrame;/* free Rx buffer */ NIC_DEVICE * pNic= pDrvCtrl->nicAddr; /* update ring buffer/page pointers */ if ((pRx->rxHdr.nextRxPage < PSTART)||(pRx->rxHdr.nextRxPage >= PSTOP)) {#ifdef NIC_DEBUG if (_func_logMsg != NULL) _func_logMsg ("nicPagePtrUpdate: statusHeader=0x%x nextRxPage=%d IntNb=%d\n",pRx->rxHdr.status, pRx->rxHdr.nextRxPage, nicIntNb, 0,0);#endif#ifdef NIC_INSTRUMENT nicInitNb++;#endif pDrvCtrl->idr.ac_if.if_ierrors++; /* restart the chip - we should never end up here - */ nicConfig (0); pDrvCtrl->nextPkt = CURR; pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS; return (FALSE); } /* updates the Boundary pointer register (BNRY) */ if ((pDrvCtrl->nextPkt = pRx->rxHdr.nextRxPage) == PSTART) nicWriteReg (pNic, &pNic->Bnry, PSTOP - 1, RPAGE0); else nicWriteReg (pNic, &pNic->Bnry, pDrvCtrl->nextPkt - 1, RPAGE0); return (TRUE); }/********************************************************************************* nicResetDelay - performs the delay required before resetting the chip ** This routine performs a 1.6 ms delay for PowerPC architecture if * using the internal PPC time base (the number of time base increment to* count for 1.6 msec is defined by the value nicRestartDelay which must * be set in the BSP), or waits for one system clock tick otherwise.** RETURNS: N/A.*/ LOCAL void nicResetDelay (void) {#ifdef NIC_USE_PPCTIMEBASE UINT32 tbu1, tbu2; UINT32 tbl1, tbl2;#endif#ifdef NIC_USE_PPCTIMEBASE vxTimeBaseGet (&tbu1, &tbl1); while (1) { vxTimeBaseGet (&tbu2, &tbl2); if ((tbu2-tbu1) != 0) vxTimeBaseGet (&tbu1, &tbl1); else if ((tbl2 - tbl1) > nicRestartDelay) break; }#else taskDelay (1); /* wait at least 1.6 mSec */#endif }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -