Commit ab7e3d48 authored by Petko Manolov's avatar Petko Manolov Committed by Greg Kroah-Hartman

USB Pegasus driver patch

  
the patch is against 2.5.6-pre3 and contains:
        - ethtool support;
        - using mii.h for the MII registers and constants;
        - 2 more device/vendor IDs added;
parent e0901283
/* /*
** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller ** Pegasus: USB 10/100Mbps/HomePNA (1Mbps) Controller
** **
** Copyright (c) 1999-2001 Petko Manolov (pmanolov@lnxw.com) ** Copyright (c) 1999-2002 Petko Manolov (petkan@users.sourceforge.net)
** **
** **
** ChangeLog: ** ChangeLog:
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
** TODO: suppressing HCD warnings spewage on disconnect. ** TODO: suppressing HCD warnings spewage on disconnect.
** v0.4.13 Ethernet address is now set at probe(), not at open() ** v0.4.13 Ethernet address is now set at probe(), not at open()
** time as this seems to break dhcpd. ** time as this seems to break dhcpd.
** v0.5.0 branch to 2.5.x kernels
** v0.5.1 ethtool support added
*/ */
/* /*
...@@ -46,20 +48,25 @@ ...@@ -46,20 +48,25 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/uaccess.h>
#include "pegasus.h" #include "pegasus.h"
/* /*
* Version Information * Version Information
*/ */
#define DRIVER_VERSION "v0.4.23 (2002/02/01)" #define DRIVER_VERSION "v0.5.1 (2002/03/06)"
#define DRIVER_AUTHOR "Petko Manolov <pmanolov@lnxw.com>" #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
#define PEGASUS_USE_INTR #define PEGASUS_USE_INTR
#define PEGASUS_WRITE_EEPROM #define PEGASUS_WRITE_EEPROM
#define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \
BMSR_100FULL | BMSR_ANEGCAPABLE)
static int loopback = 0; static int loopback = 0;
static int mii_mode = 0; static int mii_mode = 0;
...@@ -461,8 +468,8 @@ static inline int reset_mac( pegasus_t *pegasus ) ...@@ -461,8 +468,8 @@ static inline int reset_mac( pegasus_t *pegasus )
usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK ) { usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK ) {
__u16 auxmode; __u16 auxmode;
read_mii_word( pegasus, 0, 0x1b, &auxmode ); read_mii_word( pegasus, 0, MII_TPISTATUS, &auxmode );
write_mii_word( pegasus, 0, 0x1b, auxmode | 4 ); write_mii_word( pegasus, 0, MII_TPISTATUS, auxmode | 4 );
} }
return 0; return 0;
...@@ -481,16 +488,16 @@ static int enable_net_traffic( struct net_device *dev, struct usb_device *usb ) ...@@ -481,16 +488,16 @@ static int enable_net_traffic( struct net_device *dev, struct usb_device *usb )
if ( !(bmsr & 0x20) && !loopback ) if ( !(bmsr & 0x20) && !loopback )
warn( "%s: link NOT established (0x%x) - check the cable.", warn( "%s: link NOT established (0x%x) - check the cable.",
dev->name, bmsr ); dev->name, bmsr );
if ( read_mii_word(pegasus, pegasus->phy, MII_ANLPA, &linkpart) ) if ( read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart) )
return 2; return 2;
if ( !(linkpart & 1) ) if ( !(linkpart & 1) )
warn( "link partner stat %x", linkpart ); warn( "link partner stat %x", linkpart );
data[0] = 0xc9; data[0] = 0xc9;
data[1] = 0; data[1] = 0;
if ( linkpart & (ANLPA_100TX_FD | ANLPA_10T_FD) ) if ( linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL) )
data[1] |= 0x20; /* set full duplex */ data[1] |= 0x20; /* set full duplex */
if ( linkpart & (ANLPA_100TX_FD | ANLPA_100TX_HD) ) if ( linkpart & (ADVERTISE_100FULL | ADVERTISE_100HALF) )
data[1] |= 0x10; /* set 100 Mbps */ data[1] |= 0x10; /* set 100 Mbps */
if ( mii_mode ) if ( mii_mode )
data[1] = 0; data[1] = 0;
...@@ -710,15 +717,26 @@ static inline void get_interrupt_interval( pegasus_t *pegasus ) ...@@ -710,15 +717,26 @@ static inline void get_interrupt_interval( pegasus_t *pegasus )
} }
static void set_carrier(struct net_device *net)
{
pegasus_t *pegasus;
short tmp;
pegasus = net->priv;
read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp);
if (tmp & BMSR_LSTATUS)
netif_carrier_on(net);
else
netif_carrier_off(net);
}
static int pegasus_open(struct net_device *net) static int pegasus_open(struct net_device *net)
{ {
pegasus_t *pegasus = (pegasus_t *)net->priv; pegasus_t *pegasus = (pegasus_t *)net->priv;
int res; int res;
if ( (res = enable_net_traffic(net, pegasus->usb)) ) {
err("can't enable_net_traffic() - %d", res);
return -EIO;
}
FILL_BULK_URB( pegasus->rx_urb, pegasus->usb, FILL_BULK_URB( pegasus->rx_urb, pegasus->usb,
usb_rcvbulkpipe(pegasus->usb, 1), usb_rcvbulkpipe(pegasus->usb, 1),
pegasus->rx_buff, PEGASUS_MAX_MTU, pegasus->rx_buff, PEGASUS_MAX_MTU,
...@@ -735,6 +753,11 @@ static int pegasus_open(struct net_device *net) ...@@ -735,6 +753,11 @@ static int pegasus_open(struct net_device *net)
#endif #endif
netif_start_queue( net ); netif_start_queue( net );
pegasus->flags |= PEGASUS_RUNNING; pegasus->flags |= PEGASUS_RUNNING;
if ( (res = enable_net_traffic(net, pegasus->usb)) ) {
err("can't enable_net_traffic() - %d", res);
return -EIO;
}
set_carrier(net);
return 0; return 0;
} }
...@@ -760,24 +783,103 @@ static int pegasus_close( struct net_device *net ) ...@@ -760,24 +783,103 @@ static int pegasus_close( struct net_device *net )
} }
static int pegasus_ethtool_ioctl(struct net_device *net, void *uaddr)
{
pegasus_t *pegasus;
int cmd;
char tmp[128];
pegasus = net->priv;
if (get_user(cmd, (int *)uaddr))
return -EFAULT;
switch (cmd) {
case ETHTOOL_GDRVINFO: {
struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
strncpy(info.driver, DRIVER_DESC, ETHTOOL_BUSINFO_LEN);
strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
sprintf(tmp, "usb%d:%d", pegasus->usb->bus->busnum,
pegasus->usb->devnum);
strncpy(info.bus_info, tmp, ETHTOOL_BUSINFO_LEN);
if (copy_to_user(uaddr, &info, sizeof(info)))
return -EFAULT;
return 0;
}
case ETHTOOL_GSET: {
struct ethtool_cmd ecmd;
short lpa, bmcr;
if (copy_from_user(&ecmd, uaddr, sizeof(ecmd)))
return -EFAULT;
ecmd.supported = (SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_100baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP |
SUPPORTED_MII);
ecmd.port = PORT_TP;
ecmd.transceiver = XCVR_INTERNAL;
ecmd.phy_address = pegasus->phy;
read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr);
read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa);
if (bmcr & BMCR_ANENABLE) {
ecmd.autoneg = AUTONEG_ENABLE;
ecmd.speed = lpa & (LPA_100HALF|LPA_100FULL) ?
SPEED_100 : SPEED_10;
if (ecmd.speed == SPEED_100)
ecmd.duplex = lpa & LPA_100FULL ?
DUPLEX_FULL : DUPLEX_HALF;
else
ecmd.duplex = lpa & LPA_10FULL ?
DUPLEX_FULL : DUPLEX_HALF;
} else {
ecmd.autoneg = AUTONEG_DISABLE;
ecmd.speed = bmcr & BMCR_SPEED100 ?
SPEED_100 : SPEED_10;
ecmd.duplex = bmcr & BMCR_FULLDPLX ?
DUPLEX_FULL : DUPLEX_HALF;
}
if (copy_to_user(uaddr, &ecmd, sizeof(ecmd)))
return -EFAULT;
return 0;
}
case ETHTOOL_SSET: {
return -EOPNOTSUPP;
}
case ETHTOOL_GLINK: {
struct ethtool_value edata = {ETHTOOL_GLINK};
edata.data = netif_carrier_ok(net);
if (copy_to_user(uaddr, &edata, sizeof(edata)))
return -EFAULT;
return 0;
}
default:
return -EOPNOTSUPP;
}
}
static int pegasus_ioctl( struct net_device *net, struct ifreq *rq, int cmd ) static int pegasus_ioctl( struct net_device *net, struct ifreq *rq, int cmd )
{ {
__u16 *data = (__u16 *)&rq->ifr_data; __u16 *data = (__u16 *)&rq->ifr_data;
pegasus_t *pegasus = net->priv; pegasus_t *pegasus = net->priv;
switch(cmd) { switch(cmd) {
case SIOCDEVPRIVATE: case SIOCETHTOOL:
data[0] = pegasus->phy; return pegasus_ethtool_ioctl(net, rq->ifr_data);
case SIOCDEVPRIVATE+1: case SIOCDEVPRIVATE:
read_mii_word(pegasus, data[0], data[1]&0x1f, &data[3]); data[0] = pegasus->phy;
return 0; case SIOCDEVPRIVATE+1:
case SIOCDEVPRIVATE+2: read_mii_word(pegasus, data[0], data[1]&0x1f, &data[3]);
if ( !capable(CAP_NET_ADMIN) ) return 0;
return -EPERM; case SIOCDEVPRIVATE+2:
write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]); if ( !capable(CAP_NET_ADMIN) )
return 0; return -EPERM;
default: write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]);
return -EOPNOTSUPP; return 0;
default:
return -EOPNOTSUPP;
} }
} }
......
/* /*
* Copyright (c) 1999,2000 Petko Manolov - Petkan (pmanolov@lnxw.com) * Copyright (c) 1999-2002 Petko Manolov - Petkan (petkan@users.sourceforge.net)
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -31,14 +31,6 @@ ...@@ -31,14 +31,6 @@
#define EPROM_WR_ENABLE 0x10 #define EPROM_WR_ENABLE 0x10
#define EPROM_LOAD 0x20 #define EPROM_LOAD 0x20
#define MII_BMCR 0x00
#define MII_BMSR 0x01
#define BMSR_MEDIA 0x7808
#define MII_ANLPA 0x05
#define ANLPA_100TX_FD 0x0100
#define ANLPA_100TX_HD 0x0080
#define ANLPA_10T_FD 0x0040
#define ANLPA_10T_HD 0x0020
#define PHY_DONE 0x80 #define PHY_DONE 0x80
#define PHY_READ 0x40 #define PHY_READ 0x40
#define PHY_WRITE 0x20 #define PHY_WRITE 0x20
...@@ -184,6 +176,8 @@ PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet", ...@@ -184,6 +176,8 @@ PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet",
PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)", PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)",
VENDOR_ADMTEK, 0x0986, VENDOR_ADMTEK, 0x0986,
DEFAULT_GPIO_RESET | HAS_HOME_PNA ) DEFAULT_GPIO_RESET | HAS_HOME_PNA )
PEGASUS_DEV( "AN986A USB MAC", VENDOR_ADMTEK, 1986,
DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100, PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121,
...@@ -254,6 +248,8 @@ PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003, ...@@ -254,6 +248,8 @@ PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003,
DEFAULT_GPIO_RESET | PEGASUS_II ) DEFAULT_GPIO_RESET | PEGASUS_II )
PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200, PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200,
DEFAULT_GPIO_RESET ) DEFAULT_GPIO_RESET )
PEGASUS_DEV( "SMC 2206 USB Ethernet", VENDOR_SMC, 0x0201,
DEFAULT_GPIO_RESET | PEGASUS_II)
PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100, PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100,
DEFAULT_GPIO_RESET ) DEFAULT_GPIO_RESET )
PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001, PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment