diff options
-rw-r--r-- | drivers/net/sk98lin/skge.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index d4913c3de2a1..a5d41ebc9fb4 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c | |||
@@ -113,6 +113,7 @@ | |||
113 | #include <linux/init.h> | 113 | #include <linux/init.h> |
114 | #include <linux/dma-mapping.h> | 114 | #include <linux/dma-mapping.h> |
115 | #include <linux/ip.h> | 115 | #include <linux/ip.h> |
116 | #include <linux/mii.h> | ||
116 | 117 | ||
117 | #include "h/skdrv1st.h" | 118 | #include "h/skdrv1st.h" |
118 | #include "h/skdrv2nd.h" | 119 | #include "h/skdrv2nd.h" |
@@ -2843,6 +2844,56 @@ unsigned long Flags; /* for spin lock */ | |||
2843 | return(&pAC->stats); | 2844 | return(&pAC->stats); |
2844 | } /* SkGeStats */ | 2845 | } /* SkGeStats */ |
2845 | 2846 | ||
2847 | /* | ||
2848 | * Basic MII register access | ||
2849 | */ | ||
2850 | static int SkGeMiiIoctl(struct net_device *dev, | ||
2851 | struct mii_ioctl_data *data, int cmd) | ||
2852 | { | ||
2853 | DEV_NET *pNet = netdev_priv(dev); | ||
2854 | SK_AC *pAC = pNet->pAC; | ||
2855 | SK_IOC IoC = pAC->IoBase; | ||
2856 | int Port = pNet->PortNr; | ||
2857 | SK_GEPORT *pPrt = &pAC->GIni.GP[Port]; | ||
2858 | unsigned long Flags; | ||
2859 | int err = 0; | ||
2860 | int reg = data->reg_num & 0x1f; | ||
2861 | SK_U16 val = data->val_in; | ||
2862 | |||
2863 | if (!netif_running(dev)) | ||
2864 | return -ENODEV; /* Phy still in reset */ | ||
2865 | |||
2866 | spin_lock_irqsave(&pAC->SlowPathLock, Flags); | ||
2867 | switch(cmd) { | ||
2868 | case SIOCGMIIPHY: | ||
2869 | data->phy_id = pPrt->PhyAddr; | ||
2870 | |||
2871 | /* fallthru */ | ||
2872 | case SIOCGMIIREG: | ||
2873 | if (pAC->GIni.GIGenesis) | ||
2874 | SkXmPhyRead(pAC, IoC, Port, reg, &val); | ||
2875 | else | ||
2876 | SkGmPhyRead(pAC, IoC, Port, reg, &val); | ||
2877 | |||
2878 | data->val_out = val; | ||
2879 | break; | ||
2880 | |||
2881 | case SIOCSMIIREG: | ||
2882 | if (!capable(CAP_NET_ADMIN)) | ||
2883 | err = -EPERM; | ||
2884 | |||
2885 | else if (pAC->GIni.GIGenesis) | ||
2886 | SkXmPhyWrite(pAC, IoC, Port, reg, val); | ||
2887 | else | ||
2888 | SkGmPhyWrite(pAC, IoC, Port, reg, val); | ||
2889 | break; | ||
2890 | default: | ||
2891 | err = -EOPNOTSUPP; | ||
2892 | } | ||
2893 | spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); | ||
2894 | return err; | ||
2895 | } | ||
2896 | |||
2846 | 2897 | ||
2847 | /***************************************************************************** | 2898 | /***************************************************************************** |
2848 | * | 2899 | * |
@@ -2876,6 +2927,9 @@ int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32); | |||
2876 | pNet = netdev_priv(dev); | 2927 | pNet = netdev_priv(dev); |
2877 | pAC = pNet->pAC; | 2928 | pAC = pNet->pAC; |
2878 | 2929 | ||
2930 | if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG) | ||
2931 | return SkGeMiiIoctl(dev, if_mii(rq), cmd); | ||
2932 | |||
2879 | if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { | 2933 | if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { |
2880 | return -EFAULT; | 2934 | return -EFAULT; |
2881 | } | 2935 | } |