📄 iolicomend.c
字号:
} } else clDesc.memArea = (char *) (pDrvCtrl->rxBdBase + pDrvCtrl->rxBdNum); if ((pDrvCtrl->endObj.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); /* Initialize the net buffer pool with transmit buffers */ if (netPoolInit (pDrvCtrl->endObj.pNetPool, &oliMclBlkConfig, &clDesc, 1, NULL) == ERROR) { END_LOG_MSG (END_DEBUG_LOAD, "%s%d - netPoolInit failed\n", DRV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); return (ERROR); } /* Save the cluster pool id */ pDrvCtrl->clPoolId = clPoolIdGet (pDrvCtrl->endObj.pNetPool, OLI_BUFSIZ, FALSE); /* Setup the receive ring */ for (ix = 0; ix < pDrvCtrl->rxBdNum; ix++) { pBuf = (char *) NET_BUF_ALLOC(); if (pBuf == NULL) { END_LOG_MSG (END_DEBUG_LOAD, "%s%d - netClusterGet failed\n", DRV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); return (ERROR); } pBuf += pDrvCtrl->offset; pDrvCtrl->rxBdBase[ix].dataPointer = pBuf; } END_LOG_MSG (END_DEBUG_LOAD, "Memory setup complete\n", 0, 0, 0, 0, 0, 0); return (OK); }/********************************************************************************* iOlicomStart - start the device** This function initializes the device and calls BSP functions to connect* interrupts and start the device running in interrupt mode.** The complement of this routine is iOlicomStop. Once a unit is reset by* iOlicomStop, it may be re-initialized to a running state by this routine.** RETURNS: OK if successful, otherwise ERROR*/LOCAL STATUS iOlicomStart ( END_DEVICE * pDrvCtrl /* pointer to END_DEVICE structure */ ) { STATUS result; int ix; ULONG addrC; END_LOG_MSG (END_DEBUG_LOAD, "iOlicomStart()\n", 0, 0, 0, 0, 0, 0); /* Select bank 0 of the Olicom register set */ SELECTBANK(pDrvCtrl->pcmcia.oliAddr, 0); /* reset the device */ iOlicomReset (pDrvCtrl); /* initialize the device */ iOlicomInit (pDrvCtrl); /* initialize flags */ DRV_FLAGS_CLR(OLI_POLLING | OLI_TX_CLEANING | OLI_TX_STOP); /* initialize receive buffer descriptors */ for (ix = 0; ix < pDrvCtrl->rxBdNum; ix++) pDrvCtrl->rxBdBase[ix].statusMode = RX_BD_EMPTY; pDrvCtrl->rxBdNext = 0; /* initialize transmit buffer descriptors */ for (ix = 0; ix < pDrvCtrl->txBdNum; ix++) { pDrvCtrl->txBdBase[ix].dataPointer = (UCHAR *) addrC = (RAM_TX_BASE + (ix * OLI_MAX_XMT)); PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R12), addrC); PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R13), (addrC >> 8)); PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R14), TX_BD_READY); PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R15), (TX_BD_READY >> 8)); } pDrvCtrl->txBdNext = 0; pDrvCtrl->txBdIndexC = 0; /* configure promiscuous mode and multicast addresses list */ iOlicomConfig(pDrvCtrl); /* connect interrupt */ SYS_INT_CONNECT (pDrvCtrl, iOlicomInt, (int)pDrvCtrl, &result); if (result == ERROR) return ERROR; END_LOG_MSG (END_DEBUG_LOAD, "Interrupt connected.\n", 0, 0, 0, 0, 0, 0); /* set running & up flags */ END_FLAGS_SET (&pDrvCtrl->endObj, (IFF_UP | IFF_RUNNING)); /* enable interrupt */ SYS_INT_ENABLE (pDrvCtrl); END_LOG_MSG (END_DEBUG_LOAD, "Interrupt enabled.\n", 0, 0, 0, 0, 0, 0); return (OK); }/********************************************************************************* iOlicomIntHandle - interrupt service for card interrupts** This routine is called when an interrupt has been detected from the Olicom* card.** RETURNS: N/A.*/void iOlicomIntHandle ( END_DEVICE * pDrvCtrl /* pointer to END_DEVICE structure */ ) { int cardStat; int intStat; /* * Read the card configuration state to verify this is a card I/O * interrupt. */ cardStat = PCMCIA_ATTR_READ((int)(pDrvCtrl->pcmcia.oliAttribMem + CARDCONFREG1)); END_LOG_MSG (END_DEBUG_INT, "cardStat (config Reg 1) = 0x%X\n", cardStat, 0, 0, 0, 0, 0); /* I/O Interrupt, examine card to find out what */ if (cardStat & CREG1_INT_IO) { END_LOG_MSG (END_DEBUG_INT, "I/O interrupt\n", 0, 0, 0, 0, 0, 0); /* * Read the chip's interrupt status register to find out why * an IRQ was raised. */ intStat = PCMCIA_IO_READ((int)(pDrvCtrl->pcmcia.oliAddr + I595_R1)); END_LOG_MSG (END_DEBUG_INT, "intStat (595 Reg 1) = 0x%X\n", intStat, 0, 0, 0, 0, 0); /* * Decode the interrupt down and take action accordingly. Note * that there may be multiple IRQ sources pending. */ /* handle receive events */ if (intStat & BNK0_RX_IT) { /* netTask handles any input packets */ if (! DRV_FLAGS_ISSET(OLI_RCV_HANDLING)) { DRV_FLAGS_SET(OLI_RCV_HANDLING); (void)netJobAdd ((FUNCPTR)iOlicomRxIntHandle, (int)pDrvCtrl, 0,0,0,0); } /* Acknowledge receive interrupt */ PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R1), BNK0_RX_IT); } /* handle transmitter events */ if (intStat & BNK0_TX_IT) { /* * clean the transmit buffer descriptor queue if we have * received a transmit interrupt and if we are not already * cleaning this transmit queue. */ if (! DRV_FLAGS_ISSET(OLI_TX_CLEANING)) { DRV_FLAGS_SET(OLI_TX_CLEANING); (void)netJobAdd ((FUNCPTR)iOlicomTxBdQueueClean, (int)pDrvCtrl, 0,0,0,0); } /* Acknowledge transmit interrupts */ PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R1), BNK0_TX_IT); } /* Acknowledge all other interrupts - ignore events */ PCMCIA_IO_WRITE((int) (pDrvCtrl->pcmcia.oliAddr + I595_R1), ~(BNK0_TX_IT | BNK0_RX_IT)); if (DRV_FLAGS_ISSET(OLI_TX_STOP)) /* cause a restart */ { DRV_FLAGS_CLR(OLI_TX_STOP); netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj, 0, 0, 0, 0); } } return; }/********************************************************************************* iOlicomRxIntHandle - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.** RETURNS: N/A.*/LOCAL void iOlicomRxIntHandle ( END_DEVICE * pDrvCtrl /* pointer to END_DEVICE structure */ ) { RX_BD * pRxBd = iOlicomPacketGet (pDrvCtrl); END_LOG_MSG (END_DEBUG_RX, ("iOlicomRxIntHandle\n"), 0, 0, 0, 0, 0, 0); do { DRV_FLAGS_SET (OLI_RCV_HANDLING); while (pRxBd != NULL) { iOlicomRecv (pDrvCtrl, pRxBd); pRxBd = iOlicomPacketGet (pDrvCtrl); } DRV_FLAGS_CLR (OLI_RCV_HANDLING); /* check once more after resetting flags */ pRxBd = iOlicomPacketGet (pDrvCtrl); } while (pRxBd != NULL); }/********************************************************************************* iOlicomPacketGet - get next received message** Get next recevied message. Returns NULL if none are* ready.** RETURNS: ptr to next packet, or NULL if none ready.*/LOCAL RX_BD * iOlicomPacketGet ( END_DEVICE * pDrvCtrl /* pointer to END_DEVICE structure */ ) { int start; int event; int status; int length; int s; int nextStop; char * pData; RX_BD * pRxBd = &pDrvCtrl->rxBdBase[pDrvCtrl->rxBdNext]; END_LOG_MSG (END_DEBUG_RX, "iOlicomPacketGet oliAddr=0x%X\n", pDrvCtrl->pcmcia.oliAddr, 0, 0, 0, 0, 0); /* * 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. */ s = intLock(); start = PCMCIA_IO_READ((int)pDrvCtrl->pcmcia.oliAddr + I595_R6); start |= (PCMCIA_IO_READ((int)pDrvCtrl->pcmcia.oliAddr + I595_R7) << 8); start += 2; /* Handle the roll over case */ if (start > RAM_RX_LIMIT) start -= RAM_RX_BASE; END_LOG_MSG (END_DEBUG_RX, "start= 0x%X\n", start, 0, 0, 0, 0, 0); /* Set up address from where we wish to start reading data */ PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R12), start); PCMCIA_IO_WRITE((int)(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)) { intUnlock(s); return ((RX_BD *) NULL); } /* 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); END_LOG_MSG (END_DEBUG_RX, "length= 0x%X\n", length, 0, 0, 0, 0, 0); /* Check for errors */ if (!(status & RCV_OK)) { /* Bump input error packet counter */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); /* Update the STOP register from the next packet pointer */ PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R6), nextStop); PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R7), (nextStop >> 8)); intUnlock(s); return ((RX_BD *) NULL); } /* check if a receive buffer descriptor is available */ if (!(pRxBd->statusMode & RX_BD_EMPTY)) { /* Bump input error packet counter */ END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1); /* Update the STOP register from the next packet pointer */ PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R6), nextStop); PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R7), (nextStop >> 8)); intUnlock(s); return ((RX_BD *) NULL); } /* * We always read an even number of bytes from the controller, * so adjust the length if necessary. */ if ((length & ODD_MSK) != 0) ++length; pRxBd->dataLength = length; /* Read the data from the Rx ring buffer */ for (pData = pRxBd->dataPointer; length != 0; length -=2) READ_PTR_R14_R15 (pData); /* Update the STOP register from the next packet pointer */ PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R6), nextStop); PCMCIA_IO_WRITE((int)(pDrvCtrl->pcmcia.oliAddr + I595_R7), (nextStop >> 8)); /* Update status buffer descriptor */ pRxBd->statusMode = 0; /* incr buffer descriptor count */ pDrvCtrl->rxBdNext = (pDrvCtrl->rxBdNext + 1) % pDrvCtrl->rxBdNum; intUnlock(s); return (pRxBd); }/********************************************************************************* iOlicomRecv - process the next incoming packet** This routine processes an input frame, then passes it up to the higher* level in a form it expects.** RETURNS: OK, always.*/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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -