📄 skge.c
字号:
pAC->IoBase = (char*)ioremap(base_address, 0x4000); if (!pAC->IoBase){ printk(KERN_ERR "%s: Unable to map I/O register, " "SK 98xx No. %i will be disabled.\n", dev->name, boards_found); break; } pAC->Index = boards_found; if (SkGeBoardInit(dev, pAC)) { FreeResources(dev); continue; } memcpy((caddr_t) &dev->dev_addr, (caddr_t) &pAC->Addr.CurrentMacAddress, 6); boards_found++; /* * This is bollocks, but we need to tell the net-init * code that it shall go for the next device. */#ifndef MODULE dev->base_addr = 0;#endif } /* * If we're at this point we're going through skge_probe() for * the first time. Return success (0) if we've initialized 1 * or more boards. Otherwise, return failure (-ENODEV). */ return boards_found;} /* skge_probe *//***************************************************************************** * * FreeResources - release resources allocated for adapter * * Description: * This function releases the IRQ, unmaps the IO and * frees the desriptor ring. * * Returns: N/A * */static void FreeResources(struct net_device *dev){SK_U32 AllocFlag;SK_AC *pAC; if (dev->priv) { pAC = (SK_AC*) dev->priv; AllocFlag = pAC->AllocFlag; if (AllocFlag & SK_ALLOC_IRQ) { free_irq(dev->irq, dev); } if (pAC->IoBase) { iounmap(pAC->IoBase); } if (pAC->pDescrMem) { BoardFreeMem(pAC); } } } /* FreeResources */MODULE_AUTHOR("Christoph Goos <cgoos@syskonnect.de>");MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");MODULE_PARM(AutoNeg_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");MODULE_PARM(DupCap_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");MODULE_PARM(DupCap_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");MODULE_PARM(FlowCtrl_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");MODULE_PARM(Role_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");MODULE_PARM(PrefPort, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");/* not used, just there because every driver should have them: */MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");MODULE_PARM(debug, "i");#ifdef AUTO_NEG_Astatic char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A;#elsestatic char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", };#endif#ifdef DUP_CAP_Astatic char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A;#elsestatic char *DupCap_A[SK_MAX_CARD_PARAM] = {"", };#endif#ifdef FLOW_CTRL_Astatic char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A;#elsestatic char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", };#endif#ifdef ROLE_Astatic char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A;#elsestatic char *Role_A[SK_MAX_CARD_PARAM] = {"", };#endif#ifdef AUTO_NEG_Bstatic char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B;#elsestatic char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", };#endif#ifdef DUP_CAP_Bstatic char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B;#elsestatic char *DupCap_B[SK_MAX_CARD_PARAM] = {"", };#endif#ifdef FLOW_CTRL_Bstatic char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B;#elsestatic char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", };#endif#ifdef ROLE_Bstatic char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B;#elsestatic char *Role_B[SK_MAX_CARD_PARAM] = {"", };#endif#ifdef PREF_PORTstatic char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT;#elsestatic char *PrefPort[SK_MAX_CARD_PARAM] = {"", };#endif#ifdef RLMT_MODEstatic char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE;#elsestatic char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };#endifstatic int debug = 0; /* not used */static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used *//***************************************************************************** * * skge_init_module - module initialization function * * Description: * Very simple, only call skge_probe and return approriate result. * * Returns: * 0, if everything is ok * !=0, on error */static int __init skge_init_module(void){ int cards; root_dev = NULL; /* just to avoid warnings ... */ debug = 0; options[0] = 0; cards = skge_probe(); if (cards == 0) { printk("No adapter found\n"); } return cards ? 0 : -ENODEV;} /* skge_init_module *//***************************************************************************** * * skge_cleanup_module - module unload function * * Description: * Disable adapter if it is still running, free resources, * free device struct. * * Returns: N/A */static void __exit skge_cleanup_module(void){SK_AC *pAC;struct net_device *next;unsigned long Flags;SK_EVPARA EvPara; while (root_dev) { pAC = (SK_AC*)root_dev->priv; next = pAC->Next; netif_stop_queue(root_dev); SkGeYellowLED(pAC, pAC->IoBase, 0); if(pAC->BoardLevel == 2) { /* board is still alive */ spin_lock_irqsave(&pAC->SlowPathLock, Flags); SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); SkEventDispatcher(pAC, pAC->IoBase); /* disable interrupts */ SK_OUT32(pAC->IoBase, B0_IMSK, 0); SkGeDeInit(pAC, pAC->IoBase); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); pAC->BoardLevel = 0; /* We do NOT check here, if IRQ was pending, of course*/ } if(pAC->BoardLevel == 1) { /* board is still alive */ SkGeDeInit(pAC, pAC->IoBase); pAC->BoardLevel = 0; } FreeResources(root_dev); root_dev->get_stats = NULL; /* * otherwise unregister_netdev calls get_stats with * invalid IO ... :-( */ unregister_netdev(root_dev); kfree(root_dev); root_dev = next; }} /* skge_cleanup_module */module_init(skge_init_module);module_exit(skge_cleanup_module);/***************************************************************************** * * 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 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_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); /* level 0 init common modules here */ spin_lock_irqsave(&pAC->SlowPathLock, Flags); /* Does a RESET on board ...*/ if (SkGeInit(pAC, pAC->IoBase, 0) != 0) { printk("HWInit (0) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); return(-EAGAIN); } SkI2cInit( pAC, pAC->IoBase, 0); SkEventInit(pAC, pAC->IoBase, 0); SkPnmiInit( pAC, pAC->IoBase, 0); SkAddrInit( pAC, pAC->IoBase, 0); SkRlmtInit( pAC, pAC->IoBase, 0); SkTimerInit(pAC, pAC->IoBase, 0); pAC->BoardLevel = 0; 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); GetConfiguration(pAC); /* level 1 init common modules here (HW init) */ spin_lock_irqsave(&pAC->SlowPathLock, Flags); if (SkGeInit(pAC, pAC->IoBase, 1) != 0) { printk("HWInit (1) failed.\n"); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); return(-EAGAIN); } 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; 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 "%s: illegal number of ports: %d\n", dev->name, pAC->GIni.GIMacsFound); return -EAGAIN; } if (Ret) { printk(KERN_WARNING "%s: Requested IRQ %d is busy\n", dev->name, 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); } SkCsSetReceiveFlags(pAC, SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP, &pAC->CsOfs1, &pAC->CsOfs2); pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1; BoardInitMem(pAC); SetQueueSizes(pAC); /* Print adapter specific string from vpd */ ProductStr(pAC); printk("%s: %s\n", dev->name, pAC->DeviceStr); /* Print configuration settings */ printk(" PrefPort:%c RlmtMode:%s\n", 'A' + pAC->Rlmt.PrefPort, (pAC->RlmtMode==0) ? "ChkLink" : ((pAC->RlmtMode==1) ? "ChkLink" : ((pAC->RlmtMode==3) ? "ChkOth" : ((pAC->RlmtMode==7) ? "ChkSeg" : "Error")))); SkGeYellowLED(pAC, pAC->IoBase, 1); /* * Register the device here */ pAC->Next = root_dev; root_dev = 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; /* Descriptors need 8 byte alignment, and this is ensured * by pci_alloc_consistent. */ BusAddr = (unsigned long) pAC->pDescrMemDMA; 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -