📄 skge.c
字号:
#ifdef CONFIG_PROC_FS /* Remove all Proc entries if last device */ if (sk98lin_max_boards_found == 0) { /* clear proc-dir */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)#ifndef SK_DISABLE_PROC_UNLOAD remove_proc_entry(pSkRootDir->name, proc_net);#endif#else remove_proc_entry(pSkRootDir->name, init_net.proc_net);#endif }#endif}/***************************************************************************** * * 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 __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC){short i;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;#ifndef SK_ASF unsigned long Flags; /* for the spin locks */#endif 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->InitLock); /* Init lock */ spin_lock_init(&pAC->SlowPathLock); spin_lock_init(&pAC->TxQueueLock); /* for Yukon2 chipsets */ spin_lock_init(&pAC->SetPutIndexLock); /* for Yukon2 chipsets */ /* level 0 init common modules here */#ifdef SK_ASF spin_lock(&pAC->SlowPathLock);#endif#ifndef SK_ASF spin_lock_irqsave(&pAC->SlowPathLock, Flags);#endif /* Does a RESET on board ...*/ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) { printk("HWInit (0) failed.\n");#ifdef SK_ASF spin_unlock(&pAC->SlowPathLock);#endif#ifndef SK_ASF spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);#endif 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);#ifdef SK_ASF SkAsfInit(pAC, pAC->IoBase, SK_INIT_DATA);#endif pAC->BoardLevel = SK_INIT_DATA; pAC->RxPort[0].RxBufSize = ETH_BUF_SIZE; pAC->RxPort[1].RxBufSize = ETH_BUF_SIZE; SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString); SK_PNMI_SET_DRIVER_VER(pAC, VerStr); /* level 1 init common modules here (HW init) */ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { printk("sk98lin: HWInit (1) failed.\n");#ifdef SK_ASF spin_unlock(&pAC->SlowPathLock);#endif#ifndef SK_ASF spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);#endif 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);#ifdef SK_ASF SkAsfInit(pAC, pAC->IoBase, SK_INIT_IO);#endif#ifdef Y2_RECOVERY /* mark entries invalid */ pAC->LastPort = 3; pAC->LastOpc = 0xFF;#endif /* Set chipset type support */ if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) || (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) || (pAC->GIni.GIChipId == CHIP_ID_YUKON_LP)) { pAC->ChipsetType = 1; /* Yukon chipset (descriptor logic) */ } else if (CHIP_ID_YUKON_2(pAC)) { pAC->ChipsetType = 2; /* Yukon2 chipset (list logic) */ } else { pAC->ChipsetType = 0; /* Genesis chipset (descriptor logic) */ } /* wake on lan support */ pAC->WolInfo.SupportedWolOptions = 0;#if defined (ETHTOOL_GWOL) && defined (ETHTOOL_SWOL) if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) { pAC->WolInfo.SupportedWolOptions = WAKE_MAGIC; if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { if (pAC->GIni.GIChipRev == 0) { pAC->WolInfo.SupportedWolOptions = 0; } } }#endif pAC->WolInfo.ConfiguredWolOptions = pAC->WolInfo.SupportedWolOptions; GetConfiguration(pAC); if (pAC->RlmtNets == 2) { pAC->GIni.GP[0].PPortUsage = SK_MUL_LINK; pAC->GIni.GP[1].PPortUsage = SK_MUL_LINK; } /* Set the tx moderation parameter */ if (pAC->TxModeration) { pAC->GIni.GITxIdxRepThres = pAC->TxModeration; } pAC->BoardLevel = SK_INIT_IO;#ifdef SK_ASF spin_unlock(&pAC->SlowPathLock);#endif#ifndef SK_ASF spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);#endif if (!CHIP_ID_YUKON_2(pAC)) { if (pAC->GIni.GIMacsFound == 2) {#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, dev->name, dev);#else Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, dev->name, dev);#endif } else if (pAC->GIni.GIMacsFound == 1) {#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, dev->name, dev);#else Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, dev->name, dev);#endif } else { printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n", pAC->GIni.GIMacsFound); return -EAGAIN; } } else {#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) Ret = request_irq(dev->irq, SkY2Isr, IRQF_SHARED, dev->name, dev);#else Ret = request_irq(dev->irq, SkY2Isr, SA_SHIRQ, dev->name, dev);#endif } if (Ret) { printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n", dev->irq); return -EAGAIN; } pAC->AllocFlag |= SK_ALLOC_IRQ; /* ** Alloc descriptor/LETable memory for this board (both RxD/TxD) */ if (CHIP_ID_YUKON_2(pAC)) { if (!SkY2AllocateResources(pAC)) { printk("No memory for Yukon2 settings\n"); return(-EAGAIN); } } else { if(!BoardAllocMem(pAC)) { printk("No memory for descriptor rings.\n"); return(-EAGAIN); } }#ifdef SK_USE_CSUM SkCsSetReceiveFlags(pAC, SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP, &pAC->CsOfs1, &pAC->CsOfs2, 0); pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1;#endif /* ** Function BoardInitMem() for Yukon dependent settings... */ BoardInitMem(pAC); /* tschilling: New common function with minimum size check. */ DualNet = SK_FALSE; if (pAC->RlmtNets == 2) { DualNet = SK_TRUE; } /* * Register the device here */ pAC->Next = SkGeRootDev; SkGeRootDev = dev; 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 (pAC->pDescrMem) {#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 or LETables 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")); if (!pAC->GIni.GIYukon2) { 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, &pAC->TxPort[i][0].TxdRingPrevFree, 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, &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 */int *pRingPrevFree, /* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -