📄 skge.c
字号:
#endifstatic int IntsPerSec[SK_MAX_CARD_PARAM];static char *Moderation[SK_MAX_CARD_PARAM];static char *ModerationMask[SK_MAX_CARD_PARAM];static char *AutoSizing[SK_MAX_CARD_PARAM];static char *Stats[SK_MAX_CARD_PARAM];module_param_array(Speed_A, charp, NULL, 0);module_param_array(Speed_B, charp, NULL, 0);module_param_array(AutoNeg_A, charp, NULL, 0);module_param_array(AutoNeg_B, charp, NULL, 0);module_param_array(DupCap_A, charp, NULL, 0);module_param_array(DupCap_B, charp, NULL, 0);module_param_array(FlowCtrl_A, charp, NULL, 0);module_param_array(FlowCtrl_B, charp, NULL, 0);module_param_array(Role_A, charp, NULL, 0);module_param_array(Role_B, charp, NULL, 0);module_param_array(ConType, charp, NULL, 0);module_param_array(PrefPort, charp, NULL, 0);module_param_array(RlmtMode, charp, NULL, 0);/* used for interrupt moderation */module_param_array(IntsPerSec, int, NULL, 0);module_param_array(Moderation, charp, NULL, 0);module_param_array(Stats, charp, NULL, 0);module_param_array(ModerationMask, charp, NULL, 0);module_param_array(AutoSizing, charp, NULL, 0);/***************************************************************************** * * SkGeBoardInit - do level 0 and 1 initialization * * Description: * This function prepares the board hardware for running. The desriptor * ring is set up, the IRQ is allocated and the configuration settings * are examined. * * Returns: * 0, if everything is ok * !=0, on error */static int __init SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC){short i;unsigned long Flags;char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */char *VerStr = VER_STRING;int Ret; /* return code of request_irq */SK_BOOL DualNet; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("IoBase: %08lX\n", (unsigned long)pAC->IoBase)); for (i=0; i<SK_MAX_MACS; i++) { pAC->TxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0]; pAC->TxPort[i][0].PortIndex = i; pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i]; pAC->RxPort[i].PortIndex = i; } /* Initialize the mutexes */ for (i=0; i<SK_MAX_MACS; i++) { spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock); spin_lock_init(&pAC->RxPort[i].RxDesRingLock); } spin_lock_init(&pAC->SlowPathLock); /* setup phy_id blink timer */ pAC->BlinkTimer.function = SkGeBlinkTimer; pAC->BlinkTimer.data = (unsigned long) dev; init_timer(&pAC->BlinkTimer); /* level 0 init common modules here */ spin_lock_irqsave(&pAC->SlowPathLock, Flags); /* Does a RESET on board ...*/ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) { printk("HWInit (0) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); return(-EAGAIN); } SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA); SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA); SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA); SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA); SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA); SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA); pAC->BoardLevel = SK_INIT_DATA; pAC->RxBufSize = ETH_BUF_SIZE; SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString); SK_PNMI_SET_DRIVER_VER(pAC, VerStr); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); /* level 1 init common modules here (HW init) */ spin_lock_irqsave(&pAC->SlowPathLock, Flags); if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { printk("sk98lin: HWInit (1) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); return(-EAGAIN); } SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO); SkEventInit(pAC, pAC->IoBase, SK_INIT_IO); SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO); SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO); SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO); SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO); /* Set chipset type support */ pAC->ChipsetType = 0; if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) || (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) { pAC->ChipsetType = 1; } GetConfiguration(pAC); if (pAC->RlmtNets == 2) { pAC->GIni.GIPortUsage = SK_MUL_LINK; } pAC->BoardLevel = SK_INIT_IO; spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); if (pAC->GIni.GIMacsFound == 2) { Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev); } else if (pAC->GIni.GIMacsFound == 1) { Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, pAC->Name, dev); } else { printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n", pAC->GIni.GIMacsFound); return -EAGAIN; } if (Ret) { printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n", dev->irq); return -EAGAIN; } pAC->AllocFlag |= SK_ALLOC_IRQ; /* Alloc memory for this board (Mem for RxD/TxD) : */ if(!BoardAllocMem(pAC)) { printk("No memory for descriptor rings.\n"); return(-EAGAIN); } BoardInitMem(pAC); /* tschilling: New common function with minimum size check. */ DualNet = SK_FALSE; if (pAC->RlmtNets == 2) { DualNet = SK_TRUE; } if (SkGeInitAssignRamToQueues( pAC, pAC->ActivePort, DualNet)) { BoardFreeMem(pAC); printk("sk98lin: SkGeInitAssignRamToQueues failed.\n"); return(-EAGAIN); } return (0);} /* SkGeBoardInit *//***************************************************************************** * * BoardAllocMem - allocate the memory for the descriptor rings * * Description: * This function allocates the memory for all descriptor rings. * Each ring is aligned for the desriptor alignment and no ring * has a 4 GByte boundary in it (because the upper 32 bit must * be constant for all descriptiors in one rings). * * Returns: * SK_TRUE, if all memory could be allocated * SK_FALSE, if not */static SK_BOOL BoardAllocMem(SK_AC *pAC){caddr_t pDescrMem; /* pointer to descriptor memory area */size_t AllocLength; /* length of complete descriptor area */int i; /* loop counter */unsigned long BusAddr; /* rings plus one for alignment (do not cross 4 GB boundary) */ /* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */#if (BITS_PER_LONG == 32) AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;#else AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + RX_RING_SIZE + 8;#endif pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength, &pAC->pDescrMemDMA); if (pDescrMem == NULL) { return (SK_FALSE); } pAC->pDescrMem = pDescrMem; BusAddr = (unsigned long) pAC->pDescrMemDMA; /* Descriptors need 8 byte alignment, and this is ensured * by pci_alloc_consistent. */ for (i=0; i<pAC->GIni.GIMacsFound; i++) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n", i, (unsigned long) pDescrMem, BusAddr)); pAC->TxPort[i][0].pTxDescrRing = pDescrMem; pAC->TxPort[i][0].VTxDescrRing = BusAddr; pDescrMem += TX_RING_SIZE; BusAddr += TX_RING_SIZE; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("RX%d: pDescrMem: %lX, PhysDescrMem: %lX\n", i, (unsigned long) pDescrMem, (unsigned long)BusAddr)); pAC->RxPort[i].pRxDescrRing = pDescrMem; pAC->RxPort[i].VRxDescrRing = BusAddr; pDescrMem += RX_RING_SIZE; BusAddr += RX_RING_SIZE; } /* for */ return (SK_TRUE);} /* BoardAllocMem *//**************************************************************************** * * BoardFreeMem - reverse of BoardAllocMem * * Description: * Free all memory allocated in BoardAllocMem: adapter context, * descriptor rings, locks. * * Returns: N/A */static void BoardFreeMem(SK_AC *pAC){size_t AllocLength; /* length of complete descriptor area */ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("BoardFreeMem\n"));#if (BITS_PER_LONG == 32) AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;#else AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + RX_RING_SIZE + 8;#endif pci_free_consistent(pAC->PciDev, AllocLength, pAC->pDescrMem, pAC->pDescrMemDMA); pAC->pDescrMem = NULL;} /* BoardFreeMem *//***************************************************************************** * * BoardInitMem - initiate the descriptor rings * * Description: * This function sets the descriptor rings up in memory. * The adapter is initialized with the descriptor start addresses. * * Returns: N/A */static void BoardInitMem(SK_AC *pAC) /* pointer to adapter context */{int i; /* loop counter */int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/int TxDescrSize; /* the size of a tx descriptor rounded up to alignment*/ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("BoardInitMem\n")); RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize; TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize; for (i=0; i<pAC->GIni.GIMacsFound; i++) { SetupRing( pAC, pAC->TxPort[i][0].pTxDescrRing, pAC->TxPort[i][0].VTxDescrRing, (RXD**)&pAC->TxPort[i][0].pTxdRingHead, (RXD**)&pAC->TxPort[i][0].pTxdRingTail, (RXD**)&pAC->TxPort[i][0].pTxdRingPrev, &pAC->TxPort[i][0].TxdRingFree, SK_TRUE); SetupRing( pAC, pAC->RxPort[i].pRxDescrRing, pAC->RxPort[i].VRxDescrRing, &pAC->RxPort[i].pRxdRingHead, &pAC->RxPort[i].pRxdRingTail, &pAC->RxPort[i].pRxdRingPrev, &pAC->RxPort[i].RxdRingFree, SK_FALSE); }} /* BoardInitMem *//***************************************************************************** * * SetupRing - create one descriptor ring * * Description: * This function creates one descriptor ring in the given memory area. * The head, tail and number of free descriptors in the ring are set. * * Returns: * none */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; if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN; /* 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]+ Q_DA_L, (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]+ Q_DA_H, (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]+Q_DA_L, (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - pAC->RxPort[PortIndex].pRxDescrRing + pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF)); SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H, (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 * */static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs){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 = netdev_priv(dev); pAC = pNet->pAC; /* * Check and process if its our interrupt */ SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); if (IntSrc == 0) { return SkIsrRetNone; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -