📄 iolicomend.c
字号:
* memory size adjusted to hold the netPool pointer at the head. */ oliMclBlkConfig.memSize = ((oliMclBlkConfig.mBlkNum * (MSIZE + sizeof (long))) + (oliMclBlkConfig.clBlkNum * (CL_BLK_SZ + sizeof (long)))); if ((oliMclBlkConfig.memArea = (char *)memalign(sizeof (long), oliMclBlkConfig.memSize)) == NULL) return (ERROR); clDesc.clSize = OLI_BUFSIZ; clDesc.memSize = ((clDesc.clNum * (clDesc.clSize + 4)) + 4); if (DRV_FLAGS_ISSET(OLI_MEMOWN)) { clDesc.memArea = malloc (clDesc.memSize); if (clDesc.memArea == NULL) { END_LOG_MSG (END_DEBUG_LOAD, "%s%d - system memory unavailable\n", DRV_NAME, pDrvCtrl->unit, 0, 0, 0, 0); return (ERROR); } } 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 = (char *) 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_ALL_FUNCS, "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 = (char *)(addrC = (RAM_TX_BASE + (ix * OLI_MAX_XMT))); PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R12, addrC); PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R13, (addrC >> 8)); WRITE_R14_R15 (TX_BD_READY); } 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(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(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(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(pDrvCtrl->pcmcia.oliAddr + I595_R1, BNK0_TX_IT); } /* Acknowledge all other interrupts - ignore events */ PCMCIA_IO_WRITE(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 received 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; UINT8 * pData; UINT8 * pDataEnd; RX_BD * pRxBd = &pDrvCtrl->rxBdBase[pDrvCtrl->rxBdNext]; volatile UINT8 * pR14; 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(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; 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(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)) { 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(pDrvCtrl->pcmcia.oliAddr + I595_R6, nextStop); PCMCIA_IO_WRITE(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(pDrvCtrl->pcmcia.oliAddr + I595_R6, nextStop); PCMCIA_IO_WRITE(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. * * 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 (pData = (UINT8 *)pRxBd->dataPointer, pDataEnd = pData + length; pData != pDataEnd; ) READ_PTR_R14_R15 (pData, pR14); END_LOG_MSG (END_DEBUG_RX, "data = 0x%X 0x%X\n", (pRxBd->dataPointer)[0], (pRxBd->dataPointer)[1], 0, 0, 0, 0); /* 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)); /* 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.*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -