📄 velocity_main.c
字号:
#ifdef CONFIG_PM unregister_reboot_notifier(&velocity_notifier); unregister_inetaddr_notifier(&velocity_inetaddr_notifier);#endif#endif pci_unregister_driver(&velocity_driver);}module_init(velocity_init_module);module_exit(velocity_cleanup_module);/**************************************************************************** ETHTOOL ioctl support routine****************************************************************************/#ifdef VELOCITY_ETHTOOL_IOCTL_SUPPORTstatic int velocity_ethtool_ioctl(struct net_device* dev, struct ifreq* ifr){ struct ethtool_cmd ecmd; PVELOCITY_INFO pInfo = netdev_priv(dev); //PMAC_REGS pMacRegs = pInfo->pMacRegs; if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd.cmd))) return -EFAULT; switch (ecmd.cmd) { case ETHTOOL_GSET: { U32 status=check_connectiontype(&pInfo->hw); ecmd.supported= SUPPORTED_TP|SUPPORTED_Autoneg|SUPPORTED_10baseT_Half|SUPPORTED_10baseT_Full |SUPPORTED_100baseT_Half|SUPPORTED_100baseT_Full|SUPPORTED_1000baseT_Half|SUPPORTED_1000baseT_Full; if (status & VELOCITY_SPEED_100) ecmd.speed=SPEED_100; else ecmd.speed=SPEED_10; ecmd.autoneg=(status & VELOCITY_AUTONEG_ENABLE) ? AUTONEG_ENABLE : AUTONEG_DISABLE; ecmd.port=PORT_TP; ecmd.transceiver=XCVR_INTERNAL; ecmd.phy_address=CSR_READ_1(&pInfo->hw, MAC_REG_MIIADR) & 0x1F; if (status & VELOCITY_DUPLEX_FULL) ecmd.duplex=DUPLEX_FULL; else ecmd.duplex=DUPLEX_HALF; if(copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd))) return -EFAULT; } break; case ETHTOOL_SSET: { U32 curr_status; U32 new_status=0; if (!capable(CAP_NET_ADMIN)){ return -EPERM; } if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd))) return -EFAULT; curr_status=check_connectiontype(&pInfo->hw); curr_status&=(~VELOCITY_LINK_FAIL); new_status|=((ecmd.autoneg) ? VELOCITY_AUTONEG_ENABLE : 0); new_status|=((ecmd.speed==SPEED_100) ? VELOCITY_SPEED_100 : 0); new_status|=((ecmd.speed==SPEED_10) ? VELOCITY_SPEED_10 : 0); new_status|=((ecmd.duplex==DUPLEX_FULL) ? VELOCITY_DUPLEX_FULL : 0); if ((new_status & VELOCITY_AUTONEG_ENABLE) && (new_status!=(curr_status| VELOCITY_AUTONEG_ENABLE))) return -EINVAL; //------------------------------------------------------------ // [1.18] Save ConnectionType Info when via Ethertool if (new_status & VELOCITY_AUTONEG_ENABLE) { pInfo->hw.sOpts.spd_dpx = SPD_DPX_AUTO; // 0 } else { if (new_status & VELOCITY_SPEED_100) { if (new_status & VELOCITY_DUPLEX_FULL) { // 100-Full pInfo->hw.sOpts.spd_dpx = SPD_DPX_100_FULL; // 2 } else { // 100-Half pInfo->hw.sOpts.spd_dpx = SPD_DPX_100_HALF; // 1 } } else { if (new_status & VELOCITY_DUPLEX_FULL) { // 10-Full pInfo->hw.sOpts.spd_dpx = SPD_DPX_10_FULL; // 4 } else { // 10-Half pInfo->hw.sOpts.spd_dpx = SPD_DPX_10_HALF; // 3 } } } //------------------------------------------------------------ velocity_set_media_mode(&pInfo->hw,pInfo->hw.sOpts.spd_dpx); } break;#ifdef ETHTOOL_GLINK case ETHTOOL_GLINK: { struct ethtool_value info; memset((void *)&info, 0, sizeof(info)); info.cmd = ETHTOOL_GLINK; info.data = BYTE_REG_BITS_IS_ON(&pInfo->hw, PHYSR0_LINKGD, MAC_REG_PHYSR0) ? FALSE : TRUE; if (copy_to_user(ifr->ifr_data, &info, sizeof(info))) return -EFAULT; } break;#endif#ifdef ETHTOOL_GDRVINFO case ETHTOOL_GDRVINFO: { struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; strcpy(info.driver, VELOCITY_NAME); strcpy(info.version, VELOCITY_VERSION);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) strcpy(info.bus_info, pci_name(pInfo->pcid));#else strcpy(info.bus_info,pInfo->pcid->slot_name);#endif if (copy_to_user(ifr->ifr_data, &info, sizeof(info))) return -EFAULT; } break;#endif#ifdef ETHTOOL_GWOL case ETHTOOL_GWOL: { struct ethtool_wolinfo wol = {ETHTOOL_GWOL}; memset(&wol, 0, sizeof(wol)); wol.supported = WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_ARP; wol.wolopts |= WAKE_MAGIC; if (pInfo->wol_opts & VELOCITY_WOL_UCAST) wol.wolopts |= WAKE_UCAST; if (pInfo->wol_opts & VELOCITY_WOL_ARP) wol.wolopts |= WAKE_ARP; memcpy(&wol.sopass, pInfo->wol_passwd, 6); if (copy_to_user(ifr->ifr_data, &wol, sizeof(wol))) return -EFAULT; } break;#endif#ifdef ETHTOOL_SWOL case ETHTOOL_SWOL: { struct ethtool_wolinfo wol; if (copy_from_user(&wol, ifr->ifr_data, sizeof(wol))) return -EFAULT; if (!(wol.wolopts & (WAKE_PHY|WAKE_MAGIC|WAKE_UCAST|WAKE_ARP))) return -EFAULT; pInfo->wol_opts = VELOCITY_WOL_MAGIC; if (wol.wolopts & WAKE_MAGIC) { pInfo->wol_opts |= VELOCITY_WOL_MAGIC; pInfo->hw.flags |= VELOCITY_FLAGS_WOL_ENABLED; } if (wol.wolopts & WAKE_UCAST) { pInfo->wol_opts |= VELOCITY_WOL_UCAST; pInfo->hw.flags |= VELOCITY_FLAGS_WOL_ENABLED; } if (wol.wolopts & WAKE_ARP) { pInfo->wol_opts |= VELOCITY_WOL_ARP; pInfo->hw.flags |= VELOCITY_FLAGS_WOL_ENABLED; } memcpy(pInfo->wol_passwd,wol.sopass,6); if (copy_to_user(ifr->ifr_data, &wol, sizeof(wol))) return -EFAULT; } break;#endif#ifdef ETHTOOL_GMSGLVL case ETHTOOL_GMSGLVL: { struct ethtool_value edata = {ETHTOOL_GMSGLVL}; edata.data = msglevel; if (copy_to_user(ifr->ifr_data, &edata, sizeof(edata))) return -EFAULT; } break;#endif#ifdef ETHTOOL_SMSGLVL case ETHTOOL_SMSGLVL: { struct ethtool_value edata={ETHTOOL_SMSGLVL}; if (copy_from_user(&edata, ifr->ifr_data, sizeof(edata))) return -EFAULT; msglevel = edata.data; } break;#endif default: return -EOPNOTSUPP; } return 0;}#endif // VELOCITY_ETHTOOL_IOCTL_SUPPORT/**************************************************************************** MII ioctl support routine****************************************************************************/#ifdef VELOCITY_MII_IOCTL_SUPPORTstatic int velocity_mii_ioctl(struct net_device* dev, struct ifreq* ifr, int cmd){ PVELOCITY_INFO pInfo = netdev_priv(dev); //PMAC_REGS pMacRegs = pInfo->pMacRegs; unsigned long flags; struct mii_ioctl_data* pMiiData = (struct mii_ioctl_data*)&(ifr->ifr_data); switch(cmd) { case SIOCGMIIPHY: pMiiData->phy_id=CSR_READ_1(&pInfo->hw, MAC_REG_MIIADR) & 0x1f; break; case SIOCGMIIREG: if (!capable(CAP_NET_ADMIN)) return -EPERM; velocity_mii_read(&pInfo->hw,pMiiData->reg_num & 0x1f, &(pMiiData->val_out)); break; case SIOCSMIIREG: if (!capable(CAP_NET_ADMIN)) return -EPERM; spin_lock_irqsave(&pInfo->lock, flags); velocity_mii_write(&pInfo->hw,pMiiData->reg_num & 0x1f,pMiiData->val_in); spin_unlock_irqrestore(&pInfo->lock,flags); pInfo->hw.mii_status = check_connectiontype(&pInfo->hw); break; default: return -EOPNOTSUPP; } return 0;}#endif // VELOCITY_MII_IOCTL_SUPPORT#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,9)#ifdef CONFIG_PMstatic intvelocity_notify_reboot(struct notifier_block *nb, unsigned long event, void *p){ struct pci_dev *pcid = NULL; switch(event) { case SYS_DOWN: case SYS_HALT: case SYS_POWER_OFF:#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) while ((pcid = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcid)) != NULL) {#else pci_for_each_dev(pcid) {#endif if(pci_dev_driver(pcid) == &velocity_driver) { if (pci_get_drvdata(pcid))#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) velocity_suspend(pcid, PMSG_SUSPEND);#else velocity_suspend(pcid, PCI_D3hot);#endif } } } return NOTIFY_DONE;}static int#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)velocity_suspend(struct pci_dev *pcid, pm_message_t state)#elsevelocity_suspend(struct pci_dev *pcid, u32 state)#endif{ PVELOCITY_INFO pInfo = pci_get_drvdata(pcid); struct net_device *dev = pInfo->dev; unsigned long flags; int power_status; // to silence the compiler netif_stop_queue(dev); spin_lock_irqsave(&pInfo->lock, flags);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) pci_save_state(pcid);#else pci_save_state(pcid, pInfo->pci_state);#endif#ifdef ETHTOOL_GWOL if (pInfo->hw.flags & VELOCITY_FLAGS_WOL_ENABLED) { velocity_get_ip(pInfo); velocity_save_mac_context(&pInfo->hw, &pInfo->mac_context); velocity_save_pci_context(pInfo, &pInfo->pci_context); velocity_shutdown(&pInfo->hw); velocity_set_wol(pInfo); power_status = pci_enable_wake(pcid, PCI_D3hot, 1); power_status = pci_set_power_state(pcid, PCI_D3hot); } else { velocity_save_mac_context(&pInfo->hw, &pInfo->mac_context); velocity_save_pci_context(pInfo, &pInfo->pci_context); velocity_shutdown(&pInfo->hw); pci_disable_device(pcid);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state));#else power_status = pci_set_power_state(pcid, state);#endif } #else // !ETHTOOL_GWOL pci_disable_device(pcid);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) power_status = pci_set_power_state(pcid, pci_choose_state(pcid, state));#else power_status = pci_set_power_state(pcid, state);#endif #endif spin_unlock_irqrestore(&pInfo->lock, flags); return 0;}static intvelocity_resume(struct pci_dev *pcid){ PVELOCITY_INFO pInfo = pci_get_drvdata(pcid); struct net_device *dev = pInfo->dev; unsigned long flags; int power_status; // to silence the compiler power_status = pci_set_power_state(pcid, PCI_D0); power_status = pci_enable_wake(pcid, PCI_D0, 0);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) pci_restore_state(pcid);#else pci_restore_state(pcid, pInfo->pci_state);#endif mac_wol_reset(&pInfo->hw); if (netif_running(dev)) { int i; spin_lock_irqsave(&pInfo->lock, flags); velocity_restore_mac_context(&pInfo->hw, &pInfo->mac_context); velocity_restore_pci_context(pInfo, pInfo->pci_context); velocity_init_adapter(pInfo, VELOCITY_INIT_WOL); mac_disable_int(&pInfo->hw); velocity_tx_srv(pInfo, 0); for (i=0;i<pInfo->hw.nTxQueues;i++) { if (pInfo->hw.iTDUsed[i]) { mac_tx_queue_wake(&pInfo->hw, i); } } mac_enable_int(&pInfo->hw); netif_start_queue(dev); spin_unlock_irqrestore(&pInfo->lock, flags); } return 0;}static intvelocity_netdev_event( struct notifier_block *nb, unsigned long notification, void *ptr ){ struct in_ifaddr* ifa = (struct in_ifaddr*)ptr; struct net_device* dev; PVELOCITY_INFO pInfo; if (ifa) { dev = ifa->ifa_dev->dev; for (pInfo=pVelocity3_Infos; pInfo; pInfo=pInfo->next) { if (pInfo->dev == dev) velocity_get_ip(pInfo); } } return NOTIFY_DONE;}#endif // CONFIG_PM#endif // KERNEL_VERSION(2,4,9)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -