# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.485 -> 1.486 # drivers/usb/pegasus.h 1.9 -> 1.10 # drivers/usb/pegasus.c 1.17 -> 1.18 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/03/07 pmanolov@Lnxw.COM 1.486 # 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; # -------------------------------------------- # diff -Nru a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c --- a/drivers/usb/pegasus.c Thu Mar 7 17:03:00 2002 +++ b/drivers/usb/pegasus.c Thu Mar 7 17:03:00 2002 @@ -1,7 +1,7 @@ /* ** 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: @@ -21,6 +21,8 @@ ** TODO: suppressing HCD warnings spewage on disconnect. ** v0.4.13 Ethernet address is now set at probe(), not at open() ** 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 @@ #include #include #include +#include +#include #include #include #include +#include #include "pegasus.h" /* * Version Information */ -#define DRIVER_VERSION "v0.4.23 (2002/02/01)" -#define DRIVER_AUTHOR "Petko Manolov " +#define DRIVER_VERSION "v0.5.1 (2002/03/06)" +#define DRIVER_AUTHOR "Petko Manolov " #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" #define PEGASUS_USE_INTR #define PEGASUS_WRITE_EEPROM +#define BMSR_MEDIA (BMSR_10HALF | BMSR_10FULL | BMSR_100HALF | \ + BMSR_100FULL | BMSR_ANEGCAPABLE) static int loopback = 0; static int mii_mode = 0; @@ -461,8 +468,8 @@ usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK ) { __u16 auxmode; - read_mii_word( pegasus, 0, 0x1b, &auxmode ); - write_mii_word( pegasus, 0, 0x1b, auxmode | 4 ); + read_mii_word( pegasus, 0, MII_TPISTATUS, &auxmode ); + write_mii_word( pegasus, 0, MII_TPISTATUS, auxmode | 4 ); } return 0; @@ -481,16 +488,16 @@ if ( !(bmsr & 0x20) && !loopback ) warn( "%s: link NOT established (0x%x) - check the cable.", 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; if ( !(linkpart & 1) ) warn( "link partner stat %x", linkpart ); data[0] = 0xc9; data[1] = 0; - if ( linkpart & (ANLPA_100TX_FD | ANLPA_10T_FD) ) + if ( linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL) ) 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 */ if ( mii_mode ) data[1] = 0; @@ -710,15 +717,26 @@ } +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) { pegasus_t *pegasus = (pegasus_t *)net->priv; 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, usb_rcvbulkpipe(pegasus->usb, 1), pegasus->rx_buff, PEGASUS_MAX_MTU, @@ -735,6 +753,11 @@ #endif netif_start_queue( net ); 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; } @@ -760,24 +783,103 @@ } +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 ) { __u16 *data = (__u16 *)&rq->ifr_data; pegasus_t *pegasus = net->priv; switch(cmd) { - case SIOCDEVPRIVATE: - data[0] = pegasus->phy; - case SIOCDEVPRIVATE+1: - read_mii_word(pegasus, data[0], data[1]&0x1f, &data[3]); - return 0; - case SIOCDEVPRIVATE+2: - if ( !capable(CAP_NET_ADMIN) ) - return -EPERM; - write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]); - return 0; - default: - return -EOPNOTSUPP; + case SIOCETHTOOL: + return pegasus_ethtool_ioctl(net, rq->ifr_data); + case SIOCDEVPRIVATE: + data[0] = pegasus->phy; + case SIOCDEVPRIVATE+1: + read_mii_word(pegasus, data[0], data[1]&0x1f, &data[3]); + return 0; + case SIOCDEVPRIVATE+2: + if ( !capable(CAP_NET_ADMIN) ) + return -EPERM; + write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]); + return 0; + default: + return -EOPNOTSUPP; } } diff -Nru a/drivers/usb/pegasus.h b/drivers/usb/pegasus.h --- a/drivers/usb/pegasus.h Thu Mar 7 17:03:00 2002 +++ b/drivers/usb/pegasus.h Thu Mar 7 17:03:00 2002 @@ -1,5 +1,5 @@ /* - * 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 * it under the terms of the GNU General Public License as published by @@ -31,14 +31,6 @@ #define EPROM_WR_ENABLE 0x10 #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_READ 0x40 #define PHY_WRITE 0x20 @@ -184,6 +176,8 @@ PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval. board)", VENDOR_ADMTEK, 0x0986, 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, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, @@ -254,6 +248,8 @@ DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200, 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, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001,