📄 iolicomend.c
字号:
LOCAL STATUS iOlicomRecv ( END_DEVICE * pDrvCtrl, /* pointer to END_DEVICE structure */ RX_BD * pRxBd ) { END_OBJ * pOliObj = &pDrvCtrl->endObj; M_BLK_ID pMblk; /* MBLK to send upstream */ CL_BLK_ID pClBlk; /* pointer to clBlk */ char * pBuf; /* A replacement buffer for the current RxD */ char * pData; /* Data pointer for the current RxD */ int len; /* Len of the current data */ END_LOG_MSG (END_DEBUG_RX, "iOlicomRecv\n", 0, 0, 0, 0, 0, 0); /* Allocate an MBLK, and a replacement buffer */ pMblk = NET_MBLK_ALLOC(); pBuf = NET_BUF_ALLOC(); pClBlk = NET_CL_BLK_ALLOC(); if ((pMblk == NULL) || (pBuf == NULL) || (pClBlk == NULL)) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); if (pMblk) NET_MBLK_FREE (pMblk); if (pBuf) NET_BUF_FREE (pBuf); if (pClBlk) NET_CL_BLK_FREE (pClBlk); goto cleanRxBd; } /* Get the data pointer and len from the current RX_BD */ len = pRxBd->dataLength; pData = pRxBd->dataPointer; pData -= pDrvCtrl->offset; /* Associate the data pointer with the CL_BLK */ NET_CL_BLK_JOIN (pClBlk, pData, OLI_BUFSIZ); /* Associate the CL_BLK with the MBLK */ NET_MBLK_CL_JOIN (pMblk, pClBlk); pMblk->mBlkHdr.mData += pDrvCtrl->offset; pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */ pMblk->mBlkHdr.mLen = len; /* set the data len */ pMblk->mBlkPktHdr.len = len; /* set the total len */ /* Deal with memory alignment. */ pBuf += pDrvCtrl->offset; /* Install the new data buffer */ pRxBd->dataPointer = pBuf; /* mark the descriptor ready to receive */ pRxBd->statusMode |= RX_BD_EMPTY; /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); /* send up to protocol */ END_LOG_MSG (END_DEBUG_RX, ("Calling upper layer! \n"), 0, 0, 0, 0, 0, 0); END_RCV_RTN_CALL (pOliObj, pMblk); return OK;cleanRxBd: /* mark the descriptor ready to receive */ pRxBd->statusMode |= RX_BD_EMPTY; return OK; }/********************************************************************************* iOlicomSend - 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 iOlicomSend ( END_DEVICE * pDrvCtrl, /* pointer to END_DEVICE structure */ M_BLK * pMblk ) { TX_BD * pTxBd; char * pBuf; UINT8 * pData; UINT8 * pDataEnd; ULONG addrC; int len; int s; volatile UINT8 * pR14; END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomSend()\n", 0, 0, 0, 0, 0, 0); END_LOG_MSG (END_DEBUG_TX, "iOlicomSend()\n", 0, 0, 0, 0, 0, 0); if (DRV_FLAGS_ISSET (OLI_POLLING)) { NET_MBLK_CHAIN_FREE (pMblk); /* free the given mBlk chain */ errno = EINVAL; return (ERROR); } /* * Obtain exclusive access to transmitter. This is necessary because * we might have more than one stack transmitting at once. */ END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); END_LOG_MSG (END_DEBUG_TX, "iOlicomSend() got semaphore\n", 0, 0, 0, 0, 0, 0); /* get a free transmit frame descriptor */ pTxBd = iOlicomTxBdGet (pDrvCtrl); addrC = (ULONG) pTxBd->dataPointer; /* get a free buufer */ pBuf = NET_BUF_ALLOC(); if ((pTxBd == NULL) || (pBuf == NULL)) { END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1); END_TX_SEM_GIVE (&pDrvCtrl->endObj); if (pBuf) NET_BUF_FREE (pBuf); if (! DRV_FLAGS_ISSET(OLI_TX_CLEANING | OLI_TX_STOP)) iOlicomTxBdQueueClean (pDrvCtrl); s = intLock(); DRV_FLAGS_SET(OLI_TX_STOP); /* transmitter not ready */ intUnlock (s); /* just return without freeing mBlk chain */ return (END_ERR_BLOCK); } /* Copy and free the MBLK */ len = netMblkToBufCopy (pMblk, pBuf, NULL); NET_MBLK_CHAIN_FREE (pMblk); s = intLock(); /* Write the transmit buffer base address. */ PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R12, addrC); PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R13, (addrC >> 8)); /* Write the command opcode, and reserved field for the packet */ WRITE_R14_R15 (CMD_TRANSMIT); /* Write 16 bit status field */ WRITE_R14_R15 (0x00); /* Write the chain pointer */ WRITE_R14_R15 (0x00); /* Write the byte count low and high bytes */ WRITE_R14_R15 (len & ~XMT_CHAIN); /* * Copy data. Initialise pointer here to provoke the compiler into * generating better code */ pR14 = (volatile UINT8 *) (pDrvCtrl->pcmcia.oliAddr + I595_R14); for (pData = (UINT8 *)pBuf, pDataEnd = pData + len; pData < pDataEnd ; ) WRITE_PTR_R14_R15 (pData, pR14); /* * The Ethernet chip can't receive a transmit command while a * TRANSMIT is already in progress. The following test checks if the * 82595TX chip is transmitting a packet before issuing another transmit * command. */ if (pDrvCtrl->txBdIndexC == pDrvCtrl->txBdNext) { /* Write the XMT base address register */ PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R10, addrC); PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R11, (addrC >> 8)); /* Issue a XMT command to the 82595TX */ RUNCMD((UINT)(pDrvCtrl->pcmcia.oliAddr), CMD_TRANSMIT); } /* Save the buf info */ pDrvCtrl->freeBuf[pDrvCtrl->txBdNext].pClBuf = pBuf; /* incr BD count */ pDrvCtrl->txBdNext = (pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum; intUnlock(s); /* release exclusive access */ END_TX_SEM_GIVE (&pDrvCtrl->endObj); /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomSend() exit\n", 0, 0, 0, 0, 0, 0); return (OK); }/********************************************************************************* iOlicomTxBdGet - get an available transmit descriptor** Get next transmited message descriptor. Returns NULL if none are* ready.** RETURNS: an available transmit descriptor, otherwise NULL.*/LOCAL TX_BD * iOlicomTxBdGet ( END_DEVICE * pDrvCtrl ) { ULONG addrC; int status; TX_BD * pTxBd = &pDrvCtrl->txBdBase[pDrvCtrl->txBdNext]; addrC = (ULONG) pTxBd->dataPointer; PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R12, addrC); PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R13, (addrC >> 8)); READ_R14_R15 (status); /* check if a transmit buffer descriptor is available */ if (!(status & TX_BD_READY) || ((pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum) == pDrvCtrl->txBdIndexC) return (NULL); return (pTxBd); }/********************************************************************************* iOlicomIoctl - the driver I/O control routine** Process an ioctl request.** This routine implements the network interface control functions.* It handles EIOCSADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS,* EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2, EIOCGFBUF commands.** RETURNS: OK if successful, otherwise EINVAL.*/LOCAL int iOlicomIoctl ( END_DEVICE * pDrvCtrl, /* pointer to END_DEVICE structure */ int cmd, /* command to process */ char * data /* pointer to data */ ) { int error = 0; long value; END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomIoctl()\n", 0, 0, 0, 0, 0, 0); switch ((UINT)cmd) { case EIOCSADDR: if (data == NULL) return (EINVAL); memcpy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data, END_HADDR_LEN(&pDrvCtrl->endObj)); break; case EIOCGADDR: if (data == NULL) return (EINVAL); memcpy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj), END_HADDR_LEN(&pDrvCtrl->endObj)); break; case EIOCSFLAGS: value = (long)data; if (value < 0) { value = -value; value--; END_FLAGS_CLR (&pDrvCtrl->endObj, value); } else { END_FLAGS_SET (&pDrvCtrl->endObj, value); } iOlicomConfig (pDrvCtrl); END_LOG_MSG (END_DEBUG_IOCTL, "endFlags %#x\n", END_FLAGS_GET(&pDrvCtrl->endObj), 0, 0, 0, 0 ,0); break; case EIOCGFLAGS: *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj); break; case EIOCPOLLSTART: error = iOlicomPollStart (pDrvCtrl); break; case EIOCPOLLSTOP: error = iOlicomPollStop (pDrvCtrl); break; case EIOCGMIB2: if (data == NULL) return (EINVAL); memcpy((char *)data, (char *)&pDrvCtrl->endObj.mib2Tbl, sizeof(pDrvCtrl->endObj.mib2Tbl)); break; case EIOCGFBUF: if (data == NULL) return (EINVAL); *(int *)data = OLI_MIN_FBUF; break; default: error = EINVAL; } return (error); }/******************************************************************************** iOlicomConfig - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** RETURNS: N/A*/LOCAL void iOlicomConfig ( END_DEVICE * pDrvCtrl /* pointer to END_DEVICE structure */ ) { /* Set promiscuous mode if it's asked for. */ if (END_FLAGS_GET (&pDrvCtrl->endObj) & IFF_PROMISC) { END_LOG_MSG (END_DEBUG_IOCTL, "Setting promiscuous mode on!\n", 0, 0, 0, 0, 0, 0); SELECTBANK (pDrvCtrl->pcmcia.oliAddr, 2); PCMCIA_IO_WRITE (pDrvCtrl->pcmcia.oliAddr + I595_R2, (PCMCIA_IO_READ (pDrvCtrl->pcmcia.oliAddr + I595_R2) | BNK2_PCS_EN)); } else { END_LOG_MSG (END_DEBUG_IOCTL, "Setting promiscuous mode off!\n", 0, 0, 0, 0, 0, 0); } /* setup ethernet address and filtering mode */ iOlicomAddrFilterSet (pDrvCtrl); return; }/******************************************************************************** iOlicomAddrFilterSet - set the address filter for multicast addresses** This routine goes through all of the multicast addresses on the list* of addresses (added with the iOlicomAddrAdd() routine) and sets the* device's filter correctly.** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS iOlicomAddrFilterSet ( END_DEVICE * pDrvCtrl /* pointer to END_DEVICE structure */ ) { UINT8 * pFltrFrm; UINT8 * pData; ETHER_MULTI * pMCastNode; TX_BD * pTxBd; int length; int ix; int s; int index = 0; ULONG addrC; END_LOG_MSG (END_DEBUG_ADDR, "iOlicomAddrFilterSet \n", 0, 0, 0, 0, 0, 0); /* gain exclusive access to transmitter */ END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER); /* Select bank 0 of the Olicom register set */ SELECTBANK(pDrvCtrl->pcmcia.oliAddr, 0); /* get a free transmit frame descriptor */ pTxBd = iOlicomTxBdGet (pDrvCtrl); if (pTxBd == NULL) { END_TX_SEM_GIVE (&pDrvCtrl->endObj); return (ERROR); } addrC = (ULONG) pTxBd->dataPointer; /* get a buffer */ pFltrFrm = (UINT8 *)NET_BUF_ALLOC(); if (pFltrFrm == NULL) { END_LOG_MSG (END_DEBUG_LOAD, "netClusterGet failed\n", 0, 0, 0, 0, 0, 0); END_TX_SEM_GIVE (&pDrvCtrl->endObj); return (ERROR); } /* clear all entries */ memset (pFltrFrm, 0, FLTR_FRM_SIZE); /* install multicast addresses */ pData = pFltrFrm; for (pMCastNode = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -