📄 iolicomend.c
字号:
pMCastNode != NULL; pMCastNode = END_MULTI_LST_NEXT (pMCastNode)) { for (ix = 0; ix < EADDR_LEN; ix++) *(pData++) = pMCastNode->addr[ix]; index++; } /* Set variables to copy the buffer in */ length = index * EADDR_LEN; pData--; s = intLock (); /* disable ints during update */ /* 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_MC_SETUP); /* 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 (length & ~XMT_CHAIN); /* copy data */ for (; length > 0 ; length -= 2) { PCMCIA_IO_WRITE((UINT)(pDrvCtrl->pcmcia.oliAddr + I595_R14), *pData--); PCMCIA_IO_WRITE((UINT)(pDrvCtrl->pcmcia.oliAddr + I595_R15), *pData--); } /* 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 MC_SETUP command to the 82595TX */ RUNCMD((UINT)(pDrvCtrl->pcmcia.oliAddr), CMD_MC_SETUP); /* incr BD count */ pDrvCtrl->txBdNext = (pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum; /* Spin until we've sent it. */ while (!(PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R1) & BNK0_EXE_IT)); /* clear execution interrupt */ PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R1, BNK0_EXE_IT); /* clean the transmit queue */ iOlicomTxBdQueueClean(pDrvCtrl); intUnlock (s); /* now iOlicomInt won't get confused */ /* free the buffer */ NET_BUF_FREE (pFltrFrm); /* release exclusive access */ END_TX_SEM_GIVE (&pDrvCtrl->endObj); END_LOG_MSG (END_DEBUG_ADDR, "iOlicomAddrFilterSet() exit\n", 0, 0, 0, 0, 0, 0); return (OK); }/********************************************************************************* iOlicomPollReceive - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device. It returns EAGAIN if no packet is available. The caller must* supply a M_BLK_ID with enough space to contain the receiving packet. If* enough buffer is not available then EAGAIN is returned.** These routine should not call any kernel functions.** RETURNS: OK on success, EAGAIN on failure.*/LOCAL STATUS iOlicomPollReceive ( END_DEVICE * pDrvCtrl, /* pointer to END_DEVICE structure */ M_BLK * pMblk ) { char * pPacket; int status; int length; int event; int start; int nextStop; BOOL gotOne=FALSE; volatile UINT8 * pR14; END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomPollReceive()\n", 0, 0, 0, 0, 0, 0); if ((pMblk->mBlkHdr.mFlags & M_EXT) != M_EXT) return (EAGAIN); /* Read the device status register */ status = PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R1); /* If no interrupt then return. */ if (!(status & BNK0_RX_IT)) { END_LOG_MSG (END_DEBUG_POLL_RX, "iOlicomPollReceive no rint\n", 0, 0, 0, 0, 0, 0); return (EAGAIN); } /* * The RCV STOP register points to the last pair of bytes * BEFORE the start of the next packet so we must add two * bytes to reach the correct address. */ start = PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R6); start |= (PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R7) << 8); start += 2; /* Handle the roll over case */ if (start > RAM_RX_LIMIT) start -= RAM_RX_BASE; /* Set up address from where we wish to start reading data */ PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R12, start); PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R13, (start >> 8)); /* The first word describes the state of reception. */ READ_R14_R15 (event); /* The following bit will be set once the packet is complete in memory. */ if (event & RCV_EOF) { /* Collect the status of the packet */ READ_R14_R15 (status); /* get next packet pointer */ READ_R14_R15 (nextStop); /* The next stop value is 2 bytes back in the circular buffer */ nextStop -= 2; /* Handle the roll over case */ if (nextStop < RAM_RX_BASE) nextStop += RAM_RX_BASE; /* get packet length */ READ_R14_R15 (length); /* Check for errors */ if (!(status & RCV_OK) || ((length - SIZEOF_ETHERHEADER) <= 0)) { /* bump input error packet counter */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); } else { /* * We always read an even number of bytes from the controller, * so adjust the length if necessary. */ if ((length & ODD_MSK) != 0) ++length; /* Upper layer provides the buffer. */ if (pMblk->mBlkHdr.mLen < length) goto pollRecvExit; /* Deal with memory aligment */ if (((int) pMblk->mBlkHdr.mData & 0x3) == 0) pMblk->mBlkHdr.mData += pDrvCtrl->offset; pMblk->mBlkHdr.mFlags |= M_PKTHDR; /* set the packet header */ pMblk->mBlkPktHdr.len = length; /* set the total len */ pMblk->mBlkHdr.mLen = length; /* set the data len */ /* Copy data. * * Set up the pointer just before the loop: provokes code * generator into producing much better code. */ pR14 = (volatile UINT8 *) (pDrvCtrl->pcmcia.oliAddr + I595_R14); for (pPacket = pMblk->mBlkHdr.mData; length != 0; length -=2) READ_PTR_R14_R15 (pPacket, pR14); gotOne = TRUE; /* bump input packet counter */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1); } /* Update the STOP register from the next packet pointer */ PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R6, nextStop); PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R7, (nextStop >> 8)); }pollRecvExit: /* clear receive interrupts. */ PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R1, BNK0_RX_IT); return (gotOne ? OK : EAGAIN); }/********************************************************************************* iOlicomPollSend - routine to send a packet in polled mode.** This routine is called by a user to try and send a packet on the* device. It sends a packet directly on the network from the caller without* going through the normal processes of queuing a pacet on an output queue* and the waiting for the device to decide to transmit it.** If it detects a transmission error, the restart command is issued.** These routine should not call any kernel functions.** RETURNS: OK on success, EAGAIN on failure*/LOCAL STATUS iOlicomPollSend ( END_DEVICE * pDrvCtrl, /* pointer to END_DEVICE structure */ M_BLK * pMblk ) { TX_BD * pTxBd; char * pBuf; char * pData; ULONG addrC; int len; int status; volatile UINT8 * pR14; END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomPollSend()\n", 0, 0, 0, 0, 0, 0); if (DRV_FLAGS_ISSET(OLI_TX_STOP)) return (EAGAIN); /* get a free transmit frame descriptor */ pTxBd = iOlicomTxBdGet (pDrvCtrl); addrC = (ULONG) pTxBd->dataPointer; /* get a free buffer */ pBuf = NET_BUF_ALLOC (); if ((pTxBd == NULL) || (pBuf == NULL)) { iOlicomTxBdQueueClean (pDrvCtrl); if (pBuf) NET_BUF_FREE (pBuf); return (EAGAIN); } /* copy the MBLK */ len = netMblkToBufCopy (pMblk, pBuf, NULL); /* 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 = pBuf; len > 0; len -= 2) WRITE_PTR_R14_R15 (pData, pR14); /* 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); /* incr BD count */ pDrvCtrl->txBdNext = (pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum; /* Bump the statistic counter. */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1); /* Spin until we've sent it. */ while (!(PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R1) & BNK0_TX_IT)); /* clear transmit interrupt */ PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R1, BNK0_TX_IT); /* Free the data immediately. */ NET_BUF_FREE (pBuf); /* check for output errors */ addrC = (ULONG) pTxBd->dataPointer + 2; PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R12, addrC); PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R13, (addrC >> 8)); READ_R14_R15 (status); if (!(status & XMT_OK)) return (EAGAIN); /* * we are allowed to do this because transmit queue is empty when we * start polling mode. */ pDrvCtrl->txBdIndexC = pDrvCtrl->txBdNext; return (OK); }/******************************************************************************** iOlicomMCastAddrAdd - add a multicast address for the device** This routine adds a multicast address to whatever the driver* is already listening for. It then resets the address filter.** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS iOlicomMCastAddrAdd ( END_DEVICE * pDrvCtrl, /* pointer to END_DEVICE structure */ char * pAddress /* address to add to the table */ ) { int error; END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomMCastAddrAdd\n", 0, 0, 0, 0, 0, 0); if ((error = etherMultiAdd (&pDrvCtrl->endObj.multiList, pAddress)) == ENETRESET) iOlicomConfig (pDrvCtrl); return (OK); }/******************************************************************************* iOlicomMCastAddrDel - delete a multicast address for the device** This routine removes a multicast address from whatever the driver* is listening for. It then resets the address filter.** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS iOlicomMCastAddrDel ( END_DEVICE * pDrvCtrl, /* pointer to END_DEVICE structure */ char * pAddress /* address to delete from the table */ ) { int error; END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomMCastAddrDel\n", 0, 0, 0, 0, 0,0); if ((error = etherMultiDel (&pDrvCtrl->endObj.multiList, (char *)pAddress)) == ENETRESET) iOlicomConfig (pDrvCtrl); return (OK); }/******************************************************************************* iOlicomMCastAddrGet - get the multicast address list for the device** This routine gets the multicast list of whatever the driver* is already listening for.** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS iOlicomMCastAddrGet ( END_DEVICE * pDrvCtrl, /* pointer to END_DEVICE structure */ MULTI_TABLE * pTable /* table to fill in with addresses */ ) { int error; END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomMCastAddrGet\n", 0, 0, 0, 0, 0,0); error = etherMultiGet (&pDrvCtrl->endObj.multiList, pTable); return (error); }/**********************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -