📄 skge.c
字号:
static void SetupRing(SK_AC *pAC,void *pMemArea, /* a pointer to the memory area for the ring */uintptr_t VMemArea, /* the virtual bus address of the memory area */RXD **ppRingHead, /* address where the head should be written */RXD **ppRingTail, /* address where the tail should be written */RXD **ppRingPrev, /* address where the tail should be written */int *pRingFree, /* address where the # of free descr. goes */SK_BOOL IsTx) /* flag: is this a tx ring */{int i; /* loop counter */int DescrSize; /* the size of a descriptor rounded up to alignment*/int DescrNum; /* number of descriptors per ring */RXD *pDescr; /* pointer to a descriptor (receive or transmit) */RXD *pNextDescr; /* pointer to the next descriptor */RXD *pPrevDescr; /* pointer to the previous descriptor */uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */ if (IsTx == SK_TRUE) { DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; DescrNum = TX_RING_SIZE / DescrSize; } else { DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; DescrNum = RX_RING_SIZE / DescrSize; } SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("Descriptor size: %d Descriptor Number: %d\n", DescrSize,DescrNum)); pDescr = (RXD*) pMemArea; pPrevDescr = NULL; pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); VNextDescr = VMemArea + DescrSize; for(i=0; i<DescrNum; i++) { /* set the pointers right */ pDescr->VNextRxd = VNextDescr & 0xffffffffULL; pDescr->pNextRxd = pNextDescr; pDescr->TcpSumStarts = pAC->CsOfs; /* advance one step */ pPrevDescr = pDescr; pDescr = pNextDescr; pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); VNextDescr += DescrSize; } pPrevDescr->pNextRxd = (RXD*) pMemArea; pPrevDescr->VNextRxd = VMemArea; pDescr = (RXD*) pMemArea; *ppRingHead = (RXD*) pMemArea; *ppRingTail = *ppRingHead; *ppRingPrev = pPrevDescr; *pRingFree = DescrNum;} /* SetupRing *//***************************************************************************** * * PortReInitBmu - re-initiate the descriptor rings for one port * * Description: * This function reinitializes the descriptor rings of one port * in memory. The port must be stopped before. * The HW is initialized with the descriptor start addresses. * * Returns: * none */static void PortReInitBmu(SK_AC *pAC, /* pointer to adapter context */int PortIndex) /* index of the port for which to re-init */{ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("PortReInitBmu ")); /* set address of first descriptor of ring in BMU */ SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ TX_Q_CUR_DESCR_LOW, (uint32_t)(((caddr_t) (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) & 0xFFFFFFFF)); SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ TX_Q_DESCR_HIGH, (uint32_t)(((caddr_t) (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32)); SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_CUR_DESCR_LOW, (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - pAC->RxPort[PortIndex].pRxDescrRing + pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF)); SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+RX_Q_DESCR_HIGH, (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - pAC->RxPort[PortIndex].pRxDescrRing + pAC->RxPort[PortIndex].VRxDescrRing) >> 32));} /* PortReInitBmu *//**************************************************************************** * * SkGeIsr - handle adapter interrupts * * Description: * The interrupt routine is called when the network adapter * generates an interrupt. It may also be called if another device * shares this interrupt vector with the driver. * * Returns: N/A * */#if 0static void SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs)#elsevoid SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs)#endif{struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;DEV_NET *pNet;SK_AC *pAC;SK_U32 IntSrc; /* interrupts source register contents */ pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; /* * Check and process if its our interrupt */ SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); if (IntSrc == 0) { return; } while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {#if 0 /* software irq currently not used */ if (IntSrc & IRQ_SW) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("Software IRQ\n")); }#endif if (IntSrc & IRQ_EOF_RX1) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF RX1 IRQ\n")); ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); SK_PNMI_CNT_RX_INTR(pAC, 0); } if (IntSrc & IRQ_EOF_RX2) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF RX2 IRQ\n")); ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); SK_PNMI_CNT_RX_INTR(pAC, 1); }#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ if (IntSrc & IRQ_EOF_AS_TX1) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF AS TX1 IRQ\n")); SK_PNMI_CNT_TX_INTR(pAC, 0); spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); } if (IntSrc & IRQ_EOF_AS_TX2) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF AS TX2 IRQ\n")); SK_PNMI_CNT_TX_INTR(pAC, 1); spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]); spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); }#if 0 /* only if sync. queues used */ if (IntSrc & IRQ_EOF_SY_TX1) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF SY TX1 IRQ\n")); SK_PNMI_CNT_TX_INTR(pAC, 1); spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); ClearTxIrq(pAC, 0, TX_PRIO_HIGH); } if (IntSrc & IRQ_EOF_SY_TX2) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF SY TX2 IRQ\n")); SK_PNMI_CNT_TX_INTR(pAC, 1); spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH); spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); ClearTxIrq(pAC, 1, TX_PRIO_HIGH); }#endif#endif /* do all IO at once */ if (IntSrc & IRQ_EOF_RX1) ClearAndStartRx(pAC, 0); if (IntSrc & IRQ_EOF_RX2) ClearAndStartRx(pAC, 1);#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ if (IntSrc & IRQ_EOF_AS_TX1) ClearTxIrq(pAC, 0, TX_PRIO_LOW); if (IntSrc & IRQ_EOF_AS_TX2) ClearTxIrq(pAC, 1, TX_PRIO_LOW);#endif SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); } /* while (IntSrc & IRQ_MASK != 0) */ if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("SPECIAL IRQ DP-Cards => %x\n", IntSrc)); pAC->CheckQueue = SK_FALSE; spin_lock(&pAC->SlowPathLock); if (IntSrc & SPECIAL_IRQS) SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); SkEventDispatcher(pAC, pAC->IoBase); spin_unlock(&pAC->SlowPathLock); } /* * do it all again is case we cleared an interrupt that * came in after handling the ring (OUTs may be delayed * in hardware buffers, but are through after IN) */ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); if (pAC->CheckQueue) { pAC->CheckQueue = SK_FALSE; spin_lock(&pAC->SlowPathLock); SkEventDispatcher(pAC, pAC->IoBase); spin_unlock(&pAC->SlowPathLock); } /* IRQ is processed - Enable IRQs again*/ SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); return;} /* SkGeIsr *//**************************************************************************** * * SkGeIsrOnePort - handle adapter interrupts for single port adapter * * Description: * The interrupt routine is called when the network adapter * generates an interrupt. It may also be called if another device * shares this interrupt vector with the driver. * This is the same as above, but handles only one port. * * Returns: N/A * */#if 0static void SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs)#elsevoid SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs)#endif{struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;DEV_NET *pNet;SK_AC *pAC;SK_U32 IntSrc; /* interrupts source register contents */ pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; /* * Check and process if its our interrupt */ SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); if (IntSrc == 0) { return; } while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {#if 0 /* software irq currently not used */ if (IntSrc & IRQ_SW) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("Software IRQ\n")); }#endif if (IntSrc & IRQ_EOF_RX1) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF RX1 IRQ\n")); ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); SK_PNMI_CNT_RX_INTR(pAC, 0); }#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ if (IntSrc & IRQ_EOF_AS_TX1) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF AS TX1 IRQ\n")); SK_PNMI_CNT_TX_INTR(pAC, 0); spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); }#if 0 /* only if sync. queues used */ if (IntSrc & IRQ_EOF_SY_TX1) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("EOF SY TX1 IRQ\n")); SK_PNMI_CNT_TX_INTR(pAC, 0); spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); ClearTxIrq(pAC, 0, TX_PRIO_HIGH); }#endif#endif /* do all IO at once */ if (IntSrc & IRQ_EOF_RX1) ClearAndStartRx(pAC, 0);#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ if (IntSrc & IRQ_EOF_AS_TX1) ClearTxIrq(pAC, 0, TX_PRIO_LOW);#endif SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); } /* while (IntSrc & IRQ_MASK != 0) */ if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, ("SPECIAL IRQ SP-Cards => %x\n", IntSrc)); pAC->CheckQueue = SK_FALSE; spin_lock(&pAC->SlowPathLock); if (IntSrc & SPECIAL_IRQS) SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); SkEventDispatcher(pAC, pAC->IoBase); spin_unlock(&pAC->SlowPathLock); } /* * do it all again is case we cleared an interrupt that * came in after handling the ring (OUTs may be delayed * in hardware buffers, but are through after IN) */ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); /* IRQ is processed - Enable IRQs again*/ SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); return;} /* SkGeIsrOnePort *//**************************************************************************** * * SkGeOpen - handle start of initialized adapter * * Description: * This function starts the initialized adapter. * The board level variable is set and the adapter is * brought to full functionality. * The device flags are set for operation. * Do all necessary level 2 initialization, enable interrupts and * give start command to RLMT. * * Returns: * 0 on success * != 0 on error */#if 0static int SkGeOpen(#elseint SkGeOpen(#endifstruct SK_NET_DEVICE *dev){ DEV_NET *pNet; SK_AC *pAC; unsigned long Flags; /* for spin lock */ int i; SK_EVPARA EvPara; /* an event parameter union */ pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC)); if (pAC->BoardLevel == 0) { /* level 1 init common modules here */ if (SkGeInit(pAC, pAC->IoBase, 1) != 0) { printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name); return (-1); } SkI2cInit (pAC, pAC->IoBase, 1); SkEventInit (pAC, pAC->IoBase, 1); SkPnmiInit (pAC, pAC->IoBase, 1); SkAddrInit (pAC, pAC->IoBase, 1); SkRlmtInit (pAC, pAC->IoBase, 1); SkTimerInit (pAC, pAC->IoBase, 1); pAC->BoardLevel = 1; } if (pAC->BoardLevel != 2) { /* tschilling: Level 2 init modules here, check return value. */ if (SkGeInit(pAC, pAC->IoBase, 2) != 0) { printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name); return (-1); } SkI2cInit (pAC, pAC->IoBase, 2); SkEventInit (pAC, pAC->IoBase, 2); SkPnmiInit (pAC, pAC->IoBase, 2); SkAddrInit (pAC, pAC->IoBase, 2); SkRlmtInit (pAC, pAC->IoBase, 2); SkTimerInit (pAC, pAC->IoBase, 2); pAC->BoardLevel = 2; } for (i=0; i<pAC->GIni.GIMacsFound; i++) { /* Enable transmit descriptor polling. */ SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); FillRxRing(pAC, &pAC->RxPort[i]); } SkGeYellowLED(pAC, pAC->IoBase, 1);#ifdef USE_INT_MOD/* moderate only TX complete interrupts (these are not time critical) */#define IRQ_MOD_MASK (IRQ_EOF_AS_TX1 | IRQ_EOF_AS_TX2) { unsigned long ModBase; ModBase = 53125000 / INTS_PER_SEC; SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK); SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); }#endif /* enable Interrupts */ SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); spin_lock_irqsave(&pAC->SlowPathLock, Flags); if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) { EvPara.Para32[0] = pAC->RlmtNets; EvPara.Para32[1] = -1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara); EvPara.Para32[0] = pAC->RlmtMode; EvPara.Para32[1] = 0; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE, EvPara); } EvPara.Para32[0] = pNet->NetNr; EvPara.Para32[1] = -1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); SkEventDispatcher(pAC, pAC->IoBase); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); pAC->MaxPorts++; pNet->Up = 1; MOD_INC_USE_COUNT; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeOpen suceeded\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -