⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 velocity_main.c

📁 VIA千兆网卡芯片VT6122的linux驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#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 + -