📄 ln97xend.c
字号:
*/ if ((pMblk = mBlkGet(pDrvCtrl->endObj.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netClBlkFree (pDrvCtrl->endObj.pNetPool, pClBlk); netClFree (pDrvCtrl->endObj.pNetPool, pNewCluster); DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); goto cleanRXD; } END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); len = LN_PKT_LEN_GET (pRmd); /* get packet length */ LN_RMD_TO_ADDR (pRmd, pCluster); /* Get pointer to packet */ pCluster -= pDrvCtrl->offset; DRV_LOG (DRV_DEBUG_RX, "Packet @ 0x%X for %d bytes!\n", pCluster, len, 3, 4, 5, 6); /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); /* make the packet data coherent */ LN_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len); pMblk->mBlkHdr.mData += pDrvCtrl->offset; pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len; DRV_LOG (DRV_DEBUG_RX, "Calling upper layer!\n", 1, 2, 3, 4, 5, 6); /* Deal with memory alignment. */ pNewCluster += pDrvCtrl->offset; /* Give receiver a new buffer */ LN_RMD_BUF_TO_ADDR (pRmd, pTemp, pNewCluster); /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->endObj, pMblk);cleanRXD: /* clear status bits */ LN_CLEAN_RXD (pRmd); /* Flush the write pipe */ CACHE_PIPE_FLUSH (); /* Advance our management index */ pDrvCtrl->rmdIndex = (pDrvCtrl->rmdIndex + 1) & (pDrvCtrl->rringSize - 1); return (OK); }/********************************************************************************* lnSend - 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. The last arguments are a free* routine to be called when the device is done with the buffer and a pointer* to the argument to pass to the free routine. ** RETURNS: OK or ERROR.*/LOCAL STATUS ln97xSend ( LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */ M_BLK_ID pMblk /* data to send */ ) { LN_TMD * pTmd; UINT32 ltmd1; void * pTemp; char * pBuf; char * pOrig; int level; int len = 0; /* * Obtain exclusive access to transmitter. This is necessary because * we might have more than one stack transmitting at once. */ if (!(pDrvCtrl->flags & LS_POLLING)) END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); pTmd = pDrvCtrl->pTring + pDrvCtrl->tmdIndex; DRV_LOG (DRV_DEBUG_TX, "Send : index %d tmd = 0x%X\n", pDrvCtrl->tmdIndex, (int)pTmd, 3, 4, 5, 6); LN_CACHE_INVALIDATE (pTmd, TMD_SIZ); ltmd1 = PCI_SWAP (pTmd->tBufTmd1); if ((ltmd1 & TMD1_OWN) || (((pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1)) == pDrvCtrl->tmdIndexC)) { if (!(pDrvCtrl->flags & LS_POLLING)) END_TX_SEM_GIVE (&pDrvCtrl->endObj); /* Are we still on the first chunk? */ DRV_LOG (DRV_DEBUG_TX, "Out of TMDs!\n", 1, 2, 3, 4, 5, 6); level = intLock (); pDrvCtrl->txBlocked = TRUE; intUnlock (level); return (END_ERR_BLOCK); } DRV_LOG (DRV_DEBUG_TX, "before cluster get %d %d\n", pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId, 3, 4, 5, 6); pOrig = pBuf = netClusterGet (pDrvCtrl->endObj.pNetPool, pDrvCtrl->pClPoolId); DRV_LOG (DRV_DEBUG_TX, "after cluster get pBuf = 0x%X\n", (int)pBuf, 2, 3, 4, 5, 6); if (pBuf == NULL) { netMblkClChainFree(pMblk); return (ERROR); } pBuf += pDrvCtrl->offset; /* take care of the alignment */ len = netMblkToBufCopy (pMblk, pBuf, NULL); netMblkClChainFree(pMblk); LN_TMD_BUF_TO_ADDR(pTmd, pTemp, pBuf); len = max (len, ETHERSMALL); pTmd->tBufTmd2 = 0; /* clear buffer error status */ ltmd1 = TMD1_STP | TMD1_ENP | TMD1_CNST; ltmd1 |= (TMD1_BCNT_MSK & -len); pTmd->tBufTmd1 = PCI_SWAP (ltmd1); CACHE_PIPE_FLUSH (); LN_CACHE_INVALIDATE (pTmd, TMD_SIZ); ltmd1 |= TMD1_OWN; DRV_LOG (DRV_DEBUG_TX, "TMD1 = 0x%X\n", ltmd1, 2, 3, 4, 5, 6); /* write to actual register */ pTmd->tBufTmd1 = PCI_SWAP (ltmd1); pDrvCtrl->freeRtn [pDrvCtrl->tmdIndex] = (FUNCPTR)netClFree; pDrvCtrl->freeData [pDrvCtrl->tmdIndex].arg1 = pDrvCtrl->endObj.pNetPool; pDrvCtrl->freeData [pDrvCtrl->tmdIndex].arg2 = pOrig; /* Advance our management index */ pDrvCtrl->tmdIndex = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1); /* Flush the write pipe */ CACHE_PIPE_FLUSH (); if (lnKickStartTx) { if (!(pDrvCtrl->flags & LS_POLLING)) ln97xCsrWrite (pDrvCtrl, 0, (CSR0_INTMASK | CSR0_TDMD)); else ln97xCsrWrite (pDrvCtrl, 0, CSR0_TDMD); } if (!(pDrvCtrl->flags & LS_POLLING)) END_TX_SEM_GIVE (&pDrvCtrl->endObj); /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); return (OK); }/********************************************************************************* ln97xIoctl - the driver I/O control routine** Process an ioctl request.** RETURNS OK or ERROR value*/LOCAL int ln97xIoctl ( LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */ int cmd, /* ioctl command to execute */ caddr_t data /* date to get or set */ ) { long value; int error = 0; switch (cmd) { case EIOCSADDR: if (data == NULL) return (EINVAL); bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj), END_HADDR_LEN (&pDrvCtrl->endObj)); break; case EIOCGADDR: if (data == NULL) return (EINVAL); bcopy ((char *)END_HADDR (&pDrvCtrl->endObj), (char *)data, END_HADDR_LEN (&pDrvCtrl->endObj)); break; case EIOCSFLAGS: value = (long)data; if (value < 0) { value = -value; value--; /* HELP: WHY ??? */ END_FLAGS_CLR (&pDrvCtrl->endObj, value); } else { END_FLAGS_SET (&pDrvCtrl->endObj, value); } ln97xConfig (pDrvCtrl); break; case EIOCGFLAGS: *(int *)data = END_FLAGS_GET (&pDrvCtrl->endObj); break; case EIOCPOLLSTART: error = ln97xPollStart (pDrvCtrl); break; case EIOCPOLLSTOP: error = ln97xPollStop (pDrvCtrl); break; case EIOCGMIB2: if (data == NULL) return (EINVAL); bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data, sizeof(pDrvCtrl->endObj.mib2Tbl)); break; case EIOCGFBUF: if (data == NULL) return (EINVAL); *(int *)data = LN_MIN_FBUF; break; case EIOCGMWIDTH: if (data == NULL) return (EINVAL); *(int *)data = pDrvCtrl->memWidth; break; case EIOCGHDRLEN: if (data == NULL) return (EINVAL); *(int *)data = 14; break; default: error = EINVAL; } return (error); }/********************************************************************************* ln97xReset - hardware reset of chip (stop it)** This routine is responsible for resetting the device and switching into* 32 bit mode.** RETURNS: OK/ERROR*/LOCAL int ln97xReset ( LN_97X_DRV_CTRL * pDrvCtrl /* device to be initialized */ ) { UINT32 resetTmp; /* Enable 32 bit access by doing a 32 bit write */ SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRdp, 0); ln97xCsrWrite (pDrvCtrl, CSR(0), CSR0_STOP); /* Generate a soft-reset of the controller */ SYS_IN_LONG(pDrvCtrl, pDrvCtrl->pReset, resetTmp); /* This isn't a real test - it just stops the compiler ignoring the read */ if (resetTmp == 0x12345678) return (ERROR); ln97xBcrWrite (pDrvCtrl, BCR(20), BCR20_SWSTYLE_PCNET); /* autoselect port tye - 10BT or AUI */ ln97xBcrWrite (pDrvCtrl, BCR(2), BCR2_AUTO_SELECT); /* read BCR */ resetTmp = ln97xBcrRead (pDrvCtrl, BCR(20)); return (OK); }/********************************************************************************* ln97xCsrWrite - select and write a CSR register** This routine selects a register to write, through the RAP register and* then writes the CSR value to the RDP register.** RETURNS: N/A*/LOCAL void ln97xCsrWrite ( LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */ int reg, /* CSR register to select */ UINT32 value /* CSR value to write */ ) { int level; level = intLock (); /* select CSR */ reg &= 0xff; SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRap, PCI_SWAP (reg)); CACHE_PIPE_FLUSH (); value &=0xffff; SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRdp, PCI_SWAP (value)); CACHE_PIPE_FLUSH (); intUnlock (level); }/********************************************************************************* ln97xCsrRead - select and read a CSR register** This routine selects a register to read, through the RAP register and* then reads the CSR value from the RDP register.** RETURNS: N/A*/LOCAL UINT32 ln97xCsrRead ( LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */ int reg /* register to select */ ) { int level; UINT32 result; level = intLock (); SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRap, PCI_SWAP (reg)); CACHE_PIPE_FLUSH (); SYS_IN_LONG (pDrvCtrl, pDrvCtrl->pRdp, result); intUnlock (level); return (PCI_SWAP (result) & 0x0000FFFF); }/********************************************************************************* ln97xBcrWrite - select and write a BCR register** This routine writes the bus configuration register. It first selects the* BCR register to write through the RAP register and then it writes the value* to the BDP register.** RETURNS: N/A*/LOCAL void ln97xBcrWrite ( LN_97X_DRV_CTRL * pDrvCtrl, /* device to be initialized */ int reg, /* BCR register to select */ UINT32 value /* BCR value to write */ ) { int level; reg &= 0xff; value &=0xffff; level = intLock (); SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pRap, PCI_SWAP(reg)); CACHE_PIPE_FLUSH (); SYS_OUT_LONG (pDrvCtrl, pDrvCtrl->pBdp, PCI_SWAP(value)); intUnlock (level); }/********************************************************************************* ln97xBcrRead - select and read a BCR register** This routine reads the bus configuration register. It first selects the* BCR register to read through the RAP register and then it reads the value* from the BDP register.** RETURNS: N/A*/LOCAL UINT32 ln97xBcrRead ( LN_97X_DRV_CTRL * pDrvCtrl, /* driver control */ int reg /* register to select */ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -