diff options
Diffstat (limited to 'drivers/usb/net')
| -rw-r--r-- | drivers/usb/net/Kconfig | 321 | ||||
| -rw-r--r-- | drivers/usb/net/Makefile | 18 | ||||
| -rw-r--r-- | drivers/usb/net/asix.c | 948 | ||||
| -rw-r--r-- | drivers/usb/net/catc.c | 958 | ||||
| -rw-r--r-- | drivers/usb/net/cdc_ether.c | 509 | ||||
| -rw-r--r-- | drivers/usb/net/cdc_subset.c | 335 | ||||
| -rw-r--r-- | drivers/usb/net/gl620a.c | 407 | ||||
| -rw-r--r-- | drivers/usb/net/kaweth.c | 1270 | ||||
| -rw-r--r-- | drivers/usb/net/kawethfw.h | 557 | ||||
| -rw-r--r-- | drivers/usb/net/net1080.c | 622 | ||||
| -rw-r--r-- | drivers/usb/net/pegasus.c | 1435 | ||||
| -rw-r--r-- | drivers/usb/net/pegasus.h | 302 | ||||
| -rw-r--r-- | drivers/usb/net/plusb.c | 156 | ||||
| -rw-r--r-- | drivers/usb/net/rndis_host.c | 615 | ||||
| -rw-r--r-- | drivers/usb/net/rtl8150.c | 940 | ||||
| -rw-r--r-- | drivers/usb/net/usbnet.c | 1223 | ||||
| -rw-r--r-- | drivers/usb/net/usbnet.h | 193 | ||||
| -rw-r--r-- | drivers/usb/net/zaurus.c | 386 | ||||
| -rw-r--r-- | drivers/usb/net/zd1201.c | 1946 | ||||
| -rw-r--r-- | drivers/usb/net/zd1201.h | 148 |
20 files changed, 0 insertions, 13289 deletions
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig deleted file mode 100644 index efd6ca7e4ac..00000000000 --- a/drivers/usb/net/Kconfig +++ /dev/null @@ -1,321 +0,0 @@ -# -# USB Network devices configuration -# -comment "Networking support is needed for USB Network Adapter support" - depends on USB && !NET - -menu "USB Network Adapters" - depends on USB && NET - -config USB_CATC - tristate "USB CATC NetMate-based Ethernet device support (EXPERIMENTAL)" - depends on EXPERIMENTAL - select CRC32 - ---help--- - Say Y if you want to use one of the following 10Mbps USB Ethernet - device based on the EL1210A chip. Supported devices are: - Belkin F5U011 - Belkin F5U111 - CATC NetMate - CATC NetMate II - smartBridges smartNIC - - This driver makes the adapter appear as a normal Ethernet interface, - typically on eth0, if it is the only ethernet device, or perhaps on - eth1, if you have a PCI or ISA ethernet card installed. - - To compile this driver as a module, choose M here: the - module will be called catc. - -config USB_KAWETH - tristate "USB KLSI KL5USB101-based ethernet device support" - ---help--- - Say Y here if you want to use one of the following 10Mbps only - USB Ethernet adapters based on the KLSI KL5KUSB101B chipset: - 3Com 3C19250 - ADS USB-10BT - ATEN USB Ethernet - ASANTE USB To Ethernet Adapter - AOX Endpoints USB Ethernet - Correga K.K. - D-Link DSB-650C and DU-E10 - Entrega / Portgear E45 - I-O DATA USB-ET/T - Jaton USB Ethernet Device Adapter - Kingston Technology USB Ethernet Adapter - Linksys USB10T - Mobility USB-Ethernet Adapter - NetGear EA-101 - Peracom Enet and Enet2 - Portsmith Express Ethernet Adapter - Shark Pocket Adapter - SMC 2202USB - Sony Vaio port extender - - This driver is likely to work with most 10Mbps only USB Ethernet - adapters, including some "no brand" devices. It does NOT work on - SmartBridges smartNIC or on Belkin F5U111 devices - you should use - the CATC NetMate driver for those. If you are not sure which one - you need, select both, and the correct one should be selected for - you. - - This driver makes the adapter appear as a normal Ethernet interface, - typically on eth0, if it is the only ethernet device, or perhaps on - eth1, if you have a PCI or ISA ethernet card installed. - - To compile this driver as a module, choose M here: the - module will be called kaweth. - -config USB_PEGASUS - tristate "USB Pegasus/Pegasus-II based ethernet device support" - select MII - ---help--- - Say Y here if you know you have Pegasus or Pegasus-II based adapter. - If in doubt then look at <file:drivers/usb/net/pegasus.h> for the - complete list of supported devices. - - If your particular adapter is not in the list and you are _sure_ it - is Pegasus or Pegasus II based then send me - <petkan@users.sourceforge.net> vendor and device IDs. - - To compile this driver as a module, choose M here: the - module will be called pegasus. - -config USB_RTL8150 - tristate "USB RTL8150 based ethernet device support (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - Say Y here if you have RTL8150 based usb-ethernet adapter. - Send me <petkan@users.sourceforge.net> any comments you may have. - You can also check for updates at <http://pegasus2.sourceforge.net/>. - - To compile this driver as a module, choose M here: the - module will be called rtl8150. - -config USB_USBNET - tristate "Multi-purpose USB Networking Framework" - ---help--- - This driver supports several kinds of network links over USB, - with "minidrivers" built around a common network driver core - that supports deep queues for efficient transfers. (This gives - better performance with small packets and at high speeds). - - The USB host runs "usbnet", and the other end of the link might be: - - - Another USB host, when using USB "network" or "data transfer" - cables. These are often used to network laptops to PCs, like - "Laplink" parallel cables or some motherboards. These rely - on specialized chips from many suppliers. - - - An intelligent USB gadget, perhaps embedding a Linux system. - These include PDAs running Linux (iPaq, Yopy, Zaurus, and - others), and devices that interoperate using the standard - CDC-Ethernet specification (including many cable modems). - - - Network adapter hardware (like those for 10/100 Ethernet) which - uses this driver framework. - - The link will appear with a name like "usb0", when the link is - a two-node link, or "eth0" for most CDC-Ethernet devices. Those - two-node links are most easily managed with Ethernet Bridging - (CONFIG_BRIDGE) instead of routing. - - For more information see <http://www.linux-usb.org/usbnet/>. - - To compile this driver as a module, choose M here: the - module will be called usbnet. - -config USB_NET_AX8817X - tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters" - depends on USB_USBNET && NET_ETHERNET - select CRC32 - select MII - default y - help - This option adds support for ASIX AX88xxx based USB 2.0 - 10/100 Ethernet adapters. - - This driver should work with at least the following devices: - * Aten UC210T - * ASIX AX88172 - * Billionton Systems, USB2AR - * Buffalo LUA-U2-KTX - * Corega FEther USB2-TX - * D-Link DUB-E100 - * Hawking UF200 - * Linksys USB200M - * Netgear FA120 - * Sitecom LN-029 - * Intellinet USB 2.0 Ethernet - * ST Lab USB 2.0 Ethernet - * TrendNet TU2-ET100 - - This driver creates an interface named "ethX", where X depends on - what other networking devices you have in use. - - -config USB_NET_CDCETHER - tristate "CDC Ethernet support (smart devices such as cable modems)" - depends on USB_USBNET - default y - help - This option supports devices conforming to the Communication Device - Class (CDC) Ethernet Control Model, a specification that's easy to - implement in device firmware. The CDC specifications are available - from <http://www.usb.org/>. - - CDC Ethernet is an implementation option for DOCSIS cable modems - that support USB connectivity, used for non-Microsoft USB hosts. - The Linux-USB CDC Ethernet Gadget driver is an open implementation. - This driver should work with at least the following devices: - - * Ericsson PipeRider (all variants) - * Motorola (DM100 and SB4100) - * Broadcom Cable Modem (reference design) - * Toshiba PCX1100U - * ... - - This driver creates an interface named "ethX", where X depends on - what other networking devices you have in use. However, if the - IEEE 802 "local assignment" bit is set in the address, a "usbX" - name is used instead. - -config USB_NET_GL620A - tristate "GeneSys GL620USB-A based cables" - depends on USB_USBNET - help - Choose this option if you're using a host-to-host cable, - or PC2PC motherboard, with this chip. - - Note that the half-duplex "GL620USB" is not supported. - -config USB_NET_NET1080 - tristate "NetChip 1080 based cables (Laplink, ...)" - default y - depends on USB_USBNET - help - Choose this option if you're using a host-to-host cable based - on this design: one NetChip 1080 chip and supporting logic, - optionally with LEDs that indicate traffic - -config USB_NET_PLUSB - tristate "Prolific PL-2301/2302 based cables" - # if the handshake/init/reset problems, from original 'plusb', - # are ever resolved ... then remove "experimental" - depends on USB_USBNET && EXPERIMENTAL - help - Choose this option if you're using a host-to-host cable - with one of these chips. - -config USB_NET_RNDIS_HOST - tristate "Host for RNDIS devices (EXPERIMENTAL)" - depends on USB_USBNET && EXPERIMENTAL - select USB_NET_CDCETHER - help - This option enables hosting "Remote NDIS" USB networking links, - as encouraged by Microsoft (instead of CDC Ethernet!) for use in - various devices that may only support this protocol. - - Avoid using this protocol unless you have no better options. - The protocol specification is incomplete, and is controlled by - (and for) Microsoft; it isn't an "Open" ecosystem or market. - -config USB_NET_CDC_SUBSET - tristate "Simple USB Network Links (CDC Ethernet subset)" - depends on USB_USBNET - help - This driver module supports USB network devices that can work - without any device-specific information. Select it if you have - one of these drivers. - - Note that while many USB host-to-host cables can work in this mode, - that may mean not being able to talk to Win32 systems or more - commonly not being able to handle certain events (like replugging - the host on the other end) very well. Also, these devices will - not generally have permanently assigned Ethernet addresses. - -config USB_ALI_M5632 - boolean "ALi M5632 based 'USB 2.0 Data Link' cables" - depends on USB_NET_CDC_SUBSET - help - Choose this option if you're using a host-to-host cable - based on this design, which supports USB 2.0 high speed. - -config USB_AN2720 - boolean "AnchorChips 2720 based cables (Xircom PGUNET, ...)" - depends on USB_NET_CDC_SUBSET - help - Choose this option if you're using a host-to-host cable - based on this design. Note that AnchorChips is now a - Cypress brand. - -config USB_BELKIN - boolean "eTEK based host-to-host cables (Advance, Belkin, ...)" - depends on USB_NET_CDC_SUBSET - default y - help - Choose this option if you're using a host-to-host cable - based on this design: two NetChip 2890 chips and an Atmel - microcontroller, with LEDs that indicate traffic. - -config USB_ARMLINUX - boolean "Embedded ARM Linux links (iPaq, ...)" - depends on USB_NET_CDC_SUBSET - default y - help - Choose this option to support the "usb-eth" networking driver - used by most of the ARM Linux community with device controllers - such as the SA-11x0 and PXA-25x UDCs, or the tftp capabilities - in some PXA versions of the "blob" boot loader. - - Linux-based "Gumstix" PXA-25x based systems use this protocol - to talk with other Linux systems. - - Although the ROMs shipped with Sharp Zaurus products use a - different link level framing protocol, you can have them use - this simpler protocol by installing a different kernel. - -config USB_EPSON2888 - boolean "Epson 2888 based firmware (DEVELOPMENT)" - depends on USB_NET_CDC_SUBSET - help - Choose this option to support the usb networking links used - by some sample firmware from Epson. - -config USB_NET_ZAURUS - tristate "Sharp Zaurus (stock ROMs) and compatible" - depends on USB_USBNET - select USB_NET_CDCETHER - select CRC32 - default y - help - Choose this option to support the usb networking links used by - Zaurus models like the SL-5000D, SL-5500, SL-5600, A-300, B-500. - This also supports some related device firmware, as used in some - PDAs from Olympus and some cell phones from Motorola. - - If you install an alternate image, such as the Linux 2.6 based - versions of OpenZaurus, you should no longer need to support this - protocol. Only the "eth-fd" or "net_fd" drivers in these devices - really need this non-conformant variant of CDC Ethernet (or in - some cases CDC MDLM) protocol, not "g_ether". - - -config USB_ZD1201 - tristate "USB ZD1201 based Wireless device support" - depends on NET_RADIO - select FW_LOADER - ---help--- - Say Y if you want to use wireless LAN adapters based on the ZyDAS - ZD1201 chip. - - This driver makes the adapter appear as a normal Ethernet interface, - typically on wlan0. - - The zd1201 device requires external firmware to be loaded. - This can be found at http://linux-lc100020.sourceforge.net/ - - To compile this driver as a module, choose M here: the - module will be called zd1201. - -endmenu diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile deleted file mode 100644 index 222c0495f79..00000000000 --- a/drivers/usb/net/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# -# Makefile for USB Network drivers -# - -obj-$(CONFIG_USB_CATC) += catc.o -obj-$(CONFIG_USB_KAWETH) += kaweth.o -obj-$(CONFIG_USB_PEGASUS) += pegasus.o -obj-$(CONFIG_USB_RTL8150) += rtl8150.o -obj-$(CONFIG_USB_NET_AX8817X) += asix.o -obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o -obj-$(CONFIG_USB_NET_GL620A) += gl620a.o -obj-$(CONFIG_USB_NET_NET1080) += net1080.o -obj-$(CONFIG_USB_NET_PLUSB) += plusb.o -obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o -obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o -obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o -obj-$(CONFIG_USB_USBNET) += usbnet.o -obj-$(CONFIG_USB_ZD1201) += zd1201.o diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c deleted file mode 100644 index 252a34fbb42..00000000000 --- a/drivers/usb/net/asix.c +++ /dev/null @@ -1,948 +0,0 @@ -/* - * ASIX AX8817X based USB 2.0 Ethernet Devices - * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com> - * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net> - * Copyright (c) 2002-2003 TiVo Inc. - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include <linux/config.h> -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#endif -#include <linux/module.h> -#include <linux/kmod.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/workqueue.h> -#include <linux/mii.h> -#include <linux/usb.h> -#include <linux/crc32.h> - -#include "usbnet.h" - - -/* ASIX AX8817X based USB 2.0 Ethernet Devices */ - -#define AX_CMD_SET_SW_MII 0x06 -#define AX_CMD_READ_MII_REG 0x07 -#define AX_CMD_WRITE_MII_REG 0x08 -#define AX_CMD_SET_HW_MII 0x0a -#define AX_CMD_READ_EEPROM 0x0b -#define AX_CMD_WRITE_EEPROM 0x0c -#define AX_CMD_WRITE_ENABLE 0x0d -#define AX_CMD_WRITE_DISABLE 0x0e -#define AX_CMD_WRITE_RX_CTL 0x10 -#define AX_CMD_READ_IPG012 0x11 -#define AX_CMD_WRITE_IPG0 0x12 -#define AX_CMD_WRITE_IPG1 0x13 -#define AX_CMD_WRITE_IPG2 0x14 -#define AX_CMD_WRITE_MULTI_FILTER 0x16 -#define AX_CMD_READ_NODE_ID 0x17 -#define AX_CMD_READ_PHY_ID 0x19 -#define AX_CMD_READ_MEDIUM_STATUS 0x1a -#define AX_CMD_WRITE_MEDIUM_MODE 0x1b -#define AX_CMD_READ_MONITOR_MODE 0x1c -#define AX_CMD_WRITE_MONITOR_MODE 0x1d -#define AX_CMD_WRITE_GPIOS 0x1f -#define AX_CMD_SW_RESET 0x20 -#define AX_CMD_SW_PHY_STATUS 0x21 -#define AX_CMD_SW_PHY_SELECT 0x22 -#define AX88772_CMD_READ_NODE_ID 0x13 - -#define AX_MONITOR_MODE 0x01 -#define AX_MONITOR_LINK 0x02 -#define AX_MONITOR_MAGIC 0x04 -#define AX_MONITOR_HSFS 0x10 - -/* AX88172 Medium Status Register values */ -#define AX_MEDIUM_FULL_DUPLEX 0x02 -#define AX_MEDIUM_TX_ABORT_ALLOW 0x04 -#define AX_MEDIUM_FLOW_CONTROL_EN 0x10 - -#define AX_MCAST_FILTER_SIZE 8 -#define AX_MAX_MCAST 64 - -#define AX_EEPROM_LEN 0x40 - -#define AX_SWRESET_CLEAR 0x00 -#define AX_SWRESET_RR 0x01 -#define AX_SWRESET_RT 0x02 -#define AX_SWRESET_PRTE 0x04 -#define AX_SWRESET_PRL 0x08 -#define AX_SWRESET_BZ 0x10 -#define AX_SWRESET_IPRL 0x20 -#define AX_SWRESET_IPPD 0x40 - -#define AX88772_IPG0_DEFAULT 0x15 -#define AX88772_IPG1_DEFAULT 0x0c -#define AX88772_IPG2_DEFAULT 0x12 - -#define AX88772_MEDIUM_FULL_DUPLEX 0x0002 -#define AX88772_MEDIUM_RESERVED 0x0004 -#define AX88772_MEDIUM_RX_FC_ENABLE 0x0010 -#define AX88772_MEDIUM_TX_FC_ENABLE 0x0020 -#define AX88772_MEDIUM_PAUSE_FORMAT 0x0080 -#define AX88772_MEDIUM_RX_ENABLE 0x0100 -#define AX88772_MEDIUM_100MB 0x0200 -#define AX88772_MEDIUM_DEFAULT \ - (AX88772_MEDIUM_FULL_DUPLEX | AX88772_MEDIUM_RX_FC_ENABLE | \ - AX88772_MEDIUM_TX_FC_ENABLE | AX88772_MEDIUM_100MB | \ - AX88772_MEDIUM_RESERVED | AX88772_MEDIUM_RX_ENABLE ) - -#define AX_EEPROM_MAGIC 0xdeadbeef - -/* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ -struct ax8817x_data { - u8 multi_filter[AX_MCAST_FILTER_SIZE]; -}; - -struct ax88172_int_data { - u16 res1; - u8 link; - u16 res2; - u8 status; - u16 res3; -} __attribute__ ((packed)); - -static int ax8817x_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - return usb_control_msg( - dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - cmd, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - data, - size, - USB_CTRL_GET_TIMEOUT); -} - -static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - return usb_control_msg( - dev->udev, - usb_sndctrlpipe(dev->udev, 0), - cmd, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, - index, - data, - size, - USB_CTRL_SET_TIMEOUT); -} - -static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs) -{ - struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; - - if (urb->status < 0) - printk(KERN_DEBUG "ax8817x_async_cmd_callback() failed with %d", - urb->status); - - kfree(req); - usb_free_urb(urb); -} - -static void ax8817x_status(struct usbnet *dev, struct urb *urb) -{ - struct ax88172_int_data *event; - int link; - - if (urb->actual_length < 8) - return; - - event = urb->transfer_buffer; - link = event->link & 0x01; - if (netif_carrier_ok(dev->net) != link) { - if (link) { - netif_carrier_on(dev->net); - usbnet_defer_kevent (dev, EVENT_LINK_RESET ); - } else - netif_carrier_off(dev->net); - devdbg(dev, "ax8817x - Link Status is: %d", link); - } -} - -static void -ax8817x_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, - u16 size, void *data) -{ - struct usb_ctrlrequest *req; - int status; - struct urb *urb; - - if ((urb = usb_alloc_urb(0, GFP_ATOMIC)) == NULL) { - devdbg(dev, "Error allocating URB in write_cmd_async!"); - return; - } - - if ((req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC)) == NULL) { - deverr(dev, "Failed to allocate memory for control request"); - usb_free_urb(urb); - return; - } - - req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; - req->bRequest = cmd; - req->wValue = cpu_to_le16(value); - req->wIndex = cpu_to_le16(index); - req->wLength = cpu_to_le16(size); - - usb_fill_control_urb(urb, dev->udev, - usb_sndctrlpipe(dev->udev, 0), - (void *)req, data, size, - ax8817x_async_cmd_callback, req); - - if((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - deverr(dev, "Error submitting the control message: status=%d", - status); - kfree(req); - usb_free_urb(urb); - } -} - -static void ax8817x_set_multicast(struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - struct ax8817x_data *data = (struct ax8817x_data *)&dev->data; - u8 rx_ctl = 0x8c; - - if (net->flags & IFF_PROMISC) { - rx_ctl |= 0x01; - } else if (net->flags & IFF_ALLMULTI - || net->mc_count > AX_MAX_MCAST) { - rx_ctl |= 0x02; - } else if (net->mc_count == 0) { - /* just broadcast and directed */ - } else { - /* We use the 20 byte dev->data - * for our 8 byte filter buffer - * to avoid allocating memory that - * is tricky to free later */ - struct dev_mc_list *mc_list = net->mc_list; - u32 crc_bits; - int i; - - memset(data->multi_filter, 0, AX_MCAST_FILTER_SIZE); - - /* Build the multicast hash filter. */ - for (i = 0; i < net->mc_count; i++) { - crc_bits = - ether_crc(ETH_ALEN, - mc_list->dmi_addr) >> 26; - data->multi_filter[crc_bits >> 3] |= - 1 << (crc_bits & 7); - mc_list = mc_list->next; - } - - ax8817x_write_cmd_async(dev, AX_CMD_WRITE_MULTI_FILTER, 0, 0, - AX_MCAST_FILTER_SIZE, data->multi_filter); - - rx_ctl |= 0x10; - } - - ax8817x_write_cmd_async(dev, AX_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); -} - -static int ax8817x_mdio_read(struct net_device *netdev, int phy_id, int loc) -{ - struct usbnet *dev = netdev_priv(netdev); - u16 res; - u8 buf[1]; - - ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf); - ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, - (__u16)loc, 2, (u16 *)&res); - ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf); - - return res & 0xffff; -} - -/* same as above, but converts resulting value to cpu byte order */ -static int ax8817x_mdio_read_le(struct net_device *netdev, int phy_id, int loc) -{ - return le16_to_cpu(ax8817x_mdio_read(netdev,phy_id, loc)); -} - -static void -ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) -{ - struct usbnet *dev = netdev_priv(netdev); - u16 res = val; - u8 buf[1]; - - ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, &buf); - ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, - (__u16)loc, 2, (u16 *)&res); - ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf); -} - -/* same as above, but converts new value to le16 byte order before writing */ -static void -ax8817x_mdio_write_le(struct net_device *netdev, int phy_id, int loc, int val) -{ - ax8817x_mdio_write( netdev, phy_id, loc, cpu_to_le16(val) ); -} - -static int ax88172_link_reset(struct usbnet *dev) -{ - u16 lpa; - u16 adv; - u16 res; - u8 mode; - - mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN; - lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA); - adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE); - res = mii_nway_result(lpa|adv); - if (res & LPA_DUPLEX) - mode |= AX_MEDIUM_FULL_DUPLEX; - ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); - - return 0; -} - -static void -ax8817x_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - u8 opt; - - if (ax8817x_read_cmd(dev, AX_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { - wolinfo->supported = 0; - wolinfo->wolopts = 0; - return; - } - wolinfo->supported = WAKE_PHY | WAKE_MAGIC; - wolinfo->wolopts = 0; - if (opt & AX_MONITOR_MODE) { - if (opt & AX_MONITOR_LINK) - wolinfo->wolopts |= WAKE_PHY; - if (opt & AX_MONITOR_MAGIC) - wolinfo->wolopts |= WAKE_MAGIC; - } -} - -static int -ax8817x_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) -{ - struct usbnet *dev = netdev_priv(net); - u8 opt = 0; - u8 buf[1]; - - if (wolinfo->wolopts & WAKE_PHY) - opt |= AX_MONITOR_LINK; - if (wolinfo->wolopts & WAKE_MAGIC) - opt |= AX_MONITOR_MAGIC; - if (opt != 0) - opt |= AX_MONITOR_MODE; - - if (ax8817x_write_cmd(dev, AX_CMD_WRITE_MONITOR_MODE, - opt, 0, 0, &buf) < 0) - return -EINVAL; - - return 0; -} - -static int ax8817x_get_eeprom_len(struct net_device *net) -{ - return AX_EEPROM_LEN; -} - -static int ax8817x_get_eeprom(struct net_device *net, - struct ethtool_eeprom *eeprom, u8 *data) -{ - struct usbnet *dev = netdev_priv(net); - u16 *ebuf = (u16 *)data; - int i; - - /* Crude hack to ensure that we don't overwrite memory - * if an odd length is supplied - */ - if (eeprom->len % 2) - return -EINVAL; - - eeprom->magic = AX_EEPROM_MAGIC; - - /* ax8817x returns 2 bytes from eeprom on read */ - for (i=0; i < eeprom->len / 2; i++) { - if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, - eeprom->offset + i, 0, 2, &ebuf[i]) < 0) - return -EINVAL; - } - return 0; -} - -static void ax8817x_get_drvinfo (struct net_device *net, - struct ethtool_drvinfo *info) -{ - /* Inherit standard device info */ - usbnet_get_drvinfo(net, info); - info->eedump_len = 0x3e; -} - -static int ax8817x_get_settings(struct net_device *net, struct ethtool_cmd *cmd) -{ - struct usbnet *dev = netdev_priv(net); - - return mii_ethtool_gset(&dev->mii,cmd); -} - -static int ax8817x_set_settings(struct net_device *net, struct ethtool_cmd *cmd) -{ - struct usbnet *dev = netdev_priv(net); - - return mii_ethtool_sset(&dev->mii,cmd); -} - -/* We need to override some ethtool_ops so we require our - own structure so we don't interfere with other usbnet - devices that may be connected at the same time. */ -static struct ethtool_ops ax8817x_ethtool_ops = { - .get_drvinfo = ax8817x_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_msglevel = usbnet_get_msglevel, - .set_msglevel = usbnet_set_msglevel, - .get_wol = ax8817x_get_wol, - .set_wol = ax8817x_set_wol, - .get_eeprom_len = ax8817x_get_eeprom_len, - .get_eeprom = ax8817x_get_eeprom, - .get_settings = ax8817x_get_settings, - .set_settings = ax8817x_set_settings, -}; - -static int ax8817x_ioctl (struct net_device *net, struct ifreq *rq, int cmd) -{ - struct usbnet *dev = netdev_priv(net); - - return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); -} - -static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf) -{ - int ret = 0; - void *buf; - int i; - unsigned long gpio_bits = dev->driver_info->data; - - usbnet_get_endpoints(dev,intf); - - buf = kmalloc(ETH_ALEN, GFP_KERNEL); - if(!buf) { - ret = -ENOMEM; - goto out1; - } - - /* Toggle the GPIOs in a manufacturer/model specific way */ - for (i = 2; i >= 0; i--) { - if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, - (gpio_bits >> (i * 8)) & 0xff, 0, 0, - buf)) < 0) - goto out2; - msleep(5); - } - - if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, - 0x80, 0, 0, buf)) < 0) { - dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret); - goto out2; - } - - /* Get the MAC address */ - memset(buf, 0, ETH_ALEN); - if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, - 0, 0, 6, buf)) < 0) { - dbg("read AX_CMD_READ_NODE_ID failed: %d", ret); - goto out2; - } - memcpy(dev->net->dev_addr, buf, ETH_ALEN); - - /* Get the PHY id */ - if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, - 0, 0, 2, buf)) < 0) { - dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret); - goto out2; - } else if (ret < 2) { - /* this should always return 2 bytes */ - dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", - ret); - ret = -EIO; - goto out2; - } - - /* Initialize MII structure */ - dev->mii.dev = dev->net; - dev->mii.mdio_read = ax8817x_mdio_read; - dev->mii.mdio_write = ax8817x_mdio_write; - dev->mii.phy_id_mask = 0x3f; - dev->mii.reg_num_mask = 0x1f; - dev->mii.phy_id = *((u8 *)buf + 1); - dev->net->do_ioctl = ax8817x_ioctl; - - dev->net->set_multicast_list = ax8817x_set_multicast; - dev->net->ethtool_ops = &ax8817x_ethtool_ops; - - ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); - ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP); - mii_nway_restart(&dev->mii); - - return 0; -out2: - kfree(buf); -out1: - return ret; -} - -static struct ethtool_ops ax88772_ethtool_ops = { - .get_drvinfo = ax8817x_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_msglevel = usbnet_get_msglevel, - .set_msglevel = usbnet_set_msglevel, - .get_wol = ax8817x_get_wol, - .set_wol = ax8817x_set_wol, - .get_eeprom_len = ax8817x_get_eeprom_len, - .get_eeprom = ax8817x_get_eeprom, - .get_settings = ax8817x_get_settings, - .set_settings = ax8817x_set_settings, -}; - -static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf) -{ - int ret; - void *buf; - - usbnet_get_endpoints(dev,intf); - - buf = kmalloc(6, GFP_KERNEL); - if(!buf) { - dbg ("Cannot allocate memory for buffer"); - ret = -ENOMEM; - goto out1; - } - - if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, - 0x00B0, 0, 0, buf)) < 0) - goto out2; - - msleep(5); - if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, - 0x0001, 0, 0, buf)) < 0) { - dbg("Select PHY #1 failed: %d", ret); - goto out2; - } - - if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD, - 0, 0, buf)) < 0) { - dbg("Failed to power down internal PHY: %d", ret); - goto out2; - } - - msleep(150); - if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR, - 0, 0, buf)) < 0) { - dbg("Failed to perform software reset: %d", ret); - goto out2; - } - - msleep(150); - if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, - AX_SWRESET_IPRL | AX_SWRESET_PRL, - 0, 0, buf)) < 0) { - dbg("Failed to set Internal/External PHY reset control: %d", - ret); - goto out2; - } - - msleep(150); - if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, - 0x0000, 0, 0, buf)) < 0) { - dbg("Failed to reset RX_CTL: %d", ret); - goto out2; - } - - /* Get the MAC address */ - memset(buf, 0, ETH_ALEN); - if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, - 0, 0, ETH_ALEN, buf)) < 0) { - dbg("Failed to read MAC address: %d", ret); - goto out2; - } - memcpy(dev->net->dev_addr, buf, ETH_ALEN); - - if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, - 0, 0, 0, buf)) < 0) { - dbg("Enabling software MII failed: %d", ret); - goto out2; - } - - if (((ret = ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, - 0x0010, 2, 2, buf)) < 0) - || (*((u16 *)buf) != 0x003b)) { - dbg("Read PHY register 2 must be 0x3b00: %d", ret); - goto out2; - } - - /* Initialize MII structure */ - dev->mii.dev = dev->net; - dev->mii.mdio_read = ax8817x_mdio_read; - dev->mii.mdio_write = ax8817x_mdio_write; - dev->mii.phy_id_mask = 0xff; - dev->mii.reg_num_mask = 0xff; - dev->net->do_ioctl = ax8817x_ioctl; - - /* Get the PHY id */ - if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, - 0, 0, 2, buf)) < 0) { - dbg("Error reading PHY ID: %02x", ret); - goto out2; - } else if (ret < 2) { - /* this should always return 2 bytes */ - dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", - ret); - ret = -EIO; - goto out2; - } - dev->mii.phy_id = *((u8 *)buf + 1); - - if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, - 0, 0, buf)) < 0) { - dbg("Set external PHY reset pin level: %d", ret); - goto out2; - } - msleep(150); - if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_RESET, - AX_SWRESET_IPRL | AX_SWRESET_PRL, - 0, 0, buf)) < 0) { - dbg("Set Internal/External PHY reset control: %d", ret); - goto out2; - } - msleep(150); - - - dev->net->set_multicast_list = ax8817x_set_multicast; - dev->net->ethtool_ops = &ax88772_ethtool_ops; - - ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); - ax8817x_mdio_write_le(dev->net, dev->mii.phy_id, MII_ADVERTISE, - ADVERTISE_ALL | ADVERTISE_CSMA); - mii_nway_restart(&dev->mii); - - if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, - AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) { - dbg("Write medium mode register: %d", ret); - goto out2; - } - - if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, - AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT, - AX88772_IPG2_DEFAULT, 0, buf)) < 0) { - dbg("Write IPG,IPG1,IPG2 failed: %d", ret); - goto out2; - } - if ((ret = - ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) { - dbg("Failed to set hardware MII: %02x", ret); - goto out2; - } - - /* Set RX_CTL to default values with 2k buffer, and enable cactus */ - if ((ret = - ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0, - buf)) < 0) { - dbg("Reset RX_CTL failed: %d", ret); - goto out2; - } - - kfree(buf); - - /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */ - if (dev->driver_info->flags & FLAG_FRAMING_AX) { - /* hard_mtu is still the default - the device does not support - jumbo eth frames */ - dev->rx_urb_size = 2048; - } - - return 0; - -out2: - kfree(buf); -out1: - return ret; -} - -static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb) -{ - u8 *head; - u32 header; - char *packet; - struct sk_buff *ax_skb; - u16 size; - - head = (u8 *) skb->data; - memcpy(&header, head, sizeof(header)); - le32_to_cpus(&header); - packet = head + sizeof(header); - - skb_pull(skb, 4); - - while (skb->len > 0) { - if ((short)(header & 0x0000ffff) != - ~((short)((header & 0xffff0000) >> 16))) { - devdbg(dev,"header length data is error"); - } - /* get the packet length */ - size = (u16) (header & 0x0000ffff); - - if ((skb->len) - ((size + 1) & 0xfffe) == 0) - return 2; - if (size > ETH_FRAME_LEN) { - devdbg(dev,"invalid rx length %d", size); - return 0; - } - ax_skb = skb_clone(skb, GFP_ATOMIC); - if (ax_skb) { - ax_skb->len = size; - ax_skb->data = packet; - ax_skb->tail = packet + size; - usbnet_skb_return(dev, ax_skb); - } else { - return 0; - } - - skb_pull(skb, (size + 1) & 0xfffe); - - if (skb->len == 0) - break; - - head = (u8 *) skb->data; - memcpy(&header, head, sizeof(header)); - le32_to_cpus(&header); - packet = head + sizeof(header); - skb_pull(skb, 4); - } - - if (skb->len < 0) { - devdbg(dev,"invalid rx length %d", skb->len); - return 0; - } - return 1; -} - -static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb, - gfp_t flags) -{ - int padlen; - int headroom = skb_headroom(skb); - int tailroom = skb_tailroom(skb); - u32 packet_len; - u32 padbytes = 0xffff0000; - - padlen = ((skb->len + 4) % 512) ? 0 : 4; - - if ((!skb_cloned(skb)) - && ((headroom + tailroom) >= (4 + padlen))) { - if ((headroom < 4) || (tailroom < padlen)) { - skb->data = memmove(skb->head + 4, skb->data, skb->len); - skb->tail = skb->data + skb->len; - } - } else { - struct sk_buff *skb2; - skb2 = skb_copy_expand(skb, 4, padlen, flags); - dev_kfree_skb_any(skb); - skb = skb2; - if (!skb) - return NULL; - } - - skb_push(skb, 4); - packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); - memcpy(skb->data, &packet_len, sizeof(packet_len)); - - if ((skb->len % 512) == 0) { - memcpy( skb->tail, &padbytes, sizeof(padbytes)); - skb_put(skb, sizeof(padbytes)); - } - return skb; -} - -static int ax88772_link_reset(struct usbnet *dev) -{ - u16 lpa; - u16 adv; - u16 res; - u16 mode; - - mode = AX88772_MEDIUM_DEFAULT; - lpa = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_LPA); - adv = ax8817x_mdio_read_le(dev->net, dev->mii.phy_id, MII_ADVERTISE); - res = mii_nway_result(lpa|adv); - - if ((res & LPA_DUPLEX) == 0) - mode &= ~AX88772_MEDIUM_FULL_DUPLEX; - if ((res & LPA_100) == 0) - mode &= ~AX88772_MEDIUM_100MB; - ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); - - return 0; -} - -static const struct driver_info ax8817x_info = { - .description = "ASIX AX8817x USB 2.0 Ethernet", - .bind = ax8817x_bind, - .status = ax8817x_status, - .link_reset = ax88172_link_reset, - .reset = ax88172_link_reset, - .flags = FLAG_ETHER, - .data = 0x00130103, -}; - -static const struct driver_info dlink_dub_e100_info = { - .description = "DLink DUB-E100 USB Ethernet", - .bind = ax8817x_bind, - .status = ax8817x_status, - .link_reset = ax88172_link_reset, - .reset = ax88172_link_reset, - .flags = FLAG_ETHER, - .data = 0x009f9d9f, -}; - -static const struct driver_info netgear_fa120_info = { - .description = "Netgear FA-120 USB Ethernet", - .bind = ax8817x_bind, - .status = ax8817x_status, - .link_reset = ax88172_link_reset, - .reset = ax88172_link_reset, - .flags = FLAG_ETHER, - .data = 0x00130103, -}; - -static const struct driver_info hawking_uf200_info = { - .description = "Hawking UF200 USB Ethernet", - .bind = ax8817x_bind, - .status = ax8817x_status, - .link_reset = ax88172_link_reset, - .reset = ax88172_link_reset, - .flags = FLAG_ETHER, - .data = 0x001f1d1f, -}; - -static const struct driver_info ax88772_info = { - .description = "ASIX AX88772 USB 2.0 Ethernet", - .bind = ax88772_bind, - .status = ax8817x_status, - .link_reset = ax88772_link_reset, - .reset = ax88772_link_reset, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, - .rx_fixup = ax88772_rx_fixup, - .tx_fixup = ax88772_tx_fixup, - .data = 0x00130103, -}; - -static const struct usb_device_id products [] = { -{ - // Linksys USB200M - USB_DEVICE (0x077b, 0x2226), - .driver_info = (unsigned long) &ax8817x_info, -}, { - // Netgear FA120 - USB_DEVICE (0x0846, 0x1040), - .driver_info = (unsigned long) &netgear_fa120_info, -}, { - // DLink DUB-E100 - USB_DEVICE (0x2001, 0x1a00), - .driver_info = (unsigned long) &dlink_dub_e100_info, -}, { - // Intellinet, ST Lab USB Ethernet - USB_DEVICE (0x0b95, 0x1720), - .driver_info = (unsigned long) &ax8817x_info, -}, { - // Hawking UF200, TrendNet TU2-ET100 - USB_DEVICE (0x07b8, 0x420a), - .driver_info = (unsigned long) &hawking_uf200_info, -}, { - // Billionton Systems, USB2AR - USB_DEVICE (0x08dd, 0x90ff), - .driver_info = (unsigned long) &ax8817x_info, -}, { - // ATEN UC210T - USB_DEVICE (0x0557, 0x2009), - .driver_info = (unsigned long) &ax8817x_info, -}, { - // Buffalo LUA-U2-KTX - USB_DEVICE (0x0411, 0x003d), - .driver_info = (unsigned long) &ax8817x_info, -}, { - // Sitecom LN-029 "USB 2.0 10/100 Ethernet adapter" - USB_DEVICE (0x6189, 0x182d), - .driver_info = (unsigned long) &ax8817x_info, -}, { - // corega FEther USB2-TX - USB_DEVICE (0x07aa, 0x0017), - .driver_info = (unsigned long) &ax8817x_info, -}, { - // Surecom EP-1427X-2 - USB_DEVICE (0x1189, 0x0893), - .driver_info = (unsigned long) &ax8817x_info, -}, { - // goodway corp usb gwusb2e - USB_DEVICE (0x1631, 0x6200), - .driver_info = (unsigned long) &ax8817x_info, -}, { - // ASIX AX88772 10/100 - USB_DEVICE (0x0b95, 0x7720), - .driver_info = (unsigned long) &ax88772_info, -}, - { }, // END -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver asix_driver = { - .owner = THIS_MODULE, - .name = "asix", - .id_table = products, - .probe = usbnet_probe, - .suspend = usbnet_suspend, - .resume = usbnet_resume, - .disconnect = usbnet_disconnect, -}; - -static int __init asix_init(void) -{ - return usb_register(&asix_driver); -} -module_init(asix_init); - -static void __exit asix_exit(void) -{ - usb_deregister(&asix_driver); -} -module_exit(asix_exit); - -MODULE_AUTHOR("David Hollis"); -MODULE_DESCRIPTION("ASIX AX8817X based USB 2.0 Ethernet Devices"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c deleted file mode 100644 index 37ef365a247..00000000000 --- a/drivers/usb/net/catc.c +++ /dev/null @@ -1,958 +0,0 @@ -/* - * Copyright (c) 2001 Vojtech Pavlik - * - * CATC EL1210A NetMate USB Ethernet driver - * - * Sponsored by SuSE - * - * Based on the work of - * Donald Becker - * - * Old chipset support added by Simon Evans <spse@secret.org.uk> 2002 - * - adds support for Belkin F5U011 - */ - -/* - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Should you need to contact me, the author, you can do so either by - * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail: - * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic - */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/slab.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/spinlock.h> -#include <linux/ethtool.h> -#include <linux/crc32.h> -#include <linux/bitops.h> -#include <asm/uaccess.h> - -#undef DEBUG - -#include <linux/usb.h> - -/* - * Version information. - */ - -#define DRIVER_VERSION "v2.8" -#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@suse.cz>" -#define DRIVER_DESC "CATC EL1210A NetMate USB Ethernet driver" -#define SHORT_DRIVER_DESC "EL1210A NetMate USB Ethernet" - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -static const char driver_name[] = "catc"; - -/* - * Some defines. - */ - -#define STATS_UPDATE (HZ) /* Time between stats updates */ -#define TX_TIMEOUT (5*HZ) /* Max time the queue can be stopped */ -#define PKT_SZ 1536 /* Max Ethernet packet size */ -#define RX_MAX_BURST 15 /* Max packets per rx buffer (> 0, < 16) */ -#define TX_MAX_BURST 15 /* Max full sized packets per tx buffer (> 0) */ -#define CTRL_QUEUE 16 /* Max control requests in flight (power of two) */ -#define RX_PKT_SZ 1600 /* Max size of receive packet for F5U011 */ - -/* - * Control requests. - */ - -enum control_requests { - ReadMem = 0xf1, - GetMac = 0xf2, - Reset = 0xf4, - SetMac = 0xf5, - SetRxMode = 0xf5, /* F5U011 only */ - WriteROM = 0xf8, - SetReg = 0xfa, - GetReg = 0xfb, - WriteMem = 0xfc, - ReadROM = 0xfd, -}; - -/* - * Registers. - */ - -enum register_offsets { - TxBufCount = 0x20, - RxBufCount = 0x21, - OpModes = 0x22, - TxQed = 0x23, - RxQed = 0x24, - MaxBurst = 0x25, - RxUnit = 0x60, - EthStatus = 0x61, - StationAddr0 = 0x67, - EthStats = 0x69, - LEDCtrl = 0x81, -}; - -enum eth_stats { - TxSingleColl = 0x00, - TxMultiColl = 0x02, - TxExcessColl = 0x04, - RxFramErr = 0x06, -}; - -enum op_mode_bits { - Op3MemWaits = 0x03, - OpLenInclude = 0x08, - OpRxMerge = 0x10, - OpTxMerge = 0x20, - OpWin95bugfix = 0x40, - OpLoopback = 0x80, -}; - -enum rx_filter_bits { - RxEnable = 0x01, - RxPolarity = 0x02, - RxForceOK = 0x04, - RxMultiCast = 0x08, - RxPromisc = 0x10, - AltRxPromisc = 0x20, /* F5U011 uses different bit */ -}; - -enum led_values { - LEDFast = 0x01, - LEDSlow = 0x02, - LEDFlash = 0x03, - LEDPulse = 0x04, - LEDLink = 0x08, -}; - -enum link_status { - LinkNoChange = 0, - LinkGood = 1, - LinkBad = 2 -}; - -/* - * The catc struct. - */ - -#define CTRL_RUNNING 0 -#define RX_RUNNING 1 -#define TX_RUNNING 2 - -struct catc { - struct net_device *netdev; - struct usb_device *usbdev; - - struct net_device_stats stats; - unsigned long flags; - - unsigned int tx_ptr, tx_idx; - unsigned int ctrl_head, ctrl_tail; - spinlock_t tx_lock, ctrl_lock; - - u8 tx_buf[2][TX_MAX_BURST * (PKT_SZ + 2)]; - u8 rx_buf[RX_MAX_BURST * (PKT_SZ + 2)]; - u8 irq_buf[2]; - u8 ctrl_buf[64]; - struct usb_ctrlrequest ctrl_dr; - - struct timer_list timer; - u8 stats_buf[8]; - u16 stats_vals[4]; - unsigned long last_stats; - - u8 multicast[64]; - - struct ctrl_queue { - u8 dir; - u8 request; - u16 value; - u16 index; - void *buf; - int len; - void (*callback)(struct catc *catc, struct ctrl_queue *q); - } ctrl_queue[CTRL_QUEUE]; - - struct urb *tx_urb, *rx_urb, *irq_urb, *ctrl_urb; - - u8 is_f5u011; /* Set if device is an F5U011 */ - u8 rxmode[2]; /* Used for F5U011 */ - atomic_t recq_sz; /* Used for F5U011 - counter of waiting rx packets */ -}; - -/* - * Useful macros. - */ - -#define catc_get_mac(catc, mac) catc_ctrl_msg(catc, USB_DIR_IN, GetMac, 0, 0, mac, 6) -#define catc_reset(catc) catc_ctrl_msg(catc, USB_DIR_OUT, Reset, 0, 0, NULL, 0) -#define catc_set_reg(catc, reg, val) catc_ctrl_msg(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0) -#define catc_get_reg(catc, reg, buf) catc_ctrl_msg(catc, USB_DIR_IN, GetReg, 0, reg, buf, 1) -#define catc_write_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size) -#define catc_read_mem(catc, addr, buf, size) catc_ctrl_msg(catc, USB_DIR_IN, ReadMem, 0, addr, buf, size) - -#define f5u011_rxmode(catc, rxmode) catc_ctrl_msg(catc, USB_DIR_OUT, SetRxMode, 0, 1, rxmode, 2) -#define f5u011_rxmode_async(catc, rxmode) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 1, &rxmode, 2, NULL) -#define f5u011_mchash_async(catc, hash) catc_ctrl_async(catc, USB_DIR_OUT, SetRxMode, 0, 2, &hash, 8, NULL) - -#define catc_set_reg_async(catc, reg, val) catc_ctrl_async(catc, USB_DIR_OUT, SetReg, val, reg, NULL, 0, NULL) -#define catc_get_reg_async(catc, reg, cb) catc_ctrl_async(catc, USB_DIR_IN, GetReg, 0, reg, NULL, 1, cb) -#define catc_write_mem_async(catc, addr, buf, size) catc_ctrl_async(catc, USB_DIR_OUT, WriteMem, 0, addr, buf, size, NULL) - -/* - * Receive routines. - */ - -static void catc_rx_done(struct urb *urb, struct pt_regs *regs) -{ - struct catc *catc = urb->context; - u8 *pkt_start = urb->transfer_buffer; - struct sk_buff *skb; - int pkt_len, pkt_offset = 0; - - if (!catc->is_f5u011) { - clear_bit(RX_RUNNING, &catc->flags); - pkt_offset = 2; - } - - if (urb->status) { - dbg("rx_done, status %d, length %d", urb->status, urb->actual_length); - return; - } - - do { - if(!catc->is_f5u011) { - pkt_len = le16_to_cpup((__le16*)pkt_start); - if (pkt_len > urb->actual_length) { - catc->stats.rx_length_errors++; - catc->stats.rx_errors++; - break; - } - } else { - pkt_len = urb->actual_length; - } - - if (!(skb = dev_alloc_skb(pkt_len))) - return; - - skb->dev = catc->netdev; - eth_copy_and_sum(skb, pkt_start + pkt_offset, pkt_len, 0); - skb_put(skb, pkt_len); - - skb->protocol = eth_type_trans(skb, catc->netdev); - netif_rx(skb); - - catc->stats.rx_packets++; - catc->stats.rx_bytes += pkt_len; - - /* F5U011 only does one packet per RX */ - if (catc->is_f5u011) - break; - pkt_start += (((pkt_len + 1) >> 6) + 1) << 6; - - } while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length); - - catc->netdev->last_rx = jiffies; - - if (catc->is_f5u011) { - if (atomic_read(&catc->recq_sz)) { - int status; - atomic_dec(&catc->recq_sz); - dbg("getting extra packet"); - urb->dev = catc->usbdev; - if ((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { - dbg("submit(rx_urb) status %d", status); - } - } else { - clear_bit(RX_RUNNING, &catc->flags); - } - } -} - -static void catc_irq_done(struct urb *urb, struct pt_regs *regs) -{ - struct catc *catc = urb->context; - u8 *data = urb->transfer_buffer; - int status; - unsigned int hasdata = 0, linksts = LinkNoChange; - - if (!catc->is_f5u011) { - hasdata = data[1] & 0x80; - if (data[1] & 0x40) - linksts = LinkGood; - else if (data[1] & 0x20) - linksts = LinkBad; - } else { - hasdata = (unsigned int)(be16_to_cpup((__be16*)data) & 0x0fff); - if (data[0] == 0x90) - linksts = LinkGood; - else if (data[0] == 0xA0) - linksts = LinkBad; - } - - switch (urb->status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]); - goto resubmit; - } - - if (linksts == LinkGood) { - netif_carrier_on(catc->netdev); - dbg("link ok"); - } - - if (linksts == LinkBad) { - netif_carrier_off(catc->netdev); - dbg("link bad"); - } - - if (hasdata) { - if (test_and_set_bit(RX_RUNNING, &catc->flags)) { - if (catc->is_f5u011) - atomic_inc(&catc->recq_sz); - } else { - catc->rx_urb->dev = catc->usbdev; - if ((status = usb_submit_urb(catc->rx_urb, GFP_ATOMIC)) < 0) { - err("submit(rx_urb) status %d", status); - } - } - } -resubmit: - status = usb_submit_urb (urb, SLAB_ATOMIC); - if (status) - err ("can't resubmit intr, %s-%s, status %d", - catc->usbdev->bus->bus_name, - catc->usbdev->devpath, status); -} - -/* - * Transmit routines. - */ - -static void catc_tx_run(struct catc *catc) -{ - int status; - - if (catc->is_f5u011) - catc->tx_ptr = (catc->tx_ptr + 63) & ~63; - - catc->tx_urb->transfer_buffer_length = catc->tx_ptr; - catc->tx_urb->transfer_buffer = catc->tx_buf[catc->tx_idx]; - catc->tx_urb->dev = catc->usbdev; - - if ((status = usb_submit_urb(catc->tx_urb, GFP_ATOMIC)) < 0) - err("submit(tx_urb), status %d", status); - - catc->tx_idx = !catc->tx_idx; - catc->tx_ptr = 0; - - catc->netdev->trans_start = jiffies; -} - -static void catc_tx_done(struct urb *urb, struct pt_regs *regs) -{ - struct catc *catc = urb->context; - unsigned long flags; - - if (urb->status == -ECONNRESET) { - dbg("Tx Reset."); - urb->status = 0; - catc->netdev->trans_start = jiffies; - catc->stats.tx_errors++; - clear_bit(TX_RUNNING, &catc->flags); - netif_wake_queue(catc->netdev); - return; - } - - if (urb->status) { - dbg("tx_done, status %d, length %d", urb->status, urb->actual_length); - return; - } - - spin_lock_irqsave(&catc->tx_lock, flags); - - if (catc->tx_ptr) - catc_tx_run(catc); - else - clear_bit(TX_RUNNING, &catc->flags); - - netif_wake_queue(catc->netdev); - - spin_unlock_irqrestore(&catc->tx_lock, flags); -} - -static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - struct catc *catc = netdev_priv(netdev); - unsigned long flags; - char *tx_buf; - - spin_lock_irqsave(&catc->tx_lock, flags); - - catc->tx_ptr = (((catc->tx_ptr - 1) >> 6) + 1) << 6; - tx_buf = catc->tx_buf[catc->tx_idx] + catc->tx_ptr; - *((u16*)tx_buf) = (catc->is_f5u011) ? cpu_to_be16((u16)skb->len) : cpu_to_le16((u16)skb->len); - memcpy(tx_buf + 2, skb->data, skb->len); - catc->tx_ptr += skb->len + 2; - - if (!test_and_set_bit(TX_RUNNING, &catc->flags)) - catc_tx_run(catc); - - if ((catc->is_f5u011 && catc->tx_ptr) - || (catc->tx_ptr >= ((TX_MAX_BURST - 1) * (PKT_SZ + 2)))) - netif_stop_queue(netdev); - - spin_unlock_irqrestore(&catc->tx_lock, flags); - - catc->stats.tx_bytes += skb->len; - catc->stats.tx_packets++; - - dev_kfree_skb(skb); - - return 0; -} - -static void catc_tx_timeout(struct net_device *netdev) -{ - struct catc *catc = netdev_priv(netdev); - - warn("Transmit timed out."); - usb_unlink_urb(catc->tx_urb); -} - -/* - * Control messages. - */ - -static int catc_ctrl_msg(struct catc *catc, u8 dir, u8 request, u16 value, u16 index, void *buf, int len) -{ - int retval = usb_control_msg(catc->usbdev, - dir ? usb_rcvctrlpipe(catc->usbdev, 0) : usb_sndctrlpipe(catc->usbdev, 0), - request, 0x40 | dir, value, index, buf, len, 1000); - return retval < 0 ? retval : 0; -} - -static void catc_ctrl_run(struct catc *catc) -{ - struct ctrl_queue *q = catc->ctrl_queue + catc->ctrl_tail; - struct usb_device *usbdev = catc->usbdev; - struct urb *urb = catc->ctrl_urb; - struct usb_ctrlrequest *dr = &catc->ctrl_dr; - int status; - - dr->bRequest = q->request; - dr->bRequestType = 0x40 | q->dir; - dr->wValue = cpu_to_le16(q->value); - dr->wIndex = cpu_to_le16(q->index); - dr->wLength = cpu_to_le16(q->len); - - urb->pipe = q->dir ? usb_rcvctrlpipe(usbdev, 0) : usb_sndctrlpipe(usbdev, 0); - urb->transfer_buffer_length = q->len; - urb->transfer_buffer = catc->ctrl_buf; - urb->setup_packet = (void *) dr; - urb->dev = usbdev; - - if (!q->dir && q->buf && q->len) - memcpy(catc->ctrl_buf, q->buf, q->len); - - if ((status = usb_submit_urb(catc->ctrl_urb, GFP_KERNEL))) - err("submit(ctrl_urb) status %d", status); -} - -static void catc_ctrl_done(struct urb *urb, struct pt_regs *regs) -{ - struct catc *catc = urb->context; - struct ctrl_queue *q; - unsigned long flags; - - if (urb->status) - dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length); - - spin_lock_irqsave(&catc->ctrl_lock, flags); - - q = catc->ctrl_queue + catc->ctrl_tail; - - if (q->dir) { - if (q->buf && q->len) - memcpy(q->buf, catc->ctrl_buf, q->len); - else - q->buf = catc->ctrl_buf; - } - - if (q->callback) - q->callback(catc, q); - - catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1); - - if (catc->ctrl_head != catc->ctrl_tail) - catc_ctrl_run(catc); - else - clear_bit(CTRL_RUNNING, &catc->flags); - - spin_unlock_irqrestore(&catc->ctrl_lock, flags); -} - -static int catc_ctrl_async(struct catc *catc, u8 dir, u8 request, u16 value, - u16 index, void *buf, int len, void (*callback)(struct catc *catc, struct ctrl_queue *q)) -{ - struct ctrl_queue *q; - int retval = 0; - unsigned long flags; - - spin_lock_irqsave(&catc->ctrl_lock, flags); - - q = catc->ctrl_queue + catc->ctrl_head; - - q->dir = dir; - q->request = request; - q->value = value; - q->index = index; - q->buf = buf; - q->len = len; - q->callback = callback; - - catc->ctrl_head = (catc->ctrl_head + 1) & (CTRL_QUEUE - 1); - - if (catc->ctrl_head == catc->ctrl_tail) { - err("ctrl queue full"); - catc->ctrl_tail = (catc->ctrl_tail + 1) & (CTRL_QUEUE - 1); - retval = -1; - } - - if (!test_and_set_bit(CTRL_RUNNING, &catc->flags)) - catc_ctrl_run(catc); - - spin_unlock_irqrestore(&catc->ctrl_lock, flags); - - return retval; -} - -/* - * Statistics. - */ - -static void catc_stats_done(struct catc *catc, struct ctrl_queue *q) -{ - int index = q->index - EthStats; - u16 data, last; - - catc->stats_buf[index] = *((char *)q->buf); - - if (index & 1) - return; - - data = ((u16)catc->stats_buf[index] << 8) | catc->stats_buf[index + 1]; - last = catc->stats_vals[index >> 1]; - - switch (index) { - case TxSingleColl: - case TxMultiColl: - catc->stats.collisions += data - last; - break; - case TxExcessColl: - catc->stats.tx_aborted_errors += data - last; - catc->stats.tx_errors += data - last; - break; - case RxFramErr: - catc->stats.rx_frame_errors += data - last; - catc->stats.rx_errors += data - last; - break; - } - - catc->stats_vals[index >> 1] = data; -} - -static void catc_stats_timer(unsigned long data) -{ - struct catc *catc = (void *) data; - int i; - - for (i = 0; i < 8; i++) - catc_get_reg_async(catc, EthStats + 7 - i, catc_stats_done); - - mod_timer(&catc->timer, jiffies + STATS_UPDATE); -} - -static struct net_device_stats *catc_get_stats(struct net_device *netdev) -{ - struct catc *catc = netdev_priv(netdev); - return &catc->stats; -} - -/* - * Receive modes. Broadcast, Multicast, Promisc. - */ - -static void catc_multicast(unsigned char *addr, u8 *multicast) -{ - u32 crc; - - crc = ether_crc_le(6, addr); - multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7); -} - -static void catc_set_multicast_list(struct net_device *netdev) -{ - struct catc *catc = netdev_priv(netdev); - struct dev_mc_list *mc; - u8 broadcast[6]; - u8 rx = RxEnable | RxPolarity | RxMultiCast; - int i; - - memset(broadcast, 0xff, 6); - memset(catc->multicast, 0, 64); - - catc_multicast(broadcast, catc->multicast); - catc_multicast(netdev->dev_addr, catc->multicast); - - if (netdev->flags & IFF_PROMISC) { - memset(catc->multicast, 0xff, 64); - rx |= (!catc->is_f5u011) ? RxPromisc : AltRxPromisc; - } - - if (netdev->flags & IFF_ALLMULTI) { - memset(catc->multicast, 0xff, 64); - } else { - for (i = 0, mc = netdev->mc_list; mc && i < netdev->mc_count; i++, mc = mc->next) { - u32 crc = ether_crc_le(6, mc->dmi_addr); - if (!catc->is_f5u011) { - catc->multicast[(crc >> 3) & 0x3f] |= 1 << (crc & 7); - } else { - catc->multicast[7-(crc >> 29)] |= 1 << ((crc >> 26) & 7); - } - } - } - if (!catc->is_f5u011) { - catc_set_reg_async(catc, RxUnit, rx); - catc_write_mem_async(catc, 0xfa80, catc->multicast, 64); - } else { - f5u011_mchash_async(catc, catc->multicast); - if (catc->rxmode[0] != rx) { - catc->rxmode[0] = rx; - dbg("Setting RX mode to %2.2X %2.2X", catc->rxmode[0], catc->rxmode[1]); - f5u011_rxmode_async(catc, catc->rxmode); - } - } -} - -static void catc_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct catc *catc = netdev_priv(dev); - strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); - strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); - usb_make_path (catc->usbdev, info->bus_info, sizeof info->bus_info); -} - -static int catc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct catc *catc = netdev_priv(dev); - if (!catc->is_f5u011) - return -EOPNOTSUPP; - - cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP; - cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP; - cmd->speed = SPEED_10; - cmd->duplex = DUPLEX_HALF; - cmd->port = PORT_TP; - cmd->phy_address = 0; - cmd->transceiver = XCVR_INTERNAL; - cmd->autoneg = AUTONEG_DISABLE; - cmd->maxtxpkt = 1; - cmd->maxrxpkt = 1; - return 0; -} - -static struct ethtool_ops ops = { - .get_drvinfo = catc_get_drvinfo, - .get_settings = catc_get_settings, - .get_link = ethtool_op_get_link -}; - -/* - * Open, close. - */ - -static int catc_open(struct net_device *netdev) -{ - struct catc *catc = netdev_priv(netdev); - int status; - - catc->irq_urb->dev = catc->usbdev; - if ((status = usb_submit_urb(catc->irq_urb, GFP_KERNEL)) < 0) { - err("submit(irq_urb) status %d", status); - return -1; - } - - netif_start_queue(netdev); - - if (!catc->is_f5u011) - mod_timer(&catc->timer, jiffies + STATS_UPDATE); - - return 0; -} - -static int catc_stop(struct net_device *netdev) -{ - struct catc *catc = netdev_priv(netdev); - - netif_stop_queue(netdev); - - if (!catc->is_f5u011) - del_timer_sync(&catc->timer); - - usb_kill_urb(catc->rx_urb); - usb_kill_urb(catc->tx_urb); - usb_kill_urb(catc->irq_urb); - usb_kill_urb(catc->ctrl_urb); - - return 0; -} - -/* - * USB probe, disconnect. - */ - -static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *usbdev = interface_to_usbdev(intf); - struct net_device *netdev; - struct catc *catc; - u8 broadcast[6]; - int i, pktsz; - - if (usb_set_interface(usbdev, - intf->altsetting->desc.bInterfaceNumber, 1)) { - err("Can't set altsetting 1."); - return -EIO; - } - - netdev = alloc_etherdev(sizeof(struct catc)); - if (!netdev) - return -ENOMEM; - - catc = netdev_priv(netdev); - - netdev->open = catc_open; - netdev->hard_start_xmit = catc_hard_start_xmit; - netdev->stop = catc_stop; - netdev->get_stats = catc_get_stats; - netdev->tx_timeout = catc_tx_timeout; - netdev->watchdog_timeo = TX_TIMEOUT; - netdev->set_multicast_list = catc_set_multicast_list; - SET_ETHTOOL_OPS(netdev, &ops); - - catc->usbdev = usbdev; - catc->netdev = netdev; - - spin_lock_init(&catc->tx_lock); - spin_lock_init(&catc->ctrl_lock); - - init_timer(&catc->timer); - catc->timer.data = (long) catc; - catc->timer.function = catc_stats_timer; - - catc->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); - catc->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - catc->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - catc->irq_urb = usb_alloc_urb(0, GFP_KERNEL); - if ((!catc->ctrl_urb) || (!catc->tx_urb) || - (!catc->rx_urb) || (!catc->irq_urb)) { - err("No free urbs available."); - if (catc->ctrl_urb) - usb_free_urb(catc->ctrl_urb); - if (catc->tx_urb) - usb_free_urb(catc->tx_urb); - if (catc->rx_urb) - usb_free_urb(catc->rx_urb); - if (catc->irq_urb) - usb_free_urb(catc->irq_urb); - free_netdev(netdev); - return -ENOMEM; - } - - /* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */ - if (le16_to_cpu(usbdev->descriptor.idVendor) == 0x0423 && - le16_to_cpu(usbdev->descriptor.idProduct) == 0xa && - le16_to_cpu(catc->usbdev->descriptor.bcdDevice) == 0x0130) { - dbg("Testing for f5u011"); - catc->is_f5u011 = 1; - atomic_set(&catc->recq_sz, 0); - pktsz = RX_PKT_SZ; - } else { - pktsz = RX_MAX_BURST * (PKT_SZ + 2); - } - - usb_fill_control_urb(catc->ctrl_urb, usbdev, usb_sndctrlpipe(usbdev, 0), - NULL, NULL, 0, catc_ctrl_done, catc); - - usb_fill_bulk_urb(catc->tx_urb, usbdev, usb_sndbulkpipe(usbdev, 1), - NULL, 0, catc_tx_done, catc); - - usb_fill_bulk_urb(catc->rx_urb, usbdev, usb_rcvbulkpipe(usbdev, 1), - catc->rx_buf, pktsz, catc_rx_done, catc); - - usb_fill_int_urb(catc->irq_urb, usbdev, usb_rcvintpipe(usbdev, 2), - catc->irq_buf, 2, catc_irq_done, catc, 1); - - if (!catc->is_f5u011) { - dbg("Checking memory size\n"); - - i = 0x12345678; - catc_write_mem(catc, 0x7a80, &i, 4); - i = 0x87654321; - catc_write_mem(catc, 0xfa80, &i, 4); - catc_read_mem(catc, 0x7a80, &i, 4); - - switch (i) { - case 0x12345678: - catc_set_reg(catc, TxBufCount, 8); - catc_set_reg(catc, RxBufCount, 32); - dbg("64k Memory\n"); - break; - default: - warn("Couldn't detect memory size, assuming 32k"); - case 0x87654321: - catc_set_reg(catc, TxBufCount, 4); - catc_set_reg(catc, RxBufCount, 16); - dbg("32k Memory\n"); - break; - } - - dbg("Getting MAC from SEEROM."); - - catc_get_mac(catc, netdev->dev_addr); - - dbg("Setting MAC into registers."); - - for (i = 0; i < 6; i++) - catc_set_reg(catc, StationAddr0 - i, netdev->dev_addr[i]); - - dbg("Filling the multicast list."); - - memset(broadcast, 0xff, 6); - catc_multicast(broadcast, catc->multicast); - catc_multicast(netdev->dev_addr, catc->multicast); - catc_write_mem(catc, 0xfa80, catc->multicast, 64); - - dbg("Clearing error counters."); - - for (i = 0; i < 8; i++) - catc_set_reg(catc, EthStats + i, 0); - catc->last_stats = jiffies; - - dbg("Enabling."); - - catc_set_reg(catc, MaxBurst, RX_MAX_BURST); - catc_set_reg(catc, OpModes, OpTxMerge | OpRxMerge | OpLenInclude | Op3MemWaits); - catc_set_reg(catc, LEDCtrl, LEDLink); - catc_set_reg(catc, RxUnit, RxEnable | RxPolarity | RxMultiCast); - } else { - dbg("Performing reset\n"); - catc_reset(catc); - catc_get_mac(catc, netdev->dev_addr); - - dbg("Setting RX Mode"); - catc->rxmode[0] = RxEnable | RxPolarity | RxMultiCast; - catc->rxmode[1] = 0; - f5u011_rxmode(catc, catc->rxmode); - } - dbg("Init done."); - printk(KERN_INFO "%s: %s USB Ethernet at usb-%s-%s, ", - netdev->name, (catc->is_f5u011) ? "Belkin F5U011" : "CATC EL1210A NetMate", - usbdev->bus->bus_name, usbdev->devpath); - for (i = 0; i < 5; i++) printk("%2.2x:", netdev->dev_addr[i]); - printk("%2.2x.\n", netdev->dev_addr[i]); - usb_set_intfdata(intf, catc); - - SET_NETDEV_DEV(netdev, &intf->dev); - if (register_netdev(netdev) != 0) { - usb_set_intfdata(intf, NULL); - usb_free_urb(catc->ctrl_urb); - usb_free_urb(catc->tx_urb); - usb_free_urb(catc->rx_urb); - usb_free_urb(catc->irq_urb); - free_netdev(netdev); - return -EIO; - } - return 0; -} - -static void catc_disconnect(struct usb_interface *intf) -{ - struct catc *catc = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - if (catc) { - unregister_netdev(catc->netdev); - usb_free_urb(catc->ctrl_urb); - usb_free_urb(catc->tx_urb); - usb_free_urb(catc->rx_urb); - usb_free_urb(catc->irq_urb); - free_netdev(catc->netdev); - } -} - -/* - * Module functions and tables. - */ - -static struct usb_device_id catc_id_table [] = { - { USB_DEVICE(0x0423, 0xa) }, /* CATC Netmate, Belkin F5U011 */ - { USB_DEVICE(0x0423, 0xc) }, /* CATC Netmate II, Belkin F5U111 */ - { USB_DEVICE(0x08d1, 0x1) }, /* smartBridges smartNIC */ - { } -}; - -MODULE_DEVICE_TABLE(usb, catc_id_table); - -static struct usb_driver catc_driver = { - .owner = THIS_MODULE, - .name = driver_name, - .probe = catc_probe, - .disconnect = catc_disconnect, - .id_table = catc_id_table, -}; - -static int __init catc_init(void) -{ - int result = usb_register(&catc_driver); - if (result == 0) - info(DRIVER_VERSION " " DRIVER_DESC); - return result; -} - -static void __exit catc_exit(void) -{ - usb_deregister(&catc_driver); -} - -module_init(catc_init); -module_exit(catc_exit); diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c deleted file mode 100644 index 652b04bbf6a..00000000000 --- a/drivers/usb/net/cdc_ether.c +++ /dev/null @@ -1,509 +0,0 @@ -/* - * CDC Ethernet based networking peripherals - * Copyright (C) 2003-2005 by David Brownell - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include <linux/config.h> -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#endif -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ctype.h> -#include <linux/ethtool.h> -#include <linux/workqueue.h> -#include <linux/mii.h> -#include <linux/usb.h> -#include <linux/usb_cdc.h> - -#include "usbnet.h" - - -/* - * probes control interface, claims data interface, collects the bulk - * endpoints, activates data interface (if needed), maybe sets MTU. - * all pure cdc, except for certain firmware workarounds, and knowing - * that rndis uses one different rule. - */ -int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) -{ - u8 *buf = intf->cur_altsetting->extra; - int len = intf->cur_altsetting->extralen; - struct usb_interface_descriptor *d; - struct cdc_state *info = (void *) &dev->data; - int status; - int rndis; - struct usb_driver *driver = driver_of(intf); - - if (sizeof dev->data < sizeof *info) - return -EDOM; - - /* expect strict spec conformance for the descriptors, but - * cope with firmware which stores them in the wrong place - */ - if (len == 0 && dev->udev->actconfig->extralen) { - /* Motorola SB4100 (and others: Brad Hards says it's - * from a Broadcom design) put CDC descriptors here - */ - buf = dev->udev->actconfig->extra; - len = dev->udev->actconfig->extralen; - if (len) - dev_dbg(&intf->dev, - "CDC descriptors on config\n"); - } - - /* this assumes that if there's a non-RNDIS vendor variant - * of cdc-acm, it'll fail RNDIS requests cleanly. - */ - rndis = (intf->cur_altsetting->desc.bInterfaceProtocol == 0xff); - - memset(info, 0, sizeof *info); - info->control = intf; - while (len > 3) { - if (buf [1] != USB_DT_CS_INTERFACE) - goto next_desc; - - /* use bDescriptorSubType to identify the CDC descriptors. - * We expect devices with CDC header and union descriptors. - * For CDC Ethernet we need the ethernet descriptor. - * For RNDIS, ignore two (pointless) CDC modem descriptors - * in favor of a complicated OID-based RPC scheme doing what - * CDC Ethernet achieves with a simple descriptor. - */ - switch (buf [2]) { - case USB_CDC_HEADER_TYPE: - if (info->header) { - dev_dbg(&intf->dev, "extra CDC header\n"); - goto bad_desc; - } - info->header = (void *) buf; - if (info->header->bLength != sizeof *info->header) { - dev_dbg(&intf->dev, "CDC header len %u\n", - info->header->bLength); - goto bad_desc; - } - break; - case USB_CDC_UNION_TYPE: - if (info->u) { - dev_dbg(&intf->dev, "extra CDC union\n"); - goto bad_desc; - } - info->u = (void *) buf; - if (info->u->bLength != sizeof *info->u) { - dev_dbg(&intf->dev, "CDC union len %u\n", - info->u->bLength); - goto bad_desc; - } - - /* we need a master/control interface (what we're - * probed with) and a slave/data interface; union - * descriptors sort this all out. - */ - info->control = usb_ifnum_to_if(dev->udev, - info->u->bMasterInterface0); - info->data = usb_ifnum_to_if(dev->udev, - info->u->bSlaveInterface0); - if (!info->control || !info->data) { - dev_dbg(&intf->dev, - "master #%u/%p slave #%u/%p\n", - info->u->bMasterInterface0, - info->control, - info->u->bSlaveInterface0, - info->data); - goto bad_desc; - } - if (info->control != intf) { - dev_dbg(&intf->dev, "bogus CDC Union\n"); - /* Ambit USB Cable Modem (and maybe others) - * interchanges master and slave interface. - */ - if (info->data == intf) { - info->data = info->control; - info->control = intf; - } else - goto bad_desc; - } - - /* a data interface altsetting does the real i/o */ - d = &info->data->cur_altsetting->desc; - if (d->bInterfaceClass != USB_CLASS_CDC_DATA) { - dev_dbg(&intf->dev, "slave class %u\n", - d->bInterfaceClass); - goto bad_desc; - } - break; - case USB_CDC_ETHERNET_TYPE: - if (info->ether) { - dev_dbg(&intf->dev, "extra CDC ether\n"); - goto bad_desc; - } - info->ether = (void *) buf; - if (info->ether->bLength != sizeof *info->ether) { - dev_dbg(&intf->dev, "CDC ether len %u\n", - info->ether->bLength); - goto bad_desc; - } - dev->hard_mtu = le16_to_cpu( - info->ether->wMaxSegmentSize); - /* because of Zaurus, we may be ignoring the host - * side link address we were given. - */ - break; - } -next_desc: - len -= buf [0]; /* bLength */ - buf += buf [0]; - } - - if (!info->header || !info->u || (!rndis && !info->ether)) { - dev_dbg(&intf->dev, "missing cdc %s%s%sdescriptor\n", - info->header ? "" : "header ", - info->u ? "" : "union ", - info->ether ? "" : "ether "); - goto bad_desc; - } - - /* claim data interface and set it up ... with side effects. - * network traffic can't flow until an altsetting is enabled. - */ - status = usb_driver_claim_interface(driver, info->data, dev); - if (status < 0) - return status; - status = usbnet_get_endpoints(dev, info->data); - if (status < 0) { - /* ensure immediate exit from usbnet_disconnect */ - usb_set_intfdata(info->data, NULL); - usb_driver_release_interface(driver, info->data); - return status; - } - - /* status endpoint: optional for CDC Ethernet, not RNDIS (or ACM) */ - dev->status = NULL; - if (info->control->cur_altsetting->desc.bNumEndpoints == 1) { - struct usb_endpoint_descriptor *desc; - - dev->status = &info->control->cur_altsetting->endpoint [0]; - desc = &dev->status->desc; - if (desc->bmAttributes != USB_ENDPOINT_XFER_INT - || !(desc->bEndpointAddress & USB_DIR_IN) - || (le16_to_cpu(desc->wMaxPacketSize) - < sizeof(struct usb_cdc_notification)) - || !desc->bInterval) { - dev_dbg(&intf->dev, "bad notification endpoint\n"); - dev->status = NULL; - } - } - if (rndis && !dev->status) { - dev_dbg(&intf->dev, "missing RNDIS status endpoint\n"); - usb_set_intfdata(info->data, NULL); - usb_driver_release_interface(driver, info->data); - return -ENODEV; - } - return 0; - -bad_desc: - dev_info(&dev->udev->dev, "bad CDC descriptors\n"); - return -ENODEV; -} -EXPORT_SYMBOL_GPL(usbnet_generic_cdc_bind); - -void usbnet_cdc_unbind(struct usbnet *dev, struct usb_interface *intf) -{ - struct cdc_state *info = (void *) &dev->data; - struct usb_driver *driver = driver_of(intf); - - /* disconnect master --> disconnect slave */ - if (intf == info->control && info->data) { - /* ensure immediate exit from usbnet_disconnect */ - usb_set_intfdata(info->data, NULL); - usb_driver_release_interface(driver, info->data); - info->data = NULL; - } - - /* and vice versa (just in case) */ - else if (intf == info->data && info->control) { - /* ensure immediate exit from usbnet_disconnect */ - usb_set_intfdata(info->control, NULL); - usb_driver_release_interface(driver, info->control); - info->control = NULL; - } -} -EXPORT_SYMBOL_GPL(usbnet_cdc_unbind); - - -/*------------------------------------------------------------------------- - * - * Communications Device Class, Ethernet Control model - * - * Takes two interfaces. The DATA interface is inactive till an altsetting - * is selected. Configuration data includes class descriptors. There's - * an optional status endpoint on the control interface. - * - * This should interop with whatever the 2.4 "CDCEther.c" driver - * (by Brad Hards) talked with, with more functionality. - * - *-------------------------------------------------------------------------*/ - -static void dumpspeed(struct usbnet *dev, __le32 *speeds) -{ - if (netif_msg_timer(dev)) - devinfo(dev, "link speeds: %u kbps up, %u kbps down", - __le32_to_cpu(speeds[0]) / 1000, - __le32_to_cpu(speeds[1]) / 1000); -} - -static void cdc_status(struct usbnet *dev, struct urb *urb) -{ - struct usb_cdc_notification *event; - - if (urb->actual_length < sizeof *event) - return; - - /* SPEED_CHANGE can get split into two 8-byte packets */ - if (test_and_clear_bit(EVENT_STS_SPLIT, &dev->flags)) { - dumpspeed(dev, (__le32 *) urb->transfer_buffer); - return; - } - - event = urb->transfer_buffer; - switch (event->bNotificationType) { - case USB_CDC_NOTIFY_NETWORK_CONNECTION: - if (netif_msg_timer(dev)) - devdbg(dev, "CDC: carrier %s", - event->wValue ? "on" : "off"); - if (event->wValue) - netif_carrier_on(dev->net); - else - netif_carrier_off(dev->net); - break; - case USB_CDC_NOTIFY_SPEED_CHANGE: /* tx/rx rates */ - if (netif_msg_timer(dev)) - devdbg(dev, "CDC: speed change (len %d)", - urb->actual_length); - if (urb->actual_length != (sizeof *event + 8)) - set_bit(EVENT_STS_SPLIT, &dev->flags); - else - dumpspeed(dev, (__le32 *) &event[1]); - break; - /* USB_CDC_NOTIFY_RESPONSE_AVAILABLE can happen too (e.g. RNDIS), - * but there are no standard formats for the response data. - */ - default: - deverr(dev, "CDC: unexpected notification %02x!", - event->bNotificationType); - break; - } -} - -static u8 nibble(unsigned char c) -{ - if (likely(isdigit(c))) - return c - '0'; - c = toupper(c); - if (likely(isxdigit(c))) - return 10 + c - 'A'; - return 0; -} - -static inline int -get_ethernet_addr(struct usbnet *dev, struct usb_cdc_ether_desc *e) -{ - int tmp, i; - unsigned char buf [13]; - - tmp = usb_string(dev->udev, e->iMACAddress, buf, sizeof buf); - if (tmp != 12) { - dev_dbg(&dev->udev->dev, - "bad MAC string %d fetch, %d\n", e->iMACAddress, tmp); - if (tmp >= 0) - tmp = -EINVAL; - return tmp; - } - for (i = tmp = 0; i < 6; i++, tmp += 2) - dev->net->dev_addr [i] = - (nibble(buf [tmp]) << 4) + nibble(buf [tmp + 1]); - return 0; -} - -static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) -{ - int status; - struct cdc_state *info = (void *) &dev->data; - - status = usbnet_generic_cdc_bind(dev, intf); - if (status < 0) - return status; - - status = get_ethernet_addr(dev, info->ether); - if (status < 0) { - usb_set_intfdata(info->data, NULL); - usb_driver_release_interface(driver_of(intf), info->data); - return status; - } - - /* FIXME cdc-ether has some multicast code too, though it complains - * in routine cases. info->ether describes the multicast support. - * Implement that here, manipulating the cdc filter as needed. - */ - return 0; -} - -static const struct driver_info cdc_info = { - .description = "CDC Ethernet Device", - .flags = FLAG_ETHER, - // .check_connect = cdc_check_connect, - .bind = cdc_bind, - .unbind = usbnet_cdc_unbind, - .status = cdc_status, -}; - -/*-------------------------------------------------------------------------*/ - - -static const struct usb_device_id products [] = { -/* - * BLACKLIST !! - * - * First blacklist any products that are egregiously nonconformant - * with the CDC Ethernet specs. Minor braindamage we cope with; when - * they're not even trying, needing a separate driver is only the first - * of the differences to show up. - */ - -#define ZAURUS_MASTER_INTERFACE \ - .bInterfaceClass = USB_CLASS_COMM, \ - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ - .bInterfaceProtocol = USB_CDC_PROTO_NONE - -/* SA-1100 based Sharp Zaurus ("collie"), or compatible; - * wire-incompatible with true CDC Ethernet implementations. - * (And, it seems, needlessly so...) - */ -{ - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x8004, - ZAURUS_MASTER_INTERFACE, - .driver_info = 0, -}, - -/* PXA-25x based Sharp Zaurii. Note that it seems some of these - * (later models especially) may have shipped only with firmware - * advertising false "CDC MDLM" compatibility ... but we're not - * clear which models did that, so for now let's assume the worst. - */ -{ - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x8005, /* A-300 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = 0, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x8006, /* B-500/SL-5600 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = 0, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x8007, /* C-700 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = 0, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x9031, /* C-750 C-760 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = 0, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x9032, /* SL-6000 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = 0, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - /* reported with some C860 units */ - .idProduct = 0x9050, /* C-860 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = 0, -}, - -/* - * WHITELIST!!! - * - * CDC Ether uses two interfaces, not necessarily consecutive. - * We match the main interface, ignoring the optional device - * class so we could handle devices that aren't exclusively - * CDC ether. - * - * NOTE: this match must come AFTER entries blacklisting devices - * because of bugs/quirks in a given product (like Zaurus, above). - */ -{ - USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &cdc_info, -}, - { }, // END -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver cdc_driver = { - .owner = THIS_MODULE, - .name = "cdc_ether", - .id_table = products, - .probe = usbnet_probe, - .disconnect = usbnet_disconnect, - .suspend = usbnet_suspend, - .resume = usbnet_resume, -}; - - -static int __init cdc_init(void) -{ - BUG_ON((sizeof(((struct usbnet *)0)->data) - < sizeof(struct cdc_state))); - - return usb_register(&cdc_driver); -} -module_init(cdc_init); - -static void __exit cdc_exit(void) -{ - usb_deregister(&cdc_driver); -} -module_exit(cdc_exit); - -MODULE_AUTHOR("David Brownell"); -MODULE_DESCRIPTION("USB CDC Ethernet devices"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/net/cdc_subset.c b/drivers/usb/net/cdc_subset.c deleted file mode 100644 index f1730b685fd..00000000000 --- a/drivers/usb/net/cdc_subset.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Simple "CDC Subset" USB Networking Links - * Copyright (C) 2000-2005 by David Brownell - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/config.h> -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#endif -#include <linux/module.h> -#include <linux/kmod.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/workqueue.h> -#include <linux/mii.h> -#include <linux/usb.h> - -#include "usbnet.h" - - -/* - * This supports simple USB network links that don't require any special - * framing or hardware control operations. The protocol used here is a - * strict subset of CDC Ethernet, with three basic differences reflecting - * the goal that almost any hardware should run it: - * - * - Minimal runtime control: one interface, no altsettings, and - * no vendor or class specific control requests. If a device is - * configured, it is allowed to exchange packets with the host. - * Fancier models would mean not working on some hardware. - * - * - Minimal manufacturing control: no IEEE "Organizationally - * Unique ID" required, or an EEPROMs to store one. Each host uses - * one random "locally assigned" Ethernet address instead, which can - * of course be overridden using standard tools like "ifconfig". - * (With 2^46 such addresses, same-net collisions are quite rare.) - * - * - There is no additional framing data for USB. Packets are written - * exactly as in CDC Ethernet, starting with an Ethernet header and - * terminated by a short packet. However, the host will never send a - * zero length packet; some systems can't handle those robustly. - * - * Anything that can transmit and receive USB bulk packets can implement - * this protocol. That includes both smart peripherals and quite a lot - * of "host-to-host" USB cables (which embed two devices back-to-back). - * - * Note that although Linux may use many of those host-to-host links - * with this "cdc_subset" framing, that doesn't mean there may not be a - * better approach. Handling the "other end unplugs/replugs" scenario - * well tends to require chip-specific vendor requests. Also, Windows - * peers at the other end of host-to-host cables may expect their own - * framing to be used rather than this "cdc_subset" model. - */ - -#if defined(CONFIG_USB_EPSON2888) || defined(CONFIG_USB_ARMLINUX) -/* PDA style devices are always connected if present */ -static int always_connected (struct usbnet *dev) -{ - return 0; -} -#endif - -#ifdef CONFIG_USB_ALI_M5632 -#define HAVE_HARDWARE - -/*------------------------------------------------------------------------- - * - * ALi M5632 driver ... does high speed - * - *-------------------------------------------------------------------------*/ - -static const struct driver_info ali_m5632_info = { - .description = "ALi M5632", -}; - - -#endif - - -#ifdef CONFIG_USB_AN2720 -#define HAVE_HARDWARE - -/*------------------------------------------------------------------------- - * - * AnchorChips 2720 driver ... http://www.cypress.com - * - * This doesn't seem to have a way to detect whether the peer is - * connected, or need any reset handshaking. It's got pretty big - * internal buffers (handles most of a frame's worth of data). - * Chip data sheets don't describe any vendor control messages. - * - *-------------------------------------------------------------------------*/ - -static const struct driver_info an2720_info = { - .description = "AnchorChips/Cypress 2720", - // no reset available! - // no check_connect available! - - .in = 2, .out = 2, // direction distinguishes these -}; - -#endif /* CONFIG_USB_AN2720 */ - - -#ifdef CONFIG_USB_BELKIN -#define HAVE_HARDWARE - -/*------------------------------------------------------------------------- - * - * Belkin F5U104 ... two NetChip 2280 devices + Atmel AVR microcontroller - * - * ... also two eTEK designs, including one sold as "Advance USBNET" - * - *-------------------------------------------------------------------------*/ - -static const struct driver_info belkin_info = { - .description = "Belkin, eTEK, or compatible", -}; - -#endif /* CONFIG_USB_BELKIN */ - - - -#ifdef CONFIG_USB_EPSON2888 -#define HAVE_HARDWARE - -/*------------------------------------------------------------------------- - * - * EPSON USB clients - * - * This is the same idea as Linux PDAs (below) except the firmware in the - * device might not be Tux-powered. Epson provides reference firmware that - * implements this interface. Product developers can reuse or modify that - * code, such as by using their own product and vendor codes. - * - * Support was from Juro Bystricky <bystricky.juro@erd.epson.com> - * - *-------------------------------------------------------------------------*/ - -static const struct driver_info epson2888_info = { - .description = "Epson USB Device", - .check_connect = always_connected, - - .in = 4, .out = 3, -}; - -#endif /* CONFIG_USB_EPSON2888 */ - - -#ifdef CONFIG_USB_KC2190 -#define HAVE_HARDWARE -static const struct driver_info kc2190_info = { - .description = "KC Technology KC-190", -}; -#endif /* CONFIG_USB_KC2190 */ - - -#ifdef CONFIG_USB_ARMLINUX -#define HAVE_HARDWARE - -/*------------------------------------------------------------------------- - * - * Intel's SA-1100 chip integrates basic USB support, and is used - * in PDAs like some iPaqs, the Yopy, some Zaurus models, and more. - * When they run Linux, arch/arm/mach-sa1100/usb-eth.c may be used to - * network using minimal USB framing data. - * - * This describes the driver currently in standard ARM Linux kernels. - * The Zaurus uses a different driver (see later). - * - * PXA25x and PXA210 use XScale cores (ARM v5TE) with better USB support - * and different USB endpoint numbering than the SA1100 devices. The - * mach-pxa/usb-eth.c driver re-uses the device ids from mach-sa1100 - * so we rely on the endpoint descriptors. - * - *-------------------------------------------------------------------------*/ - -static const struct driver_info linuxdev_info = { - .description = "Linux Device", - .check_connect = always_connected, -}; - -static const struct driver_info yopy_info = { - .description = "Yopy", - .check_connect = always_connected, -}; - -static const struct driver_info blob_info = { - .description = "Boot Loader OBject", - .check_connect = always_connected, -}; - -#endif /* CONFIG_USB_ARMLINUX */ - - -/*-------------------------------------------------------------------------*/ - -#ifndef HAVE_HARDWARE -#error You need to configure some hardware for this driver -#endif - -/* - * chip vendor names won't normally be on the cables, and - * may not be on the device. - */ - -static const struct usb_device_id products [] = { - -#ifdef CONFIG_USB_ALI_M5632 -{ - USB_DEVICE (0x0402, 0x5632), // ALi defaults - .driver_info = (unsigned long) &ali_m5632_info, -}, -#endif - -#ifdef CONFIG_USB_AN2720 -{ - USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults - .driver_info = (unsigned long) &an2720_info, -}, { - USB_DEVICE (0x0547, 0x2727), // Xircom PGUNET - .driver_info = (unsigned long) &an2720_info, -}, -#endif - -#ifdef CONFIG_USB_BELKIN -{ - USB_DEVICE (0x050d, 0x0004), // Belkin - .driver_info = (unsigned long) &belkin_info, -}, { - USB_DEVICE (0x056c, 0x8100), // eTEK - .driver_info = (unsigned long) &belkin_info, -}, { - USB_DEVICE (0x0525, 0x9901), // Advance USBNET (eTEK) - .driver_info = (unsigned long) &belkin_info, -}, -#endif - -#ifdef CONFIG_USB_EPSON2888 -{ - USB_DEVICE (0x0525, 0x2888), // EPSON USB client - .driver_info = (unsigned long) &epson2888_info, -}, -#endif - -#ifdef CONFIG_USB_KC2190 -{ - USB_DEVICE (0x050f, 0x0190), // KC-190 - .driver_info = (unsigned long) &kc2190_info, -}, -#endif - -#ifdef CONFIG_USB_ARMLINUX -/* - * SA-1100 using standard ARM Linux kernels, or compatible. - * Often used when talking to Linux PDAs (iPaq, Yopy, etc). - * The sa-1100 "usb-eth" driver handles the basic framing. - * - * PXA25x or PXA210 ... these use a "usb-eth" driver much like - * the sa1100 one, but hardware uses different endpoint numbers. - * - * Or the Linux "Ethernet" gadget on hardware that can't talk - * CDC Ethernet (e.g., no altsettings), in either of two modes: - * - acting just like the old "usb-eth" firmware, though - * the implementation is different - * - supporting RNDIS as the first/default configuration for - * MS-Windows interop; Linux needs to use the other config - */ -{ - // 1183 = 0x049F, both used as hex values? - // Compaq "Itsy" vendor/product id - USB_DEVICE (0x049F, 0x505A), // usb-eth, or compatible - .driver_info = (unsigned long) &linuxdev_info, -}, { - USB_DEVICE (0x0E7E, 0x1001), // G.Mate "Yopy" - .driver_info = (unsigned long) &yopy_info, -}, { - USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader - .driver_info = (unsigned long) &blob_info, -}, { - // Linux Ethernet/RNDIS gadget on pxa210/25x/26x, second config - // e.g. Gumstix, current OpenZaurus, ... - USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203), - .driver_info = (unsigned long) &linuxdev_info, -}, -#endif - - { }, // END -}; -MODULE_DEVICE_TABLE(usb, products); - -/*-------------------------------------------------------------------------*/ - -static struct usb_driver cdc_subset_driver = { - .owner = THIS_MODULE, - .name = "cdc_subset", - .probe = usbnet_probe, - .suspend = usbnet_suspend, - .resume = usbnet_resume, - .disconnect = usbnet_disconnect, - .id_table = products, -}; - -static int __init cdc_subset_init(void) -{ - return usb_register(&cdc_subset_driver); -} -module_init(cdc_subset_init); - -static void __exit cdc_subset_exit(void) -{ - usb_deregister(&cdc_subset_driver); -} -module_exit(cdc_subset_exit); - -MODULE_AUTHOR("David Brownell"); -MODULE_DESCRIPTION("Simple 'CDC Subset' USB networking links"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/net/gl620a.c b/drivers/usb/net/gl620a.c deleted file mode 100644 index c0f263b202a..00000000000 --- a/drivers/usb/net/gl620a.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * GeneSys GL620USB-A based links - * Copyright (C) 2001 by Jiun-Jie Huang <huangjj@genesyslogic.com.tw> - * Copyright (C) 2001 by Stanislav Brabec <utx@penguin.cz> - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include <linux/config.h> -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#endif -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/workqueue.h> -#include <linux/mii.h> -#include <linux/usb.h> - -#include "usbnet.h" - - -/* - * GeneSys GL620USB-A (www.genesyslogic.com.tw) - * - * ... should partially interop with the Win32 driver for this hardware. - * The GeneSys docs imply there's some NDIS issue motivating this framing. - * - * Some info from GeneSys: - * - GL620USB-A is full duplex; GL620USB is only half duplex for bulk. - * (Some cables, like the BAFO-100c, use the half duplex version.) - * - For the full duplex model, the low bit of the version code says - * which side is which ("left/right"). - * - For the half duplex type, a control/interrupt handshake settles - * the transfer direction. (That's disabled here, partially coded.) - * A control URB would block until other side writes an interrupt. - * - * Original code from Jiun-Jie Huang <huangjj@genesyslogic.com.tw> - * and merged into "usbnet" by Stanislav Brabec <utx@penguin.cz>. - */ - -// control msg write command -#define GENELINK_CONNECT_WRITE 0xF0 -// interrupt pipe index -#define GENELINK_INTERRUPT_PIPE 0x03 -// interrupt read buffer size -#define INTERRUPT_BUFSIZE 0x08 -// interrupt pipe interval value -#define GENELINK_INTERRUPT_INTERVAL 0x10 -// max transmit packet number per transmit -#define GL_MAX_TRANSMIT_PACKETS 32 -// max packet length -#define GL_MAX_PACKET_LEN 1514 -// max receive buffer size -#define GL_RCV_BUF_SIZE \ - (((GL_MAX_PACKET_LEN + 4) * GL_MAX_TRANSMIT_PACKETS) + 4) - -struct gl_packet { - u32 packet_length; - char packet_data [1]; -}; - -struct gl_header { - u32 packet_count; - struct gl_packet packets; -}; - -#ifdef GENELINK_ACK - -// FIXME: this code is incomplete, not debugged; it doesn't -// handle interrupts correctly; it should use the generic -// status IRQ code (which didn't exist back in 2001). - -struct gl_priv { - struct urb *irq_urb; - char irq_buf [INTERRUPT_BUFSIZE]; -}; - -static inline int gl_control_write(struct usbnet *dev, u8 request, u16 value) -{ - int retval; - - retval = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - request, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - value, - 0, // index - 0, // data buffer - 0, // size - USB_CTRL_SET_TIMEOUT); - return retval; -} - -static void gl_interrupt_complete(struct urb *urb, struct pt_regs *regs) -{ - int status = urb->status; - - switch (status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __FUNCTION__, status); - return; - default: - dbg("%s - nonzero urb status received: %d", - __FUNCTION__, urb->status); - } - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) - err("%s - usb_submit_urb failed with result %d", - __FUNCTION__, status); -} - -static int gl_interrupt_read(struct usbnet *dev) -{ - struct gl_priv *priv = dev->priv_data; - int retval; - - // issue usb interrupt read - if (priv && priv->irq_urb) { - // submit urb - if ((retval = usb_submit_urb(priv->irq_urb, GFP_KERNEL)) != 0) - dbg("gl_interrupt_read: submit fail - %X...", retval); - else - dbg("gl_interrupt_read: submit success..."); - } - - return 0; -} - -// check whether another side is connected -static int genelink_check_connect(struct usbnet *dev) -{ - int retval; - - dbg("genelink_check_connect..."); - - // detect whether another side is connected - if ((retval = gl_control_write(dev, GENELINK_CONNECT_WRITE, 0)) != 0) { - dbg("%s: genelink_check_connect write fail - %X", - dev->net->name, retval); - return retval; - } - - // usb interrupt read to ack another side - if ((retval = gl_interrupt_read(dev)) != 0) { - dbg("%s: genelink_check_connect read fail - %X", - dev->net->name, retval); - return retval; - } - - dbg("%s: genelink_check_connect read success", dev->net->name); - return 0; -} - -// allocate and initialize the private data for genelink -static int genelink_init(struct usbnet *dev) -{ - struct gl_priv *priv; - - // allocate the private data structure - if ((priv = kmalloc(sizeof *priv, GFP_KERNEL)) == 0) { - dbg("%s: cannot allocate private data per device", - dev->net->name); - return -ENOMEM; - } - - // allocate irq urb - if ((priv->irq_urb = usb_alloc_urb(0, GFP_KERNEL)) == 0) { - dbg("%s: cannot allocate private irq urb per device", - dev->net->name); - kfree(priv); - return -ENOMEM; - } - - // fill irq urb - usb_fill_int_urb(priv->irq_urb, dev->udev, - usb_rcvintpipe(dev->udev, GENELINK_INTERRUPT_PIPE), - priv->irq_buf, INTERRUPT_BUFSIZE, - gl_interrupt_complete, 0, - GENELINK_INTERRUPT_INTERVAL); - - // set private data pointer - dev->priv_data = priv; - - return 0; -} - -// release the private data -static int genelink_free(struct usbnet *dev) -{ - struct gl_priv *priv = dev->priv_data; - - if (!priv) - return 0; - -// FIXME: can't cancel here; it's synchronous, and -// should have happened earlier in any case (interrupt -// handling needs to be generic) - - // cancel irq urb first - usb_kill_urb(priv->irq_urb); - - // free irq urb - usb_free_urb(priv->irq_urb); - - // free the private data structure - kfree(priv); - - return 0; -} - -#endif - -static int genelink_rx_fixup(struct usbnet *dev, struct sk_buff *skb) -{ - struct gl_header *header; - struct gl_packet *packet; - struct sk_buff *gl_skb; - u32 size; - - header = (struct gl_header *) skb->data; - - // get the packet count of the received skb - le32_to_cpus(&header->packet_count); - if ((header->packet_count > GL_MAX_TRANSMIT_PACKETS) - || (header->packet_count < 0)) { - dbg("genelink: invalid received packet count %d", - header->packet_count); - return 0; - } - - // set the current packet pointer to the first packet - packet = &header->packets; - - // decrement the length for the packet count size 4 bytes - skb_pull(skb, 4); - - while (header->packet_count > 1) { - // get the packet length - size = le32_to_cpu(packet->packet_length); - - // this may be a broken packet - if (size > GL_MAX_PACKET_LEN) { - dbg("genelink: invalid rx length %d", size); - return 0; - } - - // allocate the skb for the individual packet - gl_skb = alloc_skb(size, GFP_ATOMIC); - if (gl_skb) { - - // copy the packet data to the new skb - memcpy(skb_put(gl_skb, size), - packet->packet_data, size); - usbnet_skb_return(dev, gl_skb); - } - - // advance to the next packet - packet = (struct gl_packet *) - &packet->packet_data [size]; - header->packet_count--; - - // shift the data pointer to the next gl_packet - skb_pull(skb, size + 4); - } - - // skip the packet length field 4 bytes - skb_pull(skb, 4); - - if (skb->len > GL_MAX_PACKET_LEN) { - dbg("genelink: invalid rx length %d", skb->len); - return 0; - } - return 1; -} - -static struct sk_buff * -genelink_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) -{ - int padlen; - int length = skb->len; - int headroom = skb_headroom(skb); - int tailroom = skb_tailroom(skb); - u32 *packet_count; - u32 *packet_len; - - // FIXME: magic numbers, bleech - padlen = ((skb->len + (4 + 4*1)) % 64) ? 0 : 1; - - if ((!skb_cloned(skb)) - && ((headroom + tailroom) >= (padlen + (4 + 4*1)))) { - if ((headroom < (4 + 4*1)) || (tailroom < padlen)) { - skb->data = memmove(skb->head + (4 + 4*1), - skb->data, skb->len); - skb->tail = skb->data + skb->len; - } - } else { - struct sk_buff *skb2; - skb2 = skb_copy_expand(skb, (4 + 4*1) , padlen, flags); - dev_kfree_skb_any(skb); - skb = skb2; - if (!skb) - return NULL; - } - - // attach the packet count to the header - packet_count = (u32 *) skb_push(skb, (4 + 4*1)); - packet_len = packet_count + 1; - - *packet_count = cpu_to_le32(1); - *packet_len = cpu_to_le32(length); - - // add padding byte - if ((skb->len % dev->maxpacket) == 0) - skb_put(skb, 1); - - return skb; -} - -static int genelink_bind(struct usbnet *dev, struct usb_interface *intf) -{ - dev->hard_mtu = GL_RCV_BUF_SIZE; - dev->net->hard_header_len += 4; - dev->in = usb_rcvbulkpipe(dev->udev, dev->driver_info->in); - dev->out = usb_sndbulkpipe(dev->udev, dev->driver_info->out); - return 0; -} - -static const struct driver_info genelink_info = { - .description = "Genesys GeneLink", - .flags = FLAG_FRAMING_GL | FLAG_NO_SETINT, - .bind = genelink_bind, - .rx_fixup = genelink_rx_fixup, - .tx_fixup = genelink_tx_fixup, - - .in = 1, .out = 2, - -#ifdef GENELINK_ACK - .check_connect =genelink_check_connect, -#endif -}; - -static const struct usb_device_id products [] = { - -{ - USB_DEVICE(0x05e3, 0x0502), // GL620USB-A - .driver_info = (unsigned long) &genelink_info, -}, - /* NOT: USB_DEVICE(0x05e3, 0x0501), // GL620USB - * that's half duplex, not currently supported - */ - { }, // END -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver gl620a_driver = { - .owner = THIS_MODULE, - .name = "gl620a", - .id_table = products, - .probe = usbnet_probe, - .disconnect = usbnet_disconnect, - .suspend = usbnet_suspend, - .resume = usbnet_resume, -}; - -static int __init usbnet_init(void) -{ - return usb_register(&gl620a_driver); -} -module_init(usbnet_init); - -static void __exit usbnet_exit(void) -{ - usb_deregister(&gl620a_driver); -} -module_exit(usbnet_exit); - -MODULE_AUTHOR("Jiun-Jie Huang"); -MODULE_DESCRIPTION("GL620-USB-A Host-to-Host Link cables"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c deleted file mode 100644 index 6bef1be6b36..00000000000 --- a/drivers/usb/net/kaweth.c +++ /dev/null @@ -1,1270 +0,0 @@ -/**************************************************************** - * - * kaweth.c - driver for KL5KUSB101 based USB->Ethernet - * - * (c) 2000 Interlan Communications - * (c) 2000 Stephane Alnet - * (C) 2001 Brad Hards - * (C) 2002 Oliver Neukum - * - * Original author: The Zapman <zapman@interlan.net> - * Inspired by, and much credit goes to Michael Rothwell - * <rothwell@interlan.net> for the test equipment, help, and patience - * Based off of (and with thanks to) Petko Manolov's pegaus.c driver. - * Also many thanks to Joel Silverman and Ed Surprenant at Kawasaki - * for providing the firmware and driver resources. - * - * 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 the Free Software Foundation; either version 2, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - ****************************************************************/ - -/* TODO: - * Fix in_interrupt() problem - * Develop test procedures for USB net interfaces - * Run test procedures - * Fix bugs from previous two steps - * Snoop other OSs for any tricks we're not doing - * SMP locking - * Reduce arbitrary timeouts - * Smart multicast support - * Temporary MAC change support - * Tunable SOFs parameter - ioctl()? - * Ethernet stats collection - * Code formatting improvements - */ - -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/usb.h> -#include <linux/types.h> -#include <linux/ethtool.h> -#include <linux/pci.h> -#include <linux/dma-mapping.h> -#include <linux/wait.h> -#include <asm/uaccess.h> -#include <asm/semaphore.h> -#include <asm/byteorder.h> - -#undef DEBUG - -#ifdef DEBUG -#define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg) -#else -#define kaweth_dbg(format, arg...) do {} while (0) -#endif -#define kaweth_err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" ,##arg) -#define kaweth_info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ##arg) -#define kaweth_warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ##arg) - - -#include "kawethfw.h" - -#define KAWETH_MTU 1514 -#define KAWETH_BUF_SIZE 1664 -#define KAWETH_TX_TIMEOUT (5 * HZ) -#define KAWETH_SCRATCH_SIZE 32 -#define KAWETH_FIRMWARE_BUF_SIZE 4096 -#define KAWETH_CONTROL_TIMEOUT (30 * HZ) - -#define KAWETH_STATUS_BROKEN 0x0000001 -#define KAWETH_STATUS_CLOSING 0x0000002 - -#define KAWETH_PACKET_FILTER_PROMISCUOUS 0x01 -#define KAWETH_PACKET_FILTER_ALL_MULTICAST 0x02 -#define KAWETH_PACKET_FILTER_DIRECTED 0x04 -#define KAWETH_PACKET_FILTER_BROADCAST 0x08 -#define KAWETH_PACKET_FILTER_MULTICAST 0x10 - -/* Table 7 */ -#define KAWETH_COMMAND_GET_ETHERNET_DESC 0x00 -#define KAWETH_COMMAND_MULTICAST_FILTERS 0x01 -#define KAWETH_COMMAND_SET_PACKET_FILTER 0x02 -#define KAWETH_COMMAND_STATISTICS 0x03 -#define KAWETH_COMMAND_SET_TEMP_MAC 0x06 -#define KAWETH_COMMAND_GET_TEMP_MAC 0x07 -#define KAWETH_COMMAND_SET_URB_SIZE 0x08 -#define KAWETH_COMMAND_SET_SOFS_WAIT 0x09 -#define KAWETH_COMMAND_SCAN 0xFF - -#define KAWETH_SOFS_TO_WAIT 0x05 - -#define INTBUFFERSIZE 4 - -#define STATE_OFFSET 0 -#define STATE_MASK 0x40 -#define STATE_SHIFT 5 - - -MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr>, Brad Hards <bhards@bigpond.net.au> and Oliver Neukum <oliver@neukum.org>"); -MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver"); -MODULE_LICENSE("GPL"); - -static const char driver_name[] = "kaweth"; - -static int kaweth_probe( - struct usb_interface *intf, - const struct usb_device_id *id /* from id_table */ - ); -static void kaweth_disconnect(struct usb_interface *intf); -static int kaweth_internal_control_msg(struct usb_device *usb_dev, - unsigned int pipe, - struct usb_ctrlrequest *cmd, void *data, - int len, int timeout); - -/**************************************************************** - * usb_device_id - ****************************************************************/ -static struct usb_device_id usb_klsi_table[] = { - { USB_DEVICE(0x03e8, 0x0008) }, /* AOX Endpoints USB Ethernet */ - { USB_DEVICE(0x04bb, 0x0901) }, /* I-O DATA USB-ET/T */ - { USB_DEVICE(0x0506, 0x03e8) }, /* 3Com 3C19250 */ - { USB_DEVICE(0x0506, 0x11f8) }, /* 3Com 3C460 */ - { USB_DEVICE(0x0557, 0x2002) }, /* ATEN USB Ethernet */ - { USB_DEVICE(0x0557, 0x4000) }, /* D-Link DSB-650C */ - { USB_DEVICE(0x0565, 0x0002) }, /* Peracom Enet */ - { USB_DEVICE(0x0565, 0x0003) }, /* Optus@Home UEP1045A */ - { USB_DEVICE(0x0565, 0x0005) }, /* Peracom Enet2 */ - { USB_DEVICE(0x05e9, 0x0008) }, /* KLSI KL5KUSB101B */ - { USB_DEVICE(0x05e9, 0x0009) }, /* KLSI KL5KUSB101B (Board change) */ - { USB_DEVICE(0x066b, 0x2202) }, /* Linksys USB10T */ - { USB_DEVICE(0x06e1, 0x0008) }, /* ADS USB-10BT */ - { USB_DEVICE(0x06e1, 0x0009) }, /* ADS USB-10BT */ - { USB_DEVICE(0x0707, 0x0100) }, /* SMC 2202USB */ - { USB_DEVICE(0x07aa, 0x0001) }, /* Correga K.K. */ - { USB_DEVICE(0x07b8, 0x4000) }, /* D-Link DU-E10 */ - { USB_DEVICE(0x0846, 0x1001) }, /* NetGear EA-101 */ - { USB_DEVICE(0x0846, 0x1002) }, /* NetGear EA-101 */ - { USB_DEVICE(0x085a, 0x0008) }, /* PortGear Ethernet Adapter */ - { USB_DEVICE(0x085a, 0x0009) }, /* PortGear Ethernet Adapter */ - { USB_DEVICE(0x087d, 0x5704) }, /* Jaton USB Ethernet Device Adapter */ - { USB_DEVICE(0x0951, 0x0008) }, /* Kingston Technology USB Ethernet Adapter */ - { USB_DEVICE(0x095a, 0x3003) }, /* Portsmith Express Ethernet Adapter */ - { USB_DEVICE(0x10bd, 0x1427) }, /* ASANTE USB To Ethernet Adapter */ - { USB_DEVICE(0x1342, 0x0204) }, /* Mobility USB-Ethernet Adapter */ - { USB_DEVICE(0x13d2, 0x0400) }, /* Shark Pocket Adapter */ - { USB_DEVICE(0x1485, 0x0001) }, /* Silicom U2E */ - { USB_DEVICE(0x1485, 0x0002) }, /* Psion Dacom Gold Port Ethernet */ - { USB_DEVICE(0x1645, 0x0005) }, /* Entrega E45 */ - { USB_DEVICE(0x1645, 0x0008) }, /* Entrega USB Ethernet Adapter */ - { USB_DEVICE(0x1645, 0x8005) }, /* PortGear Ethernet Adapter */ - { USB_DEVICE(0x2001, 0x4000) }, /* D-link DSB-650C */ - {} /* Null terminator */ -}; - -MODULE_DEVICE_TABLE (usb, usb_klsi_table); - -/**************************************************************** - * kaweth_driver - ****************************************************************/ -static struct usb_driver kaweth_driver = { - .owner = THIS_MODULE, - .name = driver_name, - .probe = kaweth_probe, - .disconnect = kaweth_disconnect, - .id_table = usb_klsi_table, -}; - -typedef __u8 eth_addr_t[6]; - -/**************************************************************** - * usb_eth_dev - ****************************************************************/ -struct usb_eth_dev { - char *name; - __u16 vendor; - __u16 device; - void *pdata; -}; - -/**************************************************************** - * kaweth_ethernet_configuration - * Refer Table 8 - ****************************************************************/ -struct kaweth_ethernet_configuration -{ - __u8 size; - __u8 reserved1; - __u8 reserved2; - eth_addr_t hw_addr; - __u32 statistics_mask; - __le16 segment_size; - __u16 max_multicast_filters; - __u8 reserved3; -} __attribute__ ((packed)); - -/**************************************************************** - * kaweth_device - ****************************************************************/ -struct kaweth_device -{ - spinlock_t device_lock; - - __u32 status; - int end; - int removed; - int suspend_lowmem_rx; - int suspend_lowmem_ctrl; - int linkstate; - struct work_struct lowmem_work; - - struct usb_device *dev; - struct net_device *net; - wait_queue_head_t term_wait; - - struct urb *rx_urb; - struct urb *tx_urb; - struct urb *irq_urb; - - dma_addr_t intbufferhandle; - __u8 *intbuffer; - dma_addr_t rxbufferhandle; - __u8 *rx_buf; - - - struct sk_buff *tx_skb; - - __u8 *firmware_buf; - __u8 scratch[KAWETH_SCRATCH_SIZE]; - __u16 packet_filter_bitmap; - - struct kaweth_ethernet_configuration configuration; - - struct net_device_stats stats; -}; - - -/**************************************************************** - * kaweth_control - ****************************************************************/ -static int kaweth_control(struct kaweth_device *kaweth, - unsigned int pipe, - __u8 request, - __u8 requesttype, - __u16 value, - __u16 index, - void *data, - __u16 size, - int timeout) -{ - struct usb_ctrlrequest *dr; - - kaweth_dbg("kaweth_control()"); - - if(in_interrupt()) { - kaweth_dbg("in_interrupt()"); - return -EBUSY; - } - - dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); - - if (!dr) { - kaweth_dbg("kmalloc() failed"); - return -ENOMEM; - } - - dr->bRequestType= requesttype; - dr->bRequest = request; - dr->wValue = cpu_to_le16p(&value); - dr->wIndex = cpu_to_le16p(&index); - dr->wLength = cpu_to_le16p(&size); - - return kaweth_internal_control_msg(kaweth->dev, - pipe, - dr, - data, - size, - timeout); -} - -/**************************************************************** - * kaweth_read_configuration - ****************************************************************/ -static int kaweth_read_configuration(struct kaweth_device *kaweth) -{ - int retval; - - kaweth_dbg("Reading kaweth configuration"); - - retval = kaweth_control(kaweth, - usb_rcvctrlpipe(kaweth->dev, 0), - KAWETH_COMMAND_GET_ETHERNET_DESC, - USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE, - 0, - 0, - (void *)&kaweth->configuration, - sizeof(kaweth->configuration), - KAWETH_CONTROL_TIMEOUT); - - return retval; -} - -/**************************************************************** - * kaweth_set_urb_size - ****************************************************************/ -static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size) -{ - int retval; - - kaweth_dbg("Setting URB size to %d", (unsigned)urb_size); - - retval = kaweth_control(kaweth, - usb_sndctrlpipe(kaweth->dev, 0), - KAWETH_COMMAND_SET_URB_SIZE, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - urb_size, - 0, - (void *)&kaweth->scratch, - 0, - KAWETH_CONTROL_TIMEOUT); - - return retval; -} - -/**************************************************************** - * kaweth_set_sofs_wait - ****************************************************************/ -static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait) -{ - int retval; - - kaweth_dbg("Set SOFS wait to %d", (unsigned)sofs_wait); - - retval = kaweth_control(kaweth, - usb_sndctrlpipe(kaweth->dev, 0), - KAWETH_COMMAND_SET_SOFS_WAIT, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - sofs_wait, - 0, - (void *)&kaweth->scratch, - 0, - KAWETH_CONTROL_TIMEOUT); - - return retval; -} - -/**************************************************************** - * kaweth_set_receive_filter - ****************************************************************/ -static int kaweth_set_receive_filter(struct kaweth_device *kaweth, - __u16 receive_filter) -{ - int retval; - - kaweth_dbg("Set receive filter to %d", (unsigned)receive_filter); - - retval = kaweth_control(kaweth, - usb_sndctrlpipe(kaweth->dev, 0), - KAWETH_COMMAND_SET_PACKET_FILTER, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - receive_filter, - 0, - (void *)&kaweth->scratch, - 0, - KAWETH_CONTROL_TIMEOUT); - - return retval; -} - -/**************************************************************** - * kaweth_download_firmware - ****************************************************************/ -static int kaweth_download_firmware(struct kaweth_device *kaweth, - __u8 *data, - __u16 data_len, - __u8 interrupt, - __u8 type) -{ - if(data_len > KAWETH_FIRMWARE_BUF_SIZE) { - kaweth_err("Firmware too big: %d", data_len); - return -ENOSPC; - } - - memcpy(kaweth->firmware_buf, data, data_len); - - kaweth->firmware_buf[2] = (data_len & 0xFF) - 7; - kaweth->firmware_buf[3] = data_len >> 8; - kaweth->firmware_buf[4] = type; - kaweth->firmware_buf[5] = interrupt; - - kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3], - kaweth->firmware_buf[2]); - - kaweth_dbg("Downloading firmware at %p to kaweth device at %p", - data, - kaweth); - kaweth_dbg("Firmware length: %d", data_len); - - return kaweth_control(kaweth, - usb_sndctrlpipe(kaweth->dev, 0), - KAWETH_COMMAND_SCAN, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - 0, - 0, - (void *)kaweth->firmware_buf, - data_len, - KAWETH_CONTROL_TIMEOUT); -} - -/**************************************************************** - * kaweth_trigger_firmware - ****************************************************************/ -static int kaweth_trigger_firmware(struct kaweth_device *kaweth, - __u8 interrupt) -{ - kaweth->firmware_buf[0] = 0xB6; - kaweth->firmware_buf[1] = 0xC3; - kaweth->firmware_buf[2] = 0x01; - kaweth->firmware_buf[3] = 0x00; - kaweth->firmware_buf[4] = 0x06; - kaweth->firmware_buf[5] = interrupt; - kaweth->firmware_buf[6] = 0x00; - kaweth->firmware_buf[7] = 0x00; - - kaweth_dbg("Triggering firmware"); - - return kaweth_control(kaweth, - usb_sndctrlpipe(kaweth->dev, 0), - KAWETH_COMMAND_SCAN, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - 0, - 0, - (void *)kaweth->firmware_buf, - 8, - KAWETH_CONTROL_TIMEOUT); -} - -/**************************************************************** - * kaweth_reset - ****************************************************************/ -static int kaweth_reset(struct kaweth_device *kaweth) -{ - int result; - - kaweth_dbg("kaweth_reset(%p)", kaweth); - result = kaweth_control(kaweth, - usb_sndctrlpipe(kaweth->dev, 0), - USB_REQ_SET_CONFIGURATION, - 0, - kaweth->dev->config[0].desc.bConfigurationValue, - 0, - NULL, - 0, - KAWETH_CONTROL_TIMEOUT); - - mdelay(10); - - kaweth_dbg("kaweth_reset() returns %d.",result); - - return result; -} - -static void kaweth_usb_receive(struct urb *, struct pt_regs *regs); -static int kaweth_resubmit_rx_urb(struct kaweth_device *, gfp_t); - -/**************************************************************** - int_callback -*****************************************************************/ - -static void kaweth_resubmit_int_urb(struct kaweth_device *kaweth, gfp_t mf) -{ - int status; - - status = usb_submit_urb (kaweth->irq_urb, mf); - if (unlikely(status == -ENOMEM)) { - kaweth->suspend_lowmem_ctrl = 1; - schedule_delayed_work(&kaweth->lowmem_work, HZ/4); - } else { - kaweth->suspend_lowmem_ctrl = 0; - } - - if (status) - err ("can't resubmit intr, %s-%s, status %d", - kaweth->dev->bus->bus_name, - kaweth->dev->devpath, status); -} - -static void int_callback(struct urb *u, struct pt_regs *regs) -{ - struct kaweth_device *kaweth = u->context; - int act_state; - - switch (u->status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - /* we check the link state to report changes */ - if (kaweth->linkstate != (act_state = ( kaweth->intbuffer[STATE_OFFSET] | STATE_MASK) >> STATE_SHIFT)) { - if (act_state) - netif_carrier_on(kaweth->net); - else - netif_carrier_off(kaweth->net); - - kaweth->linkstate = act_state; - } -resubmit: - kaweth_resubmit_int_urb(kaweth, GFP_ATOMIC); -} - -static void kaweth_resubmit_tl(void *d) -{ - struct kaweth_device *kaweth = (struct kaweth_device *)d; - - if (kaweth->status | KAWETH_STATUS_CLOSING) - return; - - if (kaweth->suspend_lowmem_rx) - kaweth_resubmit_rx_urb(kaweth, GFP_NOIO); - - if (kaweth->suspend_lowmem_ctrl) - kaweth_resubmit_int_urb(kaweth, GFP_NOIO); -} - - -/**************************************************************** - * kaweth_resubmit_rx_urb - ****************************************************************/ -static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, - gfp_t mem_flags) -{ - int result; - - usb_fill_bulk_urb(kaweth->rx_urb, - kaweth->dev, - usb_rcvbulkpipe(kaweth->dev, 1), - kaweth->rx_buf, - KAWETH_BUF_SIZE, - kaweth_usb_receive, - kaweth); - kaweth->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - kaweth->rx_urb->transfer_dma = kaweth->rxbufferhandle; - - if((result = usb_submit_urb(kaweth->rx_urb, mem_flags))) { - if (result == -ENOMEM) { - kaweth->suspend_lowmem_rx = 1; - schedule_delayed_work(&kaweth->lowmem_work, HZ/4); - } - kaweth_err("resubmitting rx_urb %d failed", result); - } else { - kaweth->suspend_lowmem_rx = 0; - } - - return result; -} - -static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth); - -/**************************************************************** - * kaweth_usb_receive - ****************************************************************/ -static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs) -{ - struct kaweth_device *kaweth = urb->context; - struct net_device *net = kaweth->net; - - int count = urb->actual_length; - int count2 = urb->transfer_buffer_length; - - __u16 pkt_len = le16_to_cpup((__le16 *)kaweth->rx_buf); - - struct sk_buff *skb; - - if(unlikely(urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) - /* we are killed - set a flag and wake the disconnect handler */ - { - kaweth->end = 1; - wake_up(&kaweth->term_wait); - return; - } - - if (kaweth->status & KAWETH_STATUS_CLOSING) - return; - - if(urb->status && urb->status != -EREMOTEIO && count != 1) { - kaweth_err("%s RX status: %d count: %d packet_len: %d", - net->name, - urb->status, - count, - (int)pkt_len); - kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); - return; - } - - if(kaweth->net && (count > 2)) { - if(pkt_len > (count - 2)) { - kaweth_err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count); - kaweth_err("Packet len & 2047: %x", pkt_len & 2047); - kaweth_err("Count 2: %x", count2); - kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); - return; - } - - if(!(skb = dev_alloc_skb(pkt_len+2))) { - kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); - return; - } - - skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ - - skb->dev = net; - - eth_copy_and_sum(skb, kaweth->rx_buf + 2, pkt_len, 0); - - skb_put(skb, pkt_len); - - skb->protocol = eth_type_trans(skb, net); - - netif_rx(skb); - - kaweth->stats.rx_packets++; - kaweth->stats.rx_bytes += pkt_len; - } - - kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); -} - -/**************************************************************** - * kaweth_open - ****************************************************************/ -static int kaweth_open(struct net_device *net) -{ - struct kaweth_device *kaweth = netdev_priv(net); - int res; - - kaweth_dbg("Opening network device."); - - res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL); - if (res) - return -EIO; - - usb_fill_int_urb( - kaweth->irq_urb, - kaweth->dev, - usb_rcvintpipe(kaweth->dev, 3), - kaweth->intbuffer, - INTBUFFERSIZE, - int_callback, - kaweth, - 250); /* overriding the descriptor */ - kaweth->irq_urb->transfer_dma = kaweth->intbufferhandle; - kaweth->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - res = usb_submit_urb(kaweth->irq_urb, GFP_KERNEL); - if (res) { - usb_kill_urb(kaweth->rx_urb); - return -EIO; - } - - netif_start_queue(net); - - kaweth_async_set_rx_mode(kaweth); - return 0; -} - -/**************************************************************** - * kaweth_close - ****************************************************************/ -static int kaweth_close(struct net_device *net) -{ - struct kaweth_device *kaweth = netdev_priv(net); - - netif_stop_queue(net); - - kaweth->status |= KAWETH_STATUS_CLOSING; - - usb_kill_urb(kaweth->irq_urb); - usb_kill_urb(kaweth->rx_urb); - - flush_scheduled_work(); - - /* a scheduled work may have resubmitted, - we hit them again */ - usb_kill_urb(kaweth->irq_urb); - usb_kill_urb(kaweth->rx_urb); - - kaweth->status &= ~KAWETH_STATUS_CLOSING; - - return 0; -} - -static void kaweth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - - strlcpy(info->driver, driver_name, sizeof(info->driver)); -} - -static struct ethtool_ops ops = { - .get_drvinfo = kaweth_get_drvinfo -}; - -/**************************************************************** - * kaweth_usb_transmit_complete - ****************************************************************/ -static void kaweth_usb_transmit_complete(struct urb *urb, struct pt_regs *regs) -{ - struct kaweth_device *kaweth = urb->context; - struct sk_buff *skb = kaweth->tx_skb; - - if (unlikely(urb->status != 0)) - if (urb->status != -ENOENT) - kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status); - - netif_wake_queue(kaweth->net); - dev_kfree_skb_irq(skb); -} - -/**************************************************************** - * kaweth_start_xmit - ****************************************************************/ -static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) -{ - struct kaweth_device *kaweth = netdev_priv(net); - __le16 *private_header; - - int res; - - spin_lock(&kaweth->device_lock); - - if (kaweth->removed) { - /* our device is undergoing disconnection - we bail out */ - spin_unlock(&kaweth->device_lock); - dev_kfree_skb_irq(skb); - return 0; - } - - kaweth_async_set_rx_mode(kaweth); - netif_stop_queue(net); - - /* We now decide whether we can put our special header into the sk_buff */ - if (skb_cloned(skb) || skb_headroom(skb) < 2) { - /* no such luck - we make our own */ - struct sk_buff *copied_skb; - copied_skb = skb_copy_expand(skb, 2, 0, GFP_ATOMIC); - dev_kfree_skb_irq(skb); - skb = copied_skb; - if (!copied_skb) { - kaweth->stats.tx_errors++; - netif_start_queue(net); - spin_unlock(&kaweth->device_lock); - return 0; - } - } - - private_header = (__le16 *)__skb_push(skb, 2); - *private_header = cpu_to_le16(skb->len-2); - kaweth->tx_skb = skb; - - usb_fill_bulk_urb(kaweth->tx_urb, - kaweth->dev, - usb_sndbulkpipe(kaweth->dev, 2), - private_header, - skb->len, - kaweth_usb_transmit_complete, - kaweth); - kaweth->end = 0; - - if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC))) - { - kaweth_warn("kaweth failed tx_urb %d", res); - kaweth->stats.tx_errors++; - - netif_start_queue(net); - dev_kfree_skb_irq(skb); - } - else - { - kaweth->stats.tx_packets++; - kaweth->stats.tx_bytes += skb->len; - net->trans_start = jiffies; - } - - spin_unlock(&kaweth->device_lock); - - return 0; -} - -/**************************************************************** - * kaweth_set_rx_mode - ****************************************************************/ -static void kaweth_set_rx_mode(struct net_device *net) -{ - struct kaweth_device *kaweth = netdev_priv(net); - - __u16 packet_filter_bitmap = KAWETH_PACKET_FILTER_DIRECTED | - KAWETH_PACKET_FILTER_BROADCAST | - KAWETH_PACKET_FILTER_MULTICAST; - - kaweth_dbg("Setting Rx mode to %d", packet_filter_bitmap); - - netif_stop_queue(net); - - if (net->flags & IFF_PROMISC) { - packet_filter_bitmap |= KAWETH_PACKET_FILTER_PROMISCUOUS; - } - else if ((net->mc_count) || (net->flags & IFF_ALLMULTI)) { - packet_filter_bitmap |= KAWETH_PACKET_FILTER_ALL_MULTICAST; - } - - kaweth->packet_filter_bitmap = packet_filter_bitmap; - netif_wake_queue(net); -} - -/**************************************************************** - * kaweth_async_set_rx_mode - ****************************************************************/ -static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) -{ - __u16 packet_filter_bitmap = kaweth->packet_filter_bitmap; - kaweth->packet_filter_bitmap = 0; - if (packet_filter_bitmap == 0) - return; - - { - int result; - result = kaweth_control(kaweth, - usb_sndctrlpipe(kaweth->dev, 0), - KAWETH_COMMAND_SET_PACKET_FILTER, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - packet_filter_bitmap, - 0, - (void *)&kaweth->scratch, - 0, - KAWETH_CONTROL_TIMEOUT); - - if(result < 0) { - kaweth_err("Failed to set Rx mode: %d", result); - } - else { - kaweth_dbg("Set Rx mode to %d", packet_filter_bitmap); - } - } -} - -/**************************************************************** - * kaweth_netdev_stats - ****************************************************************/ -static struct net_device_stats *kaweth_netdev_stats(struct net_device *dev) -{ - struct kaweth_device *kaweth = netdev_priv(dev); - return &kaweth->stats; -} - -/**************************************************************** - * kaweth_tx_timeout - ****************************************************************/ -static void kaweth_tx_timeout(struct net_device *net) -{ - struct kaweth_device *kaweth = netdev_priv(net); - - kaweth_warn("%s: Tx timed out. Resetting.", net->name); - kaweth->stats.tx_errors++; - net->trans_start = jiffies; - - usb_unlink_urb(kaweth->tx_urb); -} - -/**************************************************************** - * kaweth_probe - ****************************************************************/ -static int kaweth_probe( - struct usb_interface *intf, - const struct usb_device_id *id /* from id_table */ - ) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct kaweth_device *kaweth; - struct net_device *netdev; - const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - int result = 0; - - kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x", - dev->devnum, - le16_to_cpu(dev->descriptor.idVendor), - le16_to_cpu(dev->descriptor.idProduct), - le16_to_cpu(dev->descriptor.bcdDevice)); - - kaweth_dbg("Device at %p", dev); - - kaweth_dbg("Descriptor length: %x type: %x", - (int)dev->descriptor.bLength, - (int)dev->descriptor.bDescriptorType); - - netdev = alloc_etherdev(sizeof(*kaweth)); - if (!netdev) - return -ENOMEM; - - kaweth = netdev_priv(netdev); - kaweth->dev = dev; - kaweth->net = netdev; - - spin_lock_init(&kaweth->device_lock); - init_waitqueue_head(&kaweth->term_wait); - - kaweth_dbg("Resetting."); - - kaweth_reset(kaweth); - - /* - * If high byte of bcdDevice is nonzero, firmware is already - * downloaded. Don't try to do it again, or we'll hang the device. - */ - - if (le16_to_cpu(dev->descriptor.bcdDevice) >> 8) { - kaweth_info("Firmware present in device."); - } else { - /* Download the firmware */ - kaweth_info("Downloading firmware..."); - kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL); - if ((result = kaweth_download_firmware(kaweth, - kaweth_new_code, - len_kaweth_new_code, - 100, - 2)) < 0) { - kaweth_err("Error downloading firmware (%d)", result); - goto err_fw; - } - - if ((result = kaweth_download_firmware(kaweth, - kaweth_new_code_fix, - len_kaweth_new_code_fix, - 100, - 3)) < 0) { - kaweth_err("Error downloading firmware fix (%d)", result); - goto err_fw; - } - - if ((result = kaweth_download_firmware(kaweth, - kaweth_trigger_code, - len_kaweth_trigger_code, - 126, - 2)) < 0) { - kaweth_err("Error downloading trigger code (%d)", result); - goto err_fw; - - } - - if ((result = kaweth_download_firmware(kaweth, - kaweth_trigger_code_fix, - len_kaweth_trigger_code_fix, - 126, - 3)) < 0) { - kaweth_err("Error downloading trigger code fix (%d)", result); - goto err_fw; - } - - - if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) { - kaweth_err("Error triggering firmware (%d)", result); - goto err_fw; - } - - /* Device will now disappear for a moment... */ - kaweth_info("Firmware loaded. I'll be back..."); -err_fw: - free_page((unsigned long)kaweth->firmware_buf); - free_netdev(netdev); - return -EIO; - } - - result = kaweth_read_configuration(kaweth); - - if(result < 0) { - kaweth_err("Error reading configuration (%d), no net device created", result); - goto err_free_netdev; - } - - kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask); - kaweth_info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1)); - kaweth_info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size)); - kaweth_info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", - (int)kaweth->configuration.hw_addr[0], - (int)kaweth->configuration.hw_addr[1], - (int)kaweth->configuration.hw_addr[2], - (int)kaweth->configuration.hw_addr[3], - (int)kaweth->configuration.hw_addr[4], - (int)kaweth->configuration.hw_addr[5]); - - if(!memcmp(&kaweth->configuration.hw_addr, - &bcast_addr, - sizeof(bcast_addr))) { - kaweth_err("Firmware not functioning properly, no net device created"); - goto err_free_netdev; - } - - if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) { - kaweth_dbg("Error setting URB size"); - goto err_free_netdev; - } - - if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) { - kaweth_err("Error setting SOFS wait"); - goto err_free_netdev; - } - - result = kaweth_set_receive_filter(kaweth, - KAWETH_PACKET_FILTER_DIRECTED | - KAWETH_PACKET_FILTER_BROADCAST | - KAWETH_PACKET_FILTER_MULTICAST); - - if(result < 0) { - kaweth_err("Error setting receive filter"); - goto err_free_netdev; - } - - kaweth_dbg("Initializing net device."); - - kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kaweth->tx_urb) - goto err_free_netdev; - kaweth->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kaweth->rx_urb) - goto err_only_tx; - kaweth->irq_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!kaweth->irq_urb) - goto err_tx_and_rx; - - kaweth->intbuffer = usb_buffer_alloc( kaweth->dev, - INTBUFFERSIZE, - GFP_KERNEL, - &kaweth->intbufferhandle); - if (!kaweth->intbuffer) - goto err_tx_and_rx_and_irq; - kaweth->rx_buf = usb_buffer_alloc( kaweth->dev, - KAWETH_BUF_SIZE, - GFP_KERNEL, - &kaweth->rxbufferhandle); - if (!kaweth->rx_buf) - goto err_all_but_rxbuf; - - memcpy(netdev->broadcast, &bcast_addr, sizeof(bcast_addr)); - memcpy(netdev->dev_addr, &kaweth->configuration.hw_addr, - sizeof(kaweth->configuration.hw_addr)); - - netdev->open = kaweth_open; - netdev->stop = kaweth_close; - - netdev->watchdog_timeo = KAWETH_TX_TIMEOUT; - netdev->tx_timeout = kaweth_tx_timeout; - - netdev->hard_start_xmit = kaweth_start_xmit; - netdev->set_multicast_list = kaweth_set_rx_mode; - netdev->get_stats = kaweth_netdev_stats; - netdev->mtu = le16_to_cpu(kaweth->configuration.segment_size); - SET_ETHTOOL_OPS(netdev, &ops); - - /* kaweth is zeroed as part of alloc_netdev */ - - INIT_WORK(&kaweth->lowmem_work, kaweth_resubmit_tl, (void *)kaweth); - - SET_MODULE_OWNER(netdev); - - usb_set_intfdata(intf, kaweth); - -#if 0 -// dma_supported() is deeply broken on almost all architectures - if (dma_supported (&intf->dev, 0xffffffffffffffffULL)) - kaweth->net->features |= NETIF_F_HIGHDMA; -#endif - - SET_NETDEV_DEV(netdev, &intf->dev); - if (register_netdev(netdev) != 0) { - kaweth_err("Error registering netdev."); - goto err_intfdata; - } - - kaweth_info("kaweth interface created at %s", kaweth->net->name); - - kaweth_dbg("Kaweth probe returning."); - - return 0; - -err_intfdata: - usb_set_intfdata(intf, NULL); - usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); -err_all_but_rxbuf: - usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); -err_tx_and_rx_and_irq: - usb_free_urb(kaweth->irq_urb); -err_tx_and_rx: - usb_free_urb(kaweth->rx_urb); -err_only_tx: - usb_free_urb(kaweth->tx_urb); -err_free_netdev: - free_netdev(netdev); - - return -EIO; -} - -/**************************************************************** - * kaweth_disconnect - ****************************************************************/ -static void kaweth_disconnect(struct usb_interface *intf) -{ - struct kaweth_device *kaweth = usb_get_intfdata(intf); - struct net_device *netdev; - - kaweth_info("Unregistering"); - - usb_set_intfdata(intf, NULL); - if (!kaweth) { - kaweth_warn("unregistering non-existant device"); - return; - } - netdev = kaweth->net; - kaweth->removed = 1; - usb_kill_urb(kaweth->irq_urb); - usb_kill_urb(kaweth->rx_urb); - usb_kill_urb(kaweth->tx_urb); - - kaweth_dbg("Unregistering net device"); - unregister_netdev(netdev); - - usb_free_urb(kaweth->rx_urb); - usb_free_urb(kaweth->tx_urb); - usb_free_urb(kaweth->irq_urb); - - usb_buffer_free(kaweth->dev, KAWETH_BUF_SIZE, (void *)kaweth->rx_buf, kaweth->rxbufferhandle); - usb_buffer_free(kaweth->dev, INTBUFFERSIZE, (void *)kaweth->intbuffer, kaweth->intbufferhandle); - - free_netdev(netdev); -} - - -// FIXME this completion stuff is a modified clone of -// an OLD version of some stuff in usb.c ... -struct usb_api_data { - wait_queue_head_t wqh; - int done; -}; - -/*-------------------------------------------------------------------* - * completion handler for compatibility wrappers (sync control/bulk) * - *-------------------------------------------------------------------*/ -static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs) -{ - struct usb_api_data *awd = (struct usb_api_data *)urb->context; - - awd->done=1; - wake_up(&awd->wqh); -} - -/*-------------------------------------------------------------------* - * COMPATIBILITY STUFF * - *-------------------------------------------------------------------*/ - -// Starts urb and waits for completion or timeout -static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) -{ - struct usb_api_data awd; - int status; - - init_waitqueue_head(&awd.wqh); - awd.done = 0; - - urb->context = &awd; - status = usb_submit_urb(urb, GFP_NOIO); - if (status) { - // something went wrong - usb_free_urb(urb); - return status; - } - - if (!wait_event_timeout(awd.wqh, awd.done, timeout)) { - // timeout - kaweth_warn("usb_control/bulk_msg: timeout"); - usb_kill_urb(urb); // remove urb safely - status = -ETIMEDOUT; - } - else { - status = urb->status; - } - - if (actual_length) { - *actual_length = urb->actual_length; - } - - usb_free_urb(urb); - return status; -} - -/*-------------------------------------------------------------------*/ -// returns status (negative) or length (positive) -static int kaweth_internal_control_msg(struct usb_device *usb_dev, - unsigned int pipe, - struct usb_ctrlrequest *cmd, void *data, - int len, int timeout) -{ - struct urb *urb; - int retv; - int length; - - urb = usb_alloc_urb(0, GFP_NOIO); - if (!urb) - return -ENOMEM; - - usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char*)cmd, data, - len, usb_api_blocking_completion, NULL); - - retv = usb_start_wait_urb(urb, timeout, &length); - if (retv < 0) { - return retv; - } - else { - return length; - } -} - - -/**************************************************************** - * kaweth_init - ****************************************************************/ -static int __init kaweth_init(void) -{ - kaweth_dbg("Driver loading"); - return usb_register(&kaweth_driver); -} - -/**************************************************************** - * kaweth_exit - ****************************************************************/ -static void __exit kaweth_exit(void) -{ - usb_deregister(&kaweth_driver); -} - -module_init(kaweth_init); -module_exit(kaweth_exit); - - - - - - - - - diff --git a/drivers/usb/net/kawethfw.h b/drivers/usb/net/kawethfw.h deleted file mode 100644 index cf85fcb0d1a..00000000000 --- a/drivers/usb/net/kawethfw.h +++ /dev/null @@ -1,557 +0,0 @@ -/******************************************/ -/* NOTE: B6/C3 is data header signature */ -/* 0xAA/0xBB is data length = total */ -/* bytes - 7, 0xCC is type, 0xDD is */ -/* interrupt to use. */ -/******************************************/ - -/**************************************************************** - * kaweth_trigger_code - ****************************************************************/ -static __u8 kaweth_trigger_code[] = -{ - 0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD, - 0xc8, 0x07, 0xa0, 0x00, 0xf0, 0x07, 0x5e, 0x00, - 0x06, 0x00, 0xf0, 0x07, 0x0a, 0x00, 0x08, 0x00, - 0xf0, 0x09, 0x00, 0x00, 0x02, 0x00, 0xe7, 0x07, - 0x36, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, - 0x04, 0x00, 0xe7, 0x07, 0x50, 0xc3, 0x10, 0xc0, - 0xf0, 0x09, 0x0e, 0xc0, 0x00, 0x00, 0xe7, 0x87, - 0x01, 0x00, 0x0e, 0xc0, 0x97, 0xcf, 0xd7, 0x09, - 0x00, 0xc0, 0x17, 0x02, 0xc8, 0x07, 0xa0, 0x00, - 0xe7, 0x17, 0x50, 0xc3, 0x10, 0xc0, 0x30, 0xd8, - 0x04, 0x00, 0x30, 0x5c, 0x08, 0x00, 0x04, 0x00, - 0xb0, 0xc0, 0x06, 0x00, 0xc8, 0x05, 0xe7, 0x05, - 0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0x49, 0xaf, - 0xc0, 0x07, 0x00, 0x00, 0x60, 0xaf, 0x4a, 0xaf, - 0x00, 0x0c, 0x0c, 0x00, 0x40, 0xd2, 0x00, 0x1c, - 0x0c, 0x00, 0x40, 0xd2, 0x30, 0x00, 0x08, 0x00, - 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, 0xf0, 0x07, - 0x86, 0x00, 0x06, 0x00, 0x67, 0xcf, 0x27, 0x0c, - 0x02, 0x00, 0x00, 0x00, 0x27, 0x0c, 0x00, 0x00, - 0x0e, 0xc0, 0x49, 0xaf, 0x64, 0xaf, 0xc0, 0x07, - 0x00, 0x00, 0x4b, 0xaf, 0x4a, 0xaf, 0x5a, 0xcf, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x94, 0x00, 0x05, 0x00, - 0x00, 0x00 -}; -/**************************************************************** - * kaweth_trigger_code_fix - ****************************************************************/ -static __u8 kaweth_trigger_code_fix[] = -{ - 0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD, - 0x02, 0x00, 0x06, 0x00, 0x18, 0x00, 0x3e, 0x00, - 0x80, 0x00, 0x98, 0x00, 0xaa, 0x00, - 0x00, 0x00 -}; - -/**************************************************************** - * kaweth_new_code - ****************************************************************/ -static __u8 kaweth_new_code[] = -{ - 0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD, - 0x9f, 0xcf, 0xde, 0x06, 0xe7, 0x57, 0x00, 0x00, - 0xc4, 0x06, 0x97, 0xc1, 0xe7, 0x67, 0xff, 0x1f, - 0x28, 0xc0, 0xe7, 0x87, 0x00, 0x04, 0x24, 0xc0, - 0xe7, 0x67, 0xff, 0xf9, 0x22, 0xc0, 0x97, 0xcf, - 0xd7, 0x09, 0x00, 0xc0, 0xe7, 0x09, 0xa2, 0xc0, - 0xbe, 0x06, 0x9f, 0xaf, 0x36, 0x00, 0xe7, 0x05, - 0x00, 0xc0, 0xa7, 0xcf, 0xbc, 0x06, 0x97, 0xcf, - 0xe7, 0x57, 0x00, 0x00, 0xb8, 0x06, 0xa7, 0xa1, - 0xb8, 0x06, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, - 0x14, 0x08, 0x0a, 0xc0, 0xe7, 0x57, 0x00, 0x00, - 0xa4, 0xc0, 0xa7, 0xc0, 0x7a, 0x06, 0x9f, 0xaf, - 0x92, 0x07, 0xe7, 0x07, 0x00, 0x00, 0x14, 0x08, - 0xe7, 0x57, 0xff, 0xff, 0xba, 0x06, 0x9f, 0xa0, - 0x38, 0x00, 0xe7, 0x59, 0xba, 0x06, 0xbe, 0x06, - 0x9f, 0xa0, 0x38, 0x00, 0xc8, 0x09, 0xca, 0x06, - 0x08, 0x62, 0x9f, 0xa1, 0x36, 0x08, 0xc0, 0x09, - 0x76, 0x06, 0x00, 0x60, 0xa7, 0xc0, 0x7a, 0x06, - 0x9f, 0xaf, 0xcc, 0x02, 0xe7, 0x57, 0x00, 0x00, - 0xb8, 0x06, 0xa7, 0xc1, 0x7a, 0x06, 0x9f, 0xaf, - 0x04, 0x00, 0xe7, 0x57, 0x00, 0x00, 0x8e, 0x06, - 0x0a, 0xc1, 0xe7, 0x09, 0x20, 0xc0, 0x10, 0x08, - 0xe7, 0xd0, 0x10, 0x08, 0xe7, 0x67, 0x40, 0x00, - 0x10, 0x08, 0x9f, 0xaf, 0x92, 0x0c, 0xc0, 0x09, - 0xd0, 0x06, 0x00, 0x60, 0x05, 0xc4, 0xc0, 0x59, - 0xbe, 0x06, 0x02, 0xc0, 0x9f, 0xaf, 0xec, 0x00, - 0x9f, 0xaf, 0x34, 0x02, 0xe7, 0x57, 0x00, 0x00, - 0xa6, 0x06, 0x9f, 0xa0, 0x7a, 0x02, 0xa7, 0xcf, - 0x7a, 0x06, 0x48, 0x02, 0xe7, 0x09, 0xbe, 0x06, - 0xd0, 0x06, 0xc8, 0x37, 0x04, 0x00, 0x9f, 0xaf, - 0x08, 0x03, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, - 0xce, 0x06, 0x97, 0xc0, 0xd7, 0x09, 0x00, 0xc0, - 0xc1, 0xdf, 0xc8, 0x09, 0xc6, 0x06, 0x08, 0x62, - 0x14, 0xc0, 0x27, 0x04, 0xc6, 0x06, 0x10, 0x94, - 0xf0, 0x07, 0x10, 0x08, 0x02, 0x00, 0xc1, 0x07, - 0x01, 0x00, 0x70, 0x00, 0x04, 0x00, 0xf0, 0x07, - 0x30, 0x01, 0x06, 0x00, 0x50, 0xaf, 0xe7, 0x07, - 0xff, 0xff, 0xd0, 0x06, 0xe7, 0x07, 0x00, 0x00, - 0xce, 0x06, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x48, 0x02, - 0xd0, 0x09, 0xc6, 0x06, 0x27, 0x02, 0xc6, 0x06, - 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0x48, 0x02, - 0xc8, 0x37, 0x04, 0x00, 0x00, 0x0c, 0x0c, 0x00, - 0x00, 0x60, 0x21, 0xc0, 0xc0, 0x37, 0x3e, 0x00, - 0x23, 0xc9, 0xc0, 0x57, 0xb4, 0x05, 0x1b, 0xc8, - 0xc0, 0x17, 0x3f, 0x00, 0xc0, 0x67, 0xc0, 0xff, - 0x30, 0x00, 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x02, 0xc0, 0x17, 0x4c, 0x00, - 0x30, 0x00, 0x06, 0x00, 0xf0, 0x07, 0xa0, 0x01, - 0x0a, 0x00, 0x48, 0x02, 0xc1, 0x07, 0x02, 0x00, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x51, 0xaf, - 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, 0x9f, 0xaf, - 0x08, 0x03, 0x9f, 0xaf, 0x7a, 0x02, 0x97, 0xcf, - 0x9f, 0xaf, 0x7a, 0x02, 0xc9, 0x37, 0x04, 0x00, - 0xc1, 0xdf, 0xc8, 0x09, 0xa2, 0x06, 0x50, 0x02, - 0x67, 0x02, 0xa2, 0x06, 0xd1, 0x07, 0x00, 0x00, - 0x27, 0xd8, 0xaa, 0x06, 0xc0, 0xdf, 0x9f, 0xaf, - 0xc4, 0x01, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, - 0xd2, 0x06, 0x97, 0xc1, 0xe7, 0x57, 0x01, 0x00, - 0xa8, 0x06, 0x97, 0xc0, 0xc8, 0x09, 0xa0, 0x06, - 0x08, 0x62, 0x97, 0xc0, 0x00, 0x02, 0xc0, 0x17, - 0x0e, 0x00, 0x27, 0x00, 0x34, 0x01, 0x27, 0x0c, - 0x0c, 0x00, 0x36, 0x01, 0xe7, 0x07, 0x50, 0xc3, - 0x12, 0xc0, 0xe7, 0x07, 0xcc, 0x0b, 0x02, 0x00, - 0xe7, 0x07, 0x01, 0x00, 0xa8, 0x06, 0xe7, 0x07, - 0x05, 0x00, 0x90, 0xc0, 0x97, 0xcf, 0xc8, 0x09, - 0xa4, 0x06, 0x08, 0x62, 0x02, 0xc0, 0x10, 0x64, - 0x07, 0xc1, 0xe7, 0x07, 0x00, 0x00, 0x9e, 0x06, - 0xe7, 0x07, 0x72, 0x04, 0x24, 0x00, 0x97, 0xcf, - 0x27, 0x04, 0xa4, 0x06, 0xc8, 0x17, 0x0e, 0x00, - 0x27, 0x02, 0x9e, 0x06, 0xe7, 0x07, 0x80, 0x04, - 0x24, 0x00, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, - 0xc1, 0xdf, 0xe7, 0x57, 0x00, 0x00, 0x90, 0x06, - 0x13, 0xc1, 0x9f, 0xaf, 0x06, 0x02, 0xe7, 0x57, - 0x00, 0x00, 0x9e, 0x06, 0x13, 0xc0, 0xe7, 0x09, - 0x9e, 0x06, 0x30, 0x01, 0xe7, 0x07, 0xf2, 0x05, - 0x32, 0x01, 0xe7, 0x07, 0x10, 0x00, 0x96, 0xc0, - 0xe7, 0x09, 0x9e, 0x06, 0x90, 0x06, 0x04, 0xcf, - 0xe7, 0x57, 0x00, 0x00, 0x9e, 0x06, 0x02, 0xc1, - 0x9f, 0xaf, 0x06, 0x02, 0xe7, 0x05, 0x00, 0xc0, - 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, - 0x08, 0x92, 0xe7, 0x57, 0x02, 0x00, 0xaa, 0x06, - 0x02, 0xc3, 0xc8, 0x09, 0xa4, 0x06, 0x27, 0x02, - 0xa6, 0x06, 0x08, 0x62, 0x03, 0xc1, 0xe7, 0x05, - 0x00, 0xc0, 0x97, 0xcf, 0x27, 0x04, 0xa4, 0x06, - 0xe7, 0x05, 0x00, 0xc0, 0xf0, 0x07, 0x40, 0x00, - 0x08, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, - 0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00, - 0x06, 0x00, 0xf0, 0x07, 0x46, 0x01, 0x0a, 0x00, - 0xc8, 0x17, 0x04, 0x00, 0xc1, 0x07, 0x02, 0x00, - 0x51, 0xaf, 0x97, 0xcf, 0xe7, 0x57, 0x00, 0x00, - 0x96, 0x06, 0x97, 0xc0, 0xc1, 0xdf, 0xc8, 0x09, - 0x96, 0x06, 0x27, 0x04, 0x96, 0x06, 0x27, 0x52, - 0x98, 0x06, 0x03, 0xc1, 0xe7, 0x07, 0x96, 0x06, - 0x98, 0x06, 0xc0, 0xdf, 0x17, 0x02, 0xc8, 0x17, - 0x0e, 0x00, 0x9f, 0xaf, 0xba, 0x03, 0xc8, 0x05, - 0x00, 0x60, 0x03, 0xc0, 0x9f, 0xaf, 0x24, 0x03, - 0x97, 0xcf, 0x9f, 0xaf, 0x08, 0x03, 0x97, 0xcf, - 0x57, 0x02, 0xc9, 0x07, 0xa4, 0x06, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0x08, 0x62, 0x1b, 0xc0, - 0x50, 0x04, 0x11, 0x02, 0xe7, 0x05, 0x00, 0xc0, - 0xc9, 0x05, 0x97, 0xcf, 0x97, 0x02, 0xca, 0x09, - 0xd6, 0x06, 0xf2, 0x17, 0x01, 0x00, 0x04, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x06, 0x00, 0xca, 0x17, - 0x2c, 0x00, 0xf8, 0x77, 0x01, 0x00, 0x0e, 0x00, - 0x06, 0xc0, 0xca, 0xd9, 0xf8, 0x57, 0xff, 0x00, - 0x0e, 0x00, 0x01, 0xc1, 0xca, 0xd9, 0x22, 0x1c, - 0x0c, 0x00, 0xe2, 0x27, 0x00, 0x00, 0xe2, 0x17, - 0x01, 0x00, 0xe2, 0x27, 0x00, 0x00, 0xca, 0x05, - 0x00, 0x0c, 0x0c, 0x00, 0xc0, 0x17, 0x41, 0x00, - 0xc0, 0x67, 0xc0, 0xff, 0x30, 0x00, 0x08, 0x00, - 0x00, 0x02, 0xc0, 0x17, 0x0c, 0x00, 0x30, 0x00, - 0x06, 0x00, 0xf0, 0x07, 0xda, 0x00, 0x0a, 0x00, - 0xf0, 0x07, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0c, - 0x08, 0x00, 0x40, 0xd1, 0x01, 0x00, 0xc0, 0x19, - 0xce, 0x06, 0xc0, 0x59, 0xc2, 0x06, 0x04, 0xc9, - 0x49, 0xaf, 0x9f, 0xaf, 0xec, 0x00, 0x4a, 0xaf, - 0x67, 0x10, 0xce, 0x06, 0xc8, 0x17, 0x04, 0x00, - 0xc1, 0x07, 0x01, 0x00, 0xd7, 0x09, 0x00, 0xc0, - 0xc1, 0xdf, 0x50, 0xaf, 0xe7, 0x05, 0x00, 0xc0, - 0x97, 0xcf, 0xc0, 0x07, 0x01, 0x00, 0xc1, 0x09, - 0xac, 0x06, 0xc1, 0x77, 0x01, 0x00, 0x97, 0xc1, - 0xd8, 0x77, 0x01, 0x00, 0x12, 0xc0, 0xc9, 0x07, - 0x6a, 0x06, 0x9f, 0xaf, 0x08, 0x04, 0x04, 0xc1, - 0xc1, 0x77, 0x08, 0x00, 0x13, 0xc0, 0x97, 0xcf, - 0xc1, 0x77, 0x02, 0x00, 0x97, 0xc1, 0xc1, 0x77, - 0x10, 0x00, 0x0c, 0xc0, 0x9f, 0xaf, 0x2c, 0x04, - 0x97, 0xcf, 0xc1, 0x77, 0x04, 0x00, 0x06, 0xc0, - 0xc9, 0x07, 0x70, 0x06, 0x9f, 0xaf, 0x08, 0x04, - 0x97, 0xc0, 0x00, 0xcf, 0x00, 0x90, 0x97, 0xcf, - 0x50, 0x54, 0x97, 0xc1, 0x70, 0x5c, 0x02, 0x00, - 0x02, 0x00, 0x97, 0xc1, 0x70, 0x5c, 0x04, 0x00, - 0x04, 0x00, 0x97, 0xcf, 0x80, 0x01, 0xc0, 0x00, - 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, - 0x06, 0x00, 0x00, 0x00, 0xcb, 0x09, 0xb2, 0x06, - 0xcc, 0x09, 0xb4, 0x06, 0x0b, 0x53, 0x11, 0xc0, - 0xc9, 0x02, 0xca, 0x07, 0x1c, 0x04, 0x9f, 0xaf, - 0x08, 0x04, 0x97, 0xc0, 0x0a, 0xc8, 0x82, 0x08, - 0x0a, 0xcf, 0x82, 0x08, 0x9f, 0xaf, 0x08, 0x04, - 0x97, 0xc0, 0x05, 0xc2, 0x89, 0x30, 0x82, 0x60, - 0x78, 0xc1, 0x00, 0x90, 0x97, 0xcf, 0x89, 0x10, - 0x09, 0x53, 0x79, 0xc2, 0x89, 0x30, 0x82, 0x08, - 0x7a, 0xcf, 0xc0, 0xdf, 0x97, 0xcf, 0xc0, 0xdf, - 0x97, 0xcf, 0xe7, 0x09, 0x96, 0xc0, 0x92, 0x06, - 0xe7, 0x09, 0x98, 0xc0, 0x94, 0x06, 0x0f, 0xcf, - 0xe7, 0x09, 0x96, 0xc0, 0x92, 0x06, 0xe7, 0x09, - 0x98, 0xc0, 0x94, 0x06, 0xe7, 0x09, 0x9e, 0x06, - 0x30, 0x01, 0xe7, 0x07, 0xf2, 0x05, 0x32, 0x01, - 0xe7, 0x07, 0x10, 0x00, 0x96, 0xc0, 0xd7, 0x09, - 0x00, 0xc0, 0x17, 0x02, 0xc8, 0x09, 0x90, 0x06, - 0xc8, 0x37, 0x0e, 0x00, 0xe7, 0x77, 0x2a, 0x00, - 0x92, 0x06, 0x30, 0xc0, 0x97, 0x02, 0xca, 0x09, - 0xd6, 0x06, 0xe7, 0x77, 0x20, 0x00, 0x92, 0x06, - 0x0e, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x10, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x12, 0x00, 0xe7, 0x77, - 0x0a, 0x00, 0x92, 0x06, 0xca, 0x05, 0x1e, 0xc0, - 0x97, 0x02, 0xca, 0x09, 0xd6, 0x06, 0xf2, 0x17, - 0x01, 0x00, 0x0c, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x0e, 0x00, 0xe7, 0x77, 0x02, 0x00, 0x92, 0x06, - 0x07, 0xc0, 0xf2, 0x17, 0x01, 0x00, 0x44, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x46, 0x00, 0x06, 0xcf, - 0xf2, 0x17, 0x01, 0x00, 0x60, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x62, 0x00, 0xca, 0x05, 0x9f, 0xaf, - 0x08, 0x03, 0x0f, 0xcf, 0x57, 0x02, 0x09, 0x02, - 0xf1, 0x09, 0x94, 0x06, 0x0c, 0x00, 0xf1, 0xda, - 0x0c, 0x00, 0xc8, 0x09, 0x98, 0x06, 0x50, 0x02, - 0x67, 0x02, 0x98, 0x06, 0xd1, 0x07, 0x00, 0x00, - 0xc9, 0x05, 0xe7, 0x09, 0x9e, 0x06, 0x90, 0x06, - 0xe7, 0x57, 0x00, 0x00, 0x90, 0x06, 0x02, 0xc0, - 0x9f, 0xaf, 0x06, 0x02, 0xc8, 0x05, 0xe7, 0x05, - 0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, 0xd7, 0x09, - 0x00, 0xc0, 0x17, 0x00, 0x17, 0x02, 0x97, 0x02, - 0xc0, 0x09, 0x92, 0xc0, 0xe7, 0x07, 0x04, 0x00, - 0x90, 0xc0, 0xca, 0x09, 0xd6, 0x06, 0xe7, 0x07, - 0x00, 0x00, 0xa8, 0x06, 0xe7, 0x07, 0x6a, 0x04, - 0x02, 0x00, 0xc0, 0x77, 0x02, 0x00, 0x08, 0xc0, - 0xf2, 0x17, 0x01, 0x00, 0x50, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x52, 0x00, 0x9f, 0xcf, 0x24, 0x06, - 0xc0, 0x77, 0x10, 0x00, 0x06, 0xc0, 0xf2, 0x17, - 0x01, 0x00, 0x58, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x5a, 0x00, 0xc0, 0x77, 0x80, 0x00, 0x06, 0xc0, - 0xf2, 0x17, 0x01, 0x00, 0x70, 0x00, 0xf2, 0x27, - 0x00, 0x00, 0x72, 0x00, 0xc0, 0x77, 0x08, 0x00, - 0x1d, 0xc1, 0xf2, 0x17, 0x01, 0x00, 0x08, 0x00, - 0xf2, 0x27, 0x00, 0x00, 0x0a, 0x00, 0xc0, 0x77, - 0x00, 0x02, 0x06, 0xc0, 0xf2, 0x17, 0x01, 0x00, - 0x64, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x66, 0x00, - 0xc0, 0x77, 0x40, 0x00, 0x06, 0xc0, 0xf2, 0x17, - 0x01, 0x00, 0x5c, 0x00, 0xf2, 0x27, 0x00, 0x00, - 0x5e, 0x00, 0xc0, 0x77, 0x01, 0x00, 0x01, 0xc0, - 0x1b, 0xcf, 0x1a, 0xcf, 0xf2, 0x17, 0x01, 0x00, - 0x00, 0x00, 0xf2, 0x27, 0x00, 0x00, 0x02, 0x00, - 0xc8, 0x09, 0x34, 0x01, 0xca, 0x17, 0x14, 0x00, - 0xd8, 0x77, 0x01, 0x00, 0x05, 0xc0, 0xca, 0xd9, - 0xd8, 0x57, 0xff, 0x00, 0x01, 0xc0, 0xca, 0xd9, - 0xe2, 0x19, 0x94, 0xc0, 0xe2, 0x27, 0x00, 0x00, - 0xe2, 0x17, 0x01, 0x00, 0xe2, 0x27, 0x00, 0x00, - 0x9f, 0xaf, 0x40, 0x06, 0x9f, 0xaf, 0xc4, 0x01, - 0xe7, 0x57, 0x00, 0x00, 0xd2, 0x06, 0x9f, 0xa1, - 0x0e, 0x0a, 0xca, 0x05, 0xc8, 0x05, 0xc0, 0x05, - 0xe7, 0x05, 0x00, 0xc0, 0xc0, 0xdf, 0x97, 0xcf, - 0xc8, 0x09, 0xa0, 0x06, 0x08, 0x62, 0x97, 0xc0, - 0x27, 0x04, 0xa0, 0x06, 0x27, 0x52, 0xa2, 0x06, - 0x03, 0xc1, 0xe7, 0x07, 0xa0, 0x06, 0xa2, 0x06, - 0x9f, 0xaf, 0x08, 0x03, 0xe7, 0x57, 0x00, 0x00, - 0xaa, 0x06, 0x02, 0xc0, 0x27, 0xda, 0xaa, 0x06, - 0x97, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0xfb, 0x13, 0xe7, 0x57, - 0x00, 0x80, 0xb2, 0x00, 0x06, 0xc2, 0xe7, 0x07, - 0xee, 0x0b, 0x12, 0x00, 0xe7, 0x07, 0x34, 0x0c, - 0xb2, 0x00, 0xe7, 0x07, 0xc6, 0x07, 0xf2, 0x02, - 0xc8, 0x09, 0xb4, 0x00, 0xf8, 0x07, 0x02, 0x00, - 0x0d, 0x00, 0xd7, 0x09, 0x0e, 0xc0, 0xe7, 0x07, - 0x00, 0x00, 0x0e, 0xc0, 0xc8, 0x09, 0xde, 0x00, - 0xc8, 0x17, 0x09, 0x00, 0xc9, 0x07, 0xda, 0x06, - 0xc0, 0x07, 0x04, 0x00, 0x68, 0x0a, 0x00, 0xda, - 0x7d, 0xc1, 0xe7, 0x09, 0xc0, 0x00, 0x7c, 0x06, - 0xe7, 0x09, 0xbe, 0x00, 0x78, 0x06, 0xe7, 0x09, - 0x10, 0x00, 0xbc, 0x06, 0xc8, 0x07, 0xd6, 0x07, - 0x9f, 0xaf, 0xae, 0x07, 0x9f, 0xaf, 0x00, 0x0a, - 0xc8, 0x09, 0xde, 0x00, 0x00, 0x0e, 0x0f, 0x00, - 0x41, 0x90, 0x9f, 0xde, 0x06, 0x00, 0x44, 0xaf, - 0x27, 0x00, 0xb2, 0x06, 0x27, 0x00, 0xb4, 0x06, - 0x27, 0x00, 0xb6, 0x06, 0xc0, 0x07, 0x74, 0x00, - 0x44, 0xaf, 0x27, 0x00, 0xd6, 0x06, 0x08, 0x00, - 0x00, 0x90, 0xc1, 0x07, 0x3a, 0x00, 0x20, 0x00, - 0x01, 0xda, 0x7d, 0xc1, 0x9f, 0xaf, 0xba, 0x09, - 0xc0, 0x07, 0x44, 0x00, 0x48, 0xaf, 0x27, 0x00, - 0x7a, 0x06, 0x9f, 0xaf, 0x96, 0x0a, 0xe7, 0x07, - 0x01, 0x00, 0xc0, 0x06, 0xe7, 0x05, 0x0e, 0xc0, - 0x97, 0xcf, 0x49, 0xaf, 0xe7, 0x87, 0x43, 0x00, - 0x0e, 0xc0, 0xe7, 0x07, 0xff, 0xff, 0xbe, 0x06, - 0x9f, 0xaf, 0xae, 0x0a, 0xc0, 0x07, 0x01, 0x00, - 0x60, 0xaf, 0x4a, 0xaf, 0x97, 0xcf, 0x00, 0x08, - 0x09, 0x08, 0x11, 0x08, 0x00, 0xda, 0x7c, 0xc1, - 0x97, 0xcf, 0x67, 0x04, 0xcc, 0x02, 0xc0, 0xdf, - 0x51, 0x94, 0xb1, 0xaf, 0x06, 0x00, 0xc1, 0xdf, - 0xc9, 0x09, 0xcc, 0x02, 0x49, 0x62, 0x75, 0xc1, - 0xc0, 0xdf, 0xa7, 0xcf, 0xd6, 0x02, 0x0e, 0x00, - 0x24, 0x00, 0x80, 0x04, 0x22, 0x00, 0x4e, 0x05, - 0xd0, 0x00, 0x0e, 0x0a, 0xaa, 0x00, 0x30, 0x08, - 0xbe, 0x00, 0x4a, 0x0a, 0x10, 0x00, 0x20, 0x00, - 0x04, 0x00, 0x6e, 0x04, 0x02, 0x00, 0x6a, 0x04, - 0x06, 0x00, 0x00, 0x00, 0x24, 0xc0, 0x04, 0x04, - 0x28, 0xc0, 0xfe, 0xfb, 0x1e, 0xc0, 0x00, 0x04, - 0x22, 0xc0, 0xff, 0xf4, 0xc0, 0x00, 0x90, 0x09, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x56, 0x08, - 0x60, 0x08, 0xd0, 0x08, 0xda, 0x08, 0x00, 0x09, - 0x04, 0x09, 0x08, 0x09, 0x32, 0x09, 0x42, 0x09, - 0x50, 0x09, 0x52, 0x09, 0x5a, 0x09, 0x5a, 0x09, - 0x27, 0x02, 0xca, 0x06, 0x97, 0xcf, 0xe7, 0x07, - 0x00, 0x00, 0xca, 0x06, 0x0a, 0x0e, 0x01, 0x00, - 0xca, 0x57, 0x0e, 0x00, 0x9f, 0xc3, 0x5a, 0x09, - 0xca, 0x37, 0x00, 0x00, 0x9f, 0xc2, 0x5a, 0x09, - 0x0a, 0xd2, 0xb2, 0xcf, 0x16, 0x08, 0xc8, 0x09, - 0xde, 0x00, 0x07, 0x06, 0x9f, 0xcf, 0x6c, 0x09, - 0x17, 0x02, 0xc8, 0x09, 0xde, 0x00, 0x00, 0x0e, - 0x0f, 0x00, 0x41, 0x90, 0x9f, 0xde, 0x06, 0x00, - 0xc8, 0x05, 0x30, 0x50, 0x06, 0x00, 0x9f, 0xc8, - 0x5a, 0x09, 0x27, 0x0c, 0x02, 0x00, 0xb0, 0x06, - 0xc0, 0x09, 0xb2, 0x06, 0x27, 0x00, 0xb4, 0x06, - 0xe7, 0x07, 0x00, 0x00, 0xae, 0x06, 0x27, 0x00, - 0x80, 0x06, 0x00, 0x1c, 0x06, 0x00, 0x27, 0x00, - 0xb6, 0x06, 0x41, 0x90, 0x67, 0x50, 0xb0, 0x06, - 0x0d, 0xc0, 0x67, 0x00, 0x7e, 0x06, 0x27, 0x0c, - 0x06, 0x00, 0x82, 0x06, 0xe7, 0x07, 0xbc, 0x08, - 0x84, 0x06, 0xc8, 0x07, 0x7e, 0x06, 0x41, 0x90, - 0x51, 0xaf, 0x97, 0xcf, 0x9f, 0xaf, 0x48, 0x0c, - 0xe7, 0x09, 0xb6, 0x06, 0xb4, 0x06, 0xe7, 0x09, - 0xb0, 0x06, 0xae, 0x06, 0x59, 0xaf, 0x97, 0xcf, - 0x27, 0x0c, 0x02, 0x00, 0xac, 0x06, 0x59, 0xaf, - 0x97, 0xcf, 0x09, 0x0c, 0x02, 0x00, 0x09, 0xda, - 0x49, 0xd2, 0xc9, 0x19, 0xd6, 0x06, 0xc8, 0x07, - 0x7e, 0x06, 0xe0, 0x07, 0x00, 0x00, 0x60, 0x02, - 0xe0, 0x07, 0x04, 0x00, 0xd0, 0x07, 0xcc, 0x08, - 0x48, 0xdb, 0x41, 0x90, 0x50, 0xaf, 0x97, 0xcf, - 0x59, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf, - 0xf0, 0x57, 0x06, 0x00, 0x06, 0x00, 0x25, 0xc1, - 0xe7, 0x07, 0x70, 0x06, 0x80, 0x06, 0x41, 0x90, - 0x67, 0x00, 0x7e, 0x06, 0x27, 0x0c, 0x06, 0x00, - 0x82, 0x06, 0xe7, 0x07, 0x8c, 0x09, 0x84, 0x06, - 0xc8, 0x07, 0x7e, 0x06, 0x41, 0x90, 0x51, 0xaf, - 0x97, 0xcf, 0x07, 0x0c, 0x06, 0x00, 0xc7, 0x57, - 0x06, 0x00, 0x0f, 0xc1, 0xc8, 0x07, 0x70, 0x06, - 0x15, 0xcf, 0x00, 0x0c, 0x02, 0x00, 0x00, 0xda, - 0x40, 0xd1, 0x27, 0x00, 0xc2, 0x06, 0x1e, 0xcf, - 0x1d, 0xcf, 0x27, 0x0c, 0x02, 0x00, 0xcc, 0x06, - 0x19, 0xcf, 0x27, 0x02, 0x20, 0x01, 0xe7, 0x07, - 0x08, 0x00, 0x22, 0x01, 0xe7, 0x07, 0x13, 0x00, - 0xb0, 0xc0, 0x97, 0xcf, 0x41, 0x90, 0x67, 0x00, - 0x7e, 0x06, 0xe7, 0x01, 0x82, 0x06, 0x27, 0x02, - 0x80, 0x06, 0xe7, 0x07, 0x8c, 0x09, 0x84, 0x06, - 0xc8, 0x07, 0x7e, 0x06, 0xc1, 0x07, 0x00, 0x80, - 0x50, 0xaf, 0x97, 0xcf, 0x59, 0xaf, 0x97, 0xcf, - 0x00, 0x60, 0x05, 0xc0, 0xe7, 0x07, 0x00, 0x00, - 0xc4, 0x06, 0xa7, 0xcf, 0x7c, 0x06, 0x9f, 0xaf, - 0x00, 0x0a, 0xe7, 0x07, 0x01, 0x00, 0xc4, 0x06, - 0x49, 0xaf, 0xd7, 0x09, 0x00, 0xc0, 0x07, 0xaf, - 0xe7, 0x05, 0x00, 0xc0, 0x4a, 0xaf, 0xa7, 0xcf, - 0x7c, 0x06, 0xc0, 0x07, 0xfe, 0x7f, 0x44, 0xaf, - 0x40, 0x00, 0xc0, 0x37, 0x00, 0x01, 0x41, 0x90, - 0xc0, 0x37, 0x08, 0x00, 0xdf, 0xde, 0x50, 0x06, - 0xc0, 0x57, 0x10, 0x00, 0x02, 0xc2, 0xc0, 0x07, - 0x10, 0x00, 0x27, 0x00, 0x9a, 0x06, 0x41, 0x90, - 0x9f, 0xde, 0x40, 0x06, 0x44, 0xaf, 0x27, 0x00, - 0x9c, 0x06, 0xc0, 0x09, 0x9a, 0x06, 0x41, 0x90, - 0x00, 0xd2, 0x00, 0xd8, 0x9f, 0xde, 0x08, 0x00, - 0x44, 0xaf, 0x27, 0x00, 0xc8, 0x06, 0x97, 0xcf, - 0xe7, 0x87, 0x00, 0x84, 0x28, 0xc0, 0xe7, 0x67, - 0xff, 0xfb, 0x24, 0xc0, 0x97, 0xcf, 0xe7, 0x87, - 0x01, 0x00, 0xd2, 0x06, 0xe7, 0x57, 0x00, 0x00, - 0xa8, 0x06, 0x97, 0xc1, 0x9f, 0xaf, 0x00, 0x0a, - 0xe7, 0x87, 0x00, 0x06, 0x22, 0xc0, 0xe7, 0x07, - 0x00, 0x00, 0x90, 0xc0, 0xe7, 0x67, 0xfe, 0xff, - 0x3e, 0xc0, 0xe7, 0x07, 0x26, 0x00, 0x0a, 0xc0, - 0xe7, 0x87, 0x01, 0x00, 0x3e, 0xc0, 0xe7, 0x07, - 0xff, 0xff, 0xbe, 0x06, 0x9f, 0xaf, 0x10, 0x0b, - 0x97, 0xcf, 0x17, 0x00, 0xa7, 0xaf, 0x78, 0x06, - 0xc0, 0x05, 0x27, 0x00, 0x76, 0x06, 0xe7, 0x87, - 0x01, 0x00, 0xd2, 0x06, 0x9f, 0xaf, 0x00, 0x0a, - 0xe7, 0x07, 0x0c, 0x00, 0x40, 0xc0, 0x9f, 0xaf, - 0x10, 0x0b, 0x00, 0x90, 0x27, 0x00, 0xa6, 0x06, - 0x27, 0x00, 0xaa, 0x06, 0xe7, 0x09, 0xb2, 0x06, - 0xb4, 0x06, 0x27, 0x00, 0xae, 0x06, 0x27, 0x00, - 0xac, 0x06, 0x9f, 0xaf, 0xae, 0x0a, 0xc0, 0x07, - 0x00, 0x00, 0x27, 0x00, 0xb2, 0x02, 0x27, 0x00, - 0xb4, 0x02, 0x27, 0x00, 0x8e, 0x06, 0xc0, 0x07, - 0x06, 0x00, 0xc8, 0x09, 0xde, 0x00, 0xc8, 0x17, - 0x03, 0x00, 0xc9, 0x07, 0x70, 0x06, 0x29, 0x0a, - 0x00, 0xda, 0x7d, 0xc1, 0x97, 0xcf, 0xd7, 0x09, - 0x00, 0xc0, 0xc1, 0xdf, 0x00, 0x90, 0x27, 0x00, - 0x96, 0x06, 0xe7, 0x07, 0x96, 0x06, 0x98, 0x06, - 0x27, 0x00, 0xa0, 0x06, 0xe7, 0x07, 0xa0, 0x06, - 0xa2, 0x06, 0x27, 0x00, 0xa6, 0x06, 0x27, 0x00, - 0x90, 0x06, 0x27, 0x00, 0x9e, 0x06, 0xc8, 0x09, - 0x9c, 0x06, 0xc1, 0x09, 0x9a, 0x06, 0xc9, 0x07, - 0xa4, 0x06, 0x11, 0x02, 0x09, 0x02, 0xc8, 0x17, - 0x40, 0x06, 0x01, 0xda, 0x7a, 0xc1, 0x51, 0x94, - 0xc8, 0x09, 0xc8, 0x06, 0xc9, 0x07, 0xc6, 0x06, - 0xc1, 0x09, 0x9a, 0x06, 0x11, 0x02, 0x09, 0x02, - 0xc8, 0x17, 0x08, 0x00, 0x01, 0xda, 0x7a, 0xc1, - 0x51, 0x94, 0xe7, 0x05, 0x00, 0xc0, 0x97, 0xcf, - 0xe7, 0x57, 0x00, 0x00, 0x76, 0x06, 0x97, 0xc0, - 0x9f, 0xaf, 0x04, 0x00, 0xe7, 0x09, 0xbe, 0x06, - 0xba, 0x06, 0xe7, 0x57, 0xff, 0xff, 0xba, 0x06, - 0x04, 0xc1, 0xe7, 0x07, 0x10, 0x0b, 0xb8, 0x06, - 0x97, 0xcf, 0xe7, 0x17, 0x32, 0x00, 0xba, 0x06, - 0xe7, 0x67, 0xff, 0x07, 0xba, 0x06, 0xe7, 0x07, - 0x46, 0x0b, 0xb8, 0x06, 0x97, 0xcf, 0xe7, 0x57, - 0x00, 0x00, 0xc0, 0x06, 0x23, 0xc0, 0xe7, 0x07, - 0x04, 0x00, 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x80, - 0x80, 0xc0, 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0, - 0xe7, 0x07, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0x07, - 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xc0, 0x07, - 0x00, 0x00, 0xe7, 0x07, 0x00, 0x00, 0x80, 0xc0, - 0xe7, 0x07, 0x00, 0x80, 0x80, 0xc0, 0xe7, 0x07, - 0x00, 0x80, 0x40, 0xc0, 0xc0, 0x07, 0x00, 0x00, - 0xe7, 0x07, 0x00, 0x00, 0x40, 0xc0, 0xe7, 0x07, - 0x00, 0x00, 0x80, 0xc0, 0xe7, 0x07, 0x04, 0x00, - 0x90, 0xc0, 0xe7, 0x07, 0x00, 0x02, 0x40, 0xc0, - 0xe7, 0x07, 0x0c, 0x02, 0x40, 0xc0, 0xe7, 0x07, - 0x00, 0x00, 0xc0, 0x06, 0xe7, 0x07, 0x00, 0x00, - 0xb8, 0x06, 0xe7, 0x07, 0x00, 0x00, 0xd2, 0x06, - 0xd7, 0x09, 0x00, 0xc0, 0xc1, 0xdf, 0x9f, 0xaf, - 0x34, 0x02, 0xe7, 0x05, 0x00, 0xc0, 0x9f, 0xaf, - 0xc4, 0x01, 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, - 0x17, 0x00, 0x17, 0x02, 0x97, 0x02, 0xe7, 0x57, - 0x00, 0x00, 0xa8, 0x06, 0x06, 0xc0, 0xc0, 0x09, - 0x92, 0xc0, 0xc0, 0x77, 0x09, 0x02, 0x9f, 0xc1, - 0x5c, 0x05, 0x9f, 0xcf, 0x32, 0x06, 0xd7, 0x09, - 0x0e, 0xc0, 0xe7, 0x07, 0x00, 0x00, 0x0e, 0xc0, - 0x9f, 0xaf, 0x02, 0x0c, 0xe7, 0x05, 0x0e, 0xc0, - 0x97, 0xcf, 0xd7, 0x09, 0x00, 0xc0, 0x17, 0x02, - 0xc8, 0x09, 0xb0, 0xc0, 0xe7, 0x67, 0xfe, 0x7f, - 0xb0, 0xc0, 0xc8, 0x77, 0x00, 0x20, 0x9f, 0xc1, - 0x64, 0xeb, 0xe7, 0x57, 0x00, 0x00, 0xc8, 0x02, - 0x9f, 0xc1, 0x80, 0xeb, 0xc8, 0x99, 0xca, 0x02, - 0xc8, 0x67, 0x04, 0x00, 0x9f, 0xc1, 0x96, 0xeb, - 0x9f, 0xcf, 0x4c, 0xeb, 0xe7, 0x07, 0x00, 0x00, - 0xa6, 0xc0, 0xe7, 0x09, 0xb0, 0xc0, 0xc8, 0x02, - 0xe7, 0x07, 0x03, 0x00, 0xb0, 0xc0, 0x97, 0xcf, - 0xc0, 0x09, 0xb0, 0x06, 0xc0, 0x37, 0x01, 0x00, - 0x97, 0xc9, 0xc9, 0x09, 0xb2, 0x06, 0x02, 0x00, - 0x41, 0x90, 0x48, 0x02, 0xc9, 0x17, 0x06, 0x00, - 0x9f, 0xaf, 0x08, 0x04, 0x9f, 0xa2, 0x72, 0x0c, - 0x02, 0xda, 0x77, 0xc1, 0x41, 0x60, 0x71, 0xc1, - 0x97, 0xcf, 0x17, 0x02, 0x57, 0x02, 0x43, 0x04, - 0x21, 0x04, 0xe0, 0x00, 0x43, 0x04, 0x21, 0x04, - 0xe0, 0x00, 0x43, 0x04, 0x21, 0x04, 0xe0, 0x00, - 0xc1, 0x07, 0x01, 0x00, 0xc9, 0x05, 0xc8, 0x05, - 0x97, 0xcf, 0xe7, 0x07, 0x01, 0x00, 0x8e, 0x06, - 0xc8, 0x07, 0x86, 0x06, 0xe7, 0x07, 0x00, 0x00, - 0x86, 0x06, 0xe7, 0x07, 0x10, 0x08, 0x88, 0x06, - 0xe7, 0x07, 0x04, 0x00, 0x8a, 0x06, 0xe7, 0x07, - 0xbc, 0x0c, 0x8c, 0x06, 0xc1, 0x07, 0x03, 0x80, - 0x50, 0xaf, 0x97, 0xcf, 0xe7, 0x07, 0x00, 0x00, - 0x8e, 0x06, 0x97, 0xcf, - 0x00, 0x00 -}; - -/**************************************************************** - * kaweth_new_code_fix - ****************************************************************/ -static __u8 kaweth_new_code_fix[] = -{ - 0xB6, 0xC3, 0xAA, 0xBB, 0xCC, 0xDD, - 0x02, 0x00, 0x08, 0x00, 0x28, 0x00, 0x2c, 0x00, - 0x34, 0x00, 0x3c, 0x00, 0x40, 0x00, 0x48, 0x00, - 0x54, 0x00, 0x58, 0x00, 0x5e, 0x00, 0x64, 0x00, - 0x68, 0x00, 0x6e, 0x00, 0x6c, 0x00, 0x72, 0x00, - 0x76, 0x00, 0x7c, 0x00, 0x80, 0x00, 0x86, 0x00, - 0x8a, 0x00, 0x90, 0x00, 0x94, 0x00, 0x98, 0x00, - 0x9e, 0x00, 0xa6, 0x00, 0xaa, 0x00, 0xb0, 0x00, - 0xb4, 0x00, 0xb8, 0x00, 0xc0, 0x00, 0xc6, 0x00, - 0xca, 0x00, 0xd0, 0x00, 0xd4, 0x00, 0xd8, 0x00, - 0xe0, 0x00, 0xde, 0x00, 0xe8, 0x00, 0xf0, 0x00, - 0xfc, 0x00, 0x04, 0x01, 0x0a, 0x01, 0x18, 0x01, - 0x22, 0x01, 0x28, 0x01, 0x3a, 0x01, 0x3e, 0x01, - 0x7e, 0x01, 0x98, 0x01, 0x9c, 0x01, 0xa2, 0x01, - 0xac, 0x01, 0xb2, 0x01, 0xba, 0x01, 0xc0, 0x01, - 0xc8, 0x01, 0xd0, 0x01, 0xd6, 0x01, 0xf4, 0x01, - 0xfc, 0x01, 0x08, 0x02, 0x16, 0x02, 0x1a, 0x02, - 0x22, 0x02, 0x2a, 0x02, 0x2e, 0x02, 0x3e, 0x02, - 0x44, 0x02, 0x4a, 0x02, 0x50, 0x02, 0x64, 0x02, - 0x62, 0x02, 0x6c, 0x02, 0x72, 0x02, 0x86, 0x02, - 0x8c, 0x02, 0x90, 0x02, 0x9e, 0x02, 0xbc, 0x02, - 0xd0, 0x02, 0xd8, 0x02, 0xdc, 0x02, 0xe0, 0x02, - 0xe8, 0x02, 0xe6, 0x02, 0xf4, 0x02, 0xfe, 0x02, - 0x04, 0x03, 0x0c, 0x03, 0x28, 0x03, 0x7c, 0x03, - 0x90, 0x03, 0x94, 0x03, 0x9c, 0x03, 0xa2, 0x03, - 0xc0, 0x03, 0xd0, 0x03, 0xd4, 0x03, 0xee, 0x03, - 0xfa, 0x03, 0xfe, 0x03, 0x2e, 0x04, 0x32, 0x04, - 0x3c, 0x04, 0x40, 0x04, 0x4e, 0x04, 0x76, 0x04, - 0x7c, 0x04, 0x84, 0x04, 0x8a, 0x04, 0x8e, 0x04, - 0xa6, 0x04, 0xb0, 0x04, 0xb8, 0x04, 0xbe, 0x04, - 0xd2, 0x04, 0xdc, 0x04, 0xee, 0x04, 0x10, 0x05, - 0x1a, 0x05, 0x24, 0x05, 0x2a, 0x05, 0x36, 0x05, - 0x34, 0x05, 0x3c, 0x05, 0x42, 0x05, 0x64, 0x05, - 0x6a, 0x05, 0x6e, 0x05, 0x86, 0x05, 0x22, 0x06, - 0x26, 0x06, 0x2c, 0x06, 0x30, 0x06, 0x42, 0x06, - 0x4a, 0x06, 0x4e, 0x06, 0x56, 0x06, 0x54, 0x06, - 0x5a, 0x06, 0x60, 0x06, 0x66, 0x06, 0xe8, 0x06, - 0xee, 0x06, 0xf4, 0x06, 0x16, 0x07, 0x26, 0x07, - 0x2c, 0x07, 0x32, 0x07, 0x36, 0x07, 0x3a, 0x07, - 0x3e, 0x07, 0x52, 0x07, 0x56, 0x07, 0x5a, 0x07, - 0x64, 0x07, 0x76, 0x07, 0x7a, 0x07, 0x80, 0x07, - 0x84, 0x07, 0x8a, 0x07, 0x9e, 0x07, 0xa2, 0x07, - 0xda, 0x07, 0xde, 0x07, 0xe2, 0x07, 0xe6, 0x07, - 0xea, 0x07, 0xee, 0x07, 0xf2, 0x07, 0xf6, 0x07, - 0x0e, 0x08, 0x16, 0x08, 0x18, 0x08, 0x1a, 0x08, - 0x1c, 0x08, 0x1e, 0x08, 0x20, 0x08, 0x22, 0x08, - 0x24, 0x08, 0x26, 0x08, 0x28, 0x08, 0x2a, 0x08, - 0x2c, 0x08, 0x2e, 0x08, 0x32, 0x08, 0x3a, 0x08, - 0x46, 0x08, 0x4e, 0x08, 0x54, 0x08, 0x5e, 0x08, - 0x78, 0x08, 0x7e, 0x08, 0x82, 0x08, 0x86, 0x08, - 0x8c, 0x08, 0x90, 0x08, 0x98, 0x08, 0x9e, 0x08, - 0xa4, 0x08, 0xaa, 0x08, 0xb0, 0x08, 0xae, 0x08, - 0xb4, 0x08, 0xbe, 0x08, 0xc4, 0x08, 0xc2, 0x08, - 0xca, 0x08, 0xc8, 0x08, 0xd4, 0x08, 0xe4, 0x08, - 0xe8, 0x08, 0xf6, 0x08, 0x14, 0x09, 0x12, 0x09, - 0x1a, 0x09, 0x20, 0x09, 0x26, 0x09, 0x24, 0x09, - 0x2a, 0x09, 0x3e, 0x09, 0x4c, 0x09, 0x56, 0x09, - 0x70, 0x09, 0x74, 0x09, 0x78, 0x09, 0x7e, 0x09, - 0x7c, 0x09, 0x82, 0x09, 0x98, 0x09, 0x9c, 0x09, - 0xa0, 0x09, 0xa6, 0x09, 0xb8, 0x09, 0xdc, 0x09, - 0xe8, 0x09, 0xec, 0x09, 0xfc, 0x09, 0x12, 0x0a, - 0x18, 0x0a, 0x1e, 0x0a, 0x42, 0x0a, 0x46, 0x0a, - 0x4e, 0x0a, 0x54, 0x0a, 0x5a, 0x0a, 0x5e, 0x0a, - 0x68, 0x0a, 0x6e, 0x0a, 0x72, 0x0a, 0x78, 0x0a, - 0x76, 0x0a, 0x7c, 0x0a, 0x80, 0x0a, 0x84, 0x0a, - 0x94, 0x0a, 0xa4, 0x0a, 0xb8, 0x0a, 0xbe, 0x0a, - 0xbc, 0x0a, 0xc2, 0x0a, 0xc8, 0x0a, 0xc6, 0x0a, - 0xcc, 0x0a, 0xd0, 0x0a, 0xd4, 0x0a, 0xd8, 0x0a, - 0xdc, 0x0a, 0xe0, 0x0a, 0xf2, 0x0a, 0xf6, 0x0a, - 0xfa, 0x0a, 0x14, 0x0b, 0x1a, 0x0b, 0x20, 0x0b, - 0x1e, 0x0b, 0x26, 0x0b, 0x2e, 0x0b, 0x2c, 0x0b, - 0x36, 0x0b, 0x3c, 0x0b, 0x42, 0x0b, 0x40, 0x0b, - 0x4a, 0x0b, 0xaa, 0x0b, 0xb0, 0x0b, 0xb6, 0x0b, - 0xc0, 0x0b, 0xc8, 0x0b, 0xda, 0x0b, 0xe8, 0x0b, - 0xec, 0x0b, 0xfa, 0x0b, 0x4a, 0x0c, 0x54, 0x0c, - 0x62, 0x0c, 0x66, 0x0c, 0x96, 0x0c, 0x9a, 0x0c, - 0xa0, 0x0c, 0xa6, 0x0c, 0xa4, 0x0c, 0xac, 0x0c, - 0xb2, 0x0c, 0xb0, 0x0c, 0xc0, 0x0c, - 0x00, 0x00 -}; - - -static const int len_kaweth_trigger_code = sizeof(kaweth_trigger_code); -static const int len_kaweth_trigger_code_fix = sizeof(kaweth_trigger_code_fix); -static const int len_kaweth_new_code = sizeof(kaweth_new_code); -static const int len_kaweth_new_code_fix = sizeof(kaweth_new_code_fix); diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c deleted file mode 100644 index cee55f8cf64..00000000000 --- a/drivers/usb/net/net1080.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Net1080 based USB host-to-host cables - * Copyright (C) 2000-2005 by David Brownell - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include <linux/config.h> -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#endif -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/workqueue.h> -#include <linux/mii.h> -#include <linux/usb.h> - -#include <asm/unaligned.h> - -#include "usbnet.h" - - -/* - * Netchip 1080 driver ... http://www.netchip.com - * (Sept 2004: End-of-life announcement has been sent.) - * Used in (some) LapLink cables - */ - -#define frame_errors data[1] - -/* - * NetChip framing of ethernet packets, supporting additional error - * checks for links that may drop bulk packets from inside messages. - * Odd USB length == always short read for last usb packet. - * - nc_header - * - Ethernet header (14 bytes) - * - payload - * - (optional padding byte, if needed so length becomes odd) - * - nc_trailer - * - * This framing is to be avoided for non-NetChip devices. - */ - -struct nc_header { // packed: - __le16 hdr_len; // sizeof nc_header (LE, all) - __le16 packet_len; // payload size (including ethhdr) - __le16 packet_id; // detects dropped packets -#define MIN_HEADER 6 - - // all else is optional, and must start with: - // __le16 vendorId; // from usb-if - // __le16 productId; -} __attribute__((__packed__)); - -#define PAD_BYTE ((unsigned char)0xAC) - -struct nc_trailer { - __le16 packet_id; -} __attribute__((__packed__)); - -// packets may use FLAG_FRAMING_NC and optional pad -#define FRAMED_SIZE(mtu) (sizeof (struct nc_header) \ - + sizeof (struct ethhdr) \ - + (mtu) \ - + 1 \ - + sizeof (struct nc_trailer)) - -#define MIN_FRAMED FRAMED_SIZE(0) - -/* packets _could_ be up to 64KB... */ -#define NC_MAX_PACKET 32767 - - -/* - * Zero means no timeout; else, how long a 64 byte bulk packet may be queued - * before the hardware drops it. If that's done, the driver will need to - * frame network packets to guard against the dropped USB packets. The win32 - * driver sets this for both sides of the link. - */ -#define NC_READ_TTL_MS ((u8)255) // ms - -/* - * We ignore most registers and EEPROM contents. - */ -#define REG_USBCTL ((u8)0x04) -#define REG_TTL ((u8)0x10) -#define REG_STATUS ((u8)0x11) - -/* - * Vendor specific requests to read/write data - */ -#define REQUEST_REGISTER ((u8)0x10) -#define REQUEST_EEPROM ((u8)0x11) - -static int -nc_vendor_read(struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr) -{ - int status = usb_control_msg(dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0, regnum, - retval_ptr, sizeof *retval_ptr, - USB_CTRL_GET_TIMEOUT); - if (status > 0) - status = 0; - if (!status) - le16_to_cpus(retval_ptr); - return status; -} - -static inline int -nc_register_read(struct usbnet *dev, u8 regnum, u16 *retval_ptr) -{ - return nc_vendor_read(dev, REQUEST_REGISTER, regnum, retval_ptr); -} - -// no retval ... can become async, usable in_interrupt() -static void -nc_vendor_write(struct usbnet *dev, u8 req, u8 regnum, u16 value) -{ - usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - req, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - value, regnum, - NULL, 0, // data is in setup packet - USB_CTRL_SET_TIMEOUT); -} - -static inline void -nc_register_write(struct usbnet *dev, u8 regnum, u16 value) -{ - nc_vendor_write(dev, REQUEST_REGISTER, regnum, value); -} - - -#if 0 -static void nc_dump_registers(struct usbnet *dev) -{ - u8 reg; - u16 *vp = kmalloc(sizeof (u16)); - - if (!vp) { - dbg("no memory?"); - return; - } - - dbg("%s registers:", dev->net->name); - for (reg = 0; reg < 0x20; reg++) { - int retval; - - // reading some registers is trouble - if (reg >= 0x08 && reg <= 0xf) - continue; - if (reg >= 0x12 && reg <= 0x1e) - continue; - - retval = nc_register_read(dev, reg, vp); - if (retval < 0) - dbg("%s reg [0x%x] ==> error %d", - dev->net->name, reg, retval); - else - dbg("%s reg [0x%x] = 0x%x", - dev->net->name, reg, *vp); - } - kfree(vp); -} -#endif - - -/*-------------------------------------------------------------------------*/ - -/* - * Control register - */ - -#define USBCTL_WRITABLE_MASK 0x1f0f -// bits 15-13 reserved, r/o -#define USBCTL_ENABLE_LANG (1 << 12) -#define USBCTL_ENABLE_MFGR (1 << 11) -#define USBCTL_ENABLE_PROD (1 << 10) -#define USBCTL_ENABLE_SERIAL (1 << 9) -#define USBCTL_ENABLE_DEFAULTS (1 << 8) -// bits 7-4 reserved, r/o -#define USBCTL_FLUSH_OTHER (1 << 3) -#define USBCTL_FLUSH_THIS (1 << 2) -#define USBCTL_DISCONN_OTHER (1 << 1) -#define USBCTL_DISCONN_THIS (1 << 0) - -static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl) -{ - if (!netif_msg_link(dev)) - return; - devdbg(dev, "net1080 %s-%s usbctl 0x%x:%s%s%s%s%s;" - " this%s%s;" - " other%s%s; r/o 0x%x", - dev->udev->bus->bus_name, dev->udev->devpath, - usbctl, - (usbctl & USBCTL_ENABLE_LANG) ? " lang" : "", - (usbctl & USBCTL_ENABLE_MFGR) ? " mfgr" : "", - (usbctl & USBCTL_ENABLE_PROD) ? " prod" : "", - (usbctl & USBCTL_ENABLE_SERIAL) ? " serial" : "", - (usbctl & USBCTL_ENABLE_DEFAULTS) ? " defaults" : "", - - (usbctl & USBCTL_FLUSH_OTHER) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_OTHER) ? " DIS" : "", - (usbctl & USBCTL_FLUSH_THIS) ? " FLUSH" : "", - (usbctl & USBCTL_DISCONN_THIS) ? " DIS" : "", - usbctl & ~USBCTL_WRITABLE_MASK - ); -} - -/*-------------------------------------------------------------------------*/ - -/* - * Status register - */ - -#define STATUS_PORT_A (1 << 15) - -#define STATUS_CONN_OTHER (1 << 14) -#define STATUS_SUSPEND_OTHER (1 << 13) -#define STATUS_MAILBOX_OTHER (1 << 12) -#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03) - -#define STATUS_CONN_THIS (1 << 6) -#define STATUS_SUSPEND_THIS (1 << 5) -#define STATUS_MAILBOX_THIS (1 << 4) -#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03) - -#define STATUS_UNSPEC_MASK 0x0c8c -#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK)) - - -static inline void nc_dump_status(struct usbnet *dev, u16 status) -{ - if (!netif_msg_link(dev)) - return; - devdbg(dev, "net1080 %s-%s status 0x%x:" - " this (%c) PKT=%d%s%s%s;" - " other PKT=%d%s%s%s; unspec 0x%x", - dev->udev->bus->bus_name, dev->udev->devpath, - status, - - // XXX the packet counts don't seem right - // (1 at reset, not 0); maybe UNSPEC too - - (status & STATUS_PORT_A) ? 'A' : 'B', - STATUS_PACKETS_THIS(status), - (status & STATUS_CONN_THIS) ? " CON" : "", - (status & STATUS_SUSPEND_THIS) ? " SUS" : "", - (status & STATUS_MAILBOX_THIS) ? " MBOX" : "", - - STATUS_PACKETS_OTHER(status), - (status & STATUS_CONN_OTHER) ? " CON" : "", - (status & STATUS_SUSPEND_OTHER) ? " SUS" : "", - (status & STATUS_MAILBOX_OTHER) ? " MBOX" : "", - - status & STATUS_UNSPEC_MASK - ); -} - -/*-------------------------------------------------------------------------*/ - -/* - * TTL register - */ - -#define TTL_THIS(ttl) (0x00ff & ttl) -#define TTL_OTHER(ttl) (0x00ff & (ttl >> 8)) -#define MK_TTL(this,other) ((u16)(((other)<<8)|(0x00ff&(this)))) - -static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl) -{ - if (netif_msg_link(dev)) - devdbg(dev, "net1080 %s-%s ttl 0x%x this = %d, other = %d", - dev->udev->bus->bus_name, dev->udev->devpath, - ttl, TTL_THIS(ttl), TTL_OTHER(ttl)); -} - -/*-------------------------------------------------------------------------*/ - -static int net1080_reset(struct usbnet *dev) -{ - u16 usbctl, status, ttl; - u16 *vp = kmalloc(sizeof (u16), GFP_KERNEL); - int retval; - - if (!vp) - return -ENOMEM; - - // nc_dump_registers(dev); - - if ((retval = nc_register_read(dev, REG_STATUS, vp)) < 0) { - dbg("can't read %s-%s status: %d", - dev->udev->bus->bus_name, dev->udev->devpath, retval); - goto done; - } - status = *vp; - nc_dump_status(dev, status); - - if ((retval = nc_register_read(dev, REG_USBCTL, vp)) < 0) { - dbg("can't read USBCTL, %d", retval); - goto done; - } - usbctl = *vp; - nc_dump_usbctl(dev, usbctl); - - nc_register_write(dev, REG_USBCTL, - USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER); - - if ((retval = nc_register_read(dev, REG_TTL, vp)) < 0) { - dbg("can't read TTL, %d", retval); - goto done; - } - ttl = *vp; - // nc_dump_ttl(dev, ttl); - - nc_register_write(dev, REG_TTL, - MK_TTL(NC_READ_TTL_MS, TTL_OTHER(ttl)) ); - dbg("%s: assigned TTL, %d ms", dev->net->name, NC_READ_TTL_MS); - - if (netif_msg_link(dev)) - devinfo(dev, "port %c, peer %sconnected", - (status & STATUS_PORT_A) ? 'A' : 'B', - (status & STATUS_CONN_OTHER) ? "" : "dis" - ); - retval = 0; - -done: - kfree(vp); - return retval; -} - -static int net1080_check_connect(struct usbnet *dev) -{ - int retval; - u16 status; - u16 *vp = kmalloc(sizeof (u16), GFP_KERNEL); - - if (!vp) - return -ENOMEM; - retval = nc_register_read(dev, REG_STATUS, vp); - status = *vp; - kfree(vp); - if (retval != 0) { - dbg("%s net1080_check_conn read - %d", dev->net->name, retval); - return retval; - } - if ((status & STATUS_CONN_OTHER) != STATUS_CONN_OTHER) - return -ENOLINK; - return 0; -} - -static void nc_flush_complete(struct urb *urb, struct pt_regs *regs) -{ - kfree(urb->context); - usb_free_urb(urb); -} - -static void nc_ensure_sync(struct usbnet *dev) -{ - dev->frame_errors++; - if (dev->frame_errors > 5) { - struct urb *urb; - struct usb_ctrlrequest *req; - int status; - - /* Send a flush */ - urb = usb_alloc_urb(0, SLAB_ATOMIC); - if (!urb) - return; - - req = kmalloc(sizeof *req, GFP_ATOMIC); - if (!req) { - usb_free_urb(urb); - return; - } - - req->bRequestType = USB_DIR_OUT - | USB_TYPE_VENDOR - | USB_RECIP_DEVICE; - req->bRequest = REQUEST_REGISTER; - req->wValue = cpu_to_le16(USBCTL_FLUSH_THIS - | USBCTL_FLUSH_OTHER); - req->wIndex = cpu_to_le16(REG_USBCTL); - req->wLength = cpu_to_le16(0); - - /* queue an async control request, we don't need - * to do anything when it finishes except clean up. - */ - usb_fill_control_urb(urb, dev->udev, - usb_sndctrlpipe(dev->udev, 0), - (unsigned char *) req, - NULL, 0, - nc_flush_complete, req); - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) { - kfree(req); - usb_free_urb(urb); - return; - } - - if (netif_msg_rx_err(dev)) - devdbg(dev, "flush net1080; too many framing errors"); - dev->frame_errors = 0; - } -} - -static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb) -{ - struct nc_header *header; - struct nc_trailer *trailer; - u16 hdr_len, packet_len; - - if (!(skb->len & 0x01)) { -#ifdef DEBUG - struct net_device *net = dev->net; - dbg("rx framesize %d range %d..%d mtu %d", skb->len, - net->hard_header_len, dev->hard_mtu, net->mtu); -#endif - dev->stats.rx_frame_errors++; - nc_ensure_sync(dev); - return 0; - } - - header = (struct nc_header *) skb->data; - hdr_len = le16_to_cpup(&header->hdr_len); - packet_len = le16_to_cpup(&header->packet_len); - if (FRAMED_SIZE(packet_len) > NC_MAX_PACKET) { - dev->stats.rx_frame_errors++; - dbg("packet too big, %d", packet_len); - nc_ensure_sync(dev); - return 0; - } else if (hdr_len < MIN_HEADER) { - dev->stats.rx_frame_errors++; - dbg("header too short, %d", hdr_len); - nc_ensure_sync(dev); - return 0; - } else if (hdr_len > MIN_HEADER) { - // out of band data for us? - dbg("header OOB, %d bytes", hdr_len - MIN_HEADER); - nc_ensure_sync(dev); - // switch (vendor/product ids) { ... } - } - skb_pull(skb, hdr_len); - - trailer = (struct nc_trailer *) - (skb->data + skb->len - sizeof *trailer); - skb_trim(skb, skb->len - sizeof *trailer); - - if ((packet_len & 0x01) == 0) { - if (skb->data [packet_len] != PAD_BYTE) { - dev->stats.rx_frame_errors++; - dbg("bad pad"); - return 0; - } - skb_trim(skb, skb->len - 1); - } - if (skb->len != packet_len) { - dev->stats.rx_frame_errors++; - dbg("bad packet len %d (expected %d)", - skb->len, packet_len); - nc_ensure_sync(dev); - return 0; - } - if (header->packet_id != get_unaligned(&trailer->packet_id)) { - dev->stats.rx_fifo_errors++; - dbg("(2+ dropped) rx packet_id mismatch 0x%x 0x%x", - le16_to_cpu(header->packet_id), - le16_to_cpu(trailer->packet_id)); - return 0; - } -#if 0 - devdbg(dev, "frame <rx h %d p %d id %d", header->hdr_len, - header->packet_len, header->packet_id); -#endif - dev->frame_errors = 0; - return 1; -} - -static struct sk_buff * -net1080_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) -{ - int padlen; - struct sk_buff *skb2; - struct nc_header *header = NULL; - struct nc_trailer *trailer = NULL; - int len = skb->len; - - padlen = ((len + sizeof (struct nc_header) - + sizeof (struct nc_trailer)) & 0x01) ? 0 : 1; - if (!skb_cloned(skb)) { - int headroom = skb_headroom(skb); - int tailroom = skb_tailroom(skb); - - if ((padlen + sizeof (struct nc_trailer)) <= tailroom - && sizeof (struct nc_header) <= headroom) - /* There's enough head and tail room */ - goto encapsulate; - - if ((sizeof (struct nc_header) + padlen - + sizeof (struct nc_trailer)) < - (headroom + tailroom)) { - /* There's enough total room, so just readjust */ - skb->data = memmove(skb->head - + sizeof (struct nc_header), - skb->data, skb->len); - skb->tail = skb->data + len; - goto encapsulate; - } - } - - /* Create a new skb to use with the correct size */ - skb2 = skb_copy_expand(skb, - sizeof (struct nc_header), - sizeof (struct nc_trailer) + padlen, - flags); - dev_kfree_skb_any(skb); - if (!skb2) - return skb2; - skb = skb2; - -encapsulate: - /* header first */ - header = (struct nc_header *) skb_push(skb, sizeof *header); - header->hdr_len = cpu_to_le16(sizeof (*header)); - header->packet_len = cpu_to_le16(len); - header->packet_id = cpu_to_le16((u16)dev->xid++); - - /* maybe pad; then trailer */ - if (!((skb->len + sizeof *trailer) & 0x01)) - *skb_put(skb, 1) = PAD_BYTE; - trailer = (struct nc_trailer *) skb_put(skb, sizeof *trailer); - put_unaligned(header->packet_id, &trailer->packet_id); -#if 0 - devdbg(dev, "frame >tx h %d p %d id %d", - header->hdr_len, header->packet_len, - header->packet_id); -#endif - return skb; -} - -static int net1080_bind(struct usbnet *dev, struct usb_interface *intf) -{ - unsigned extra = sizeof (struct nc_header) - + 1 - + sizeof (struct nc_trailer); - - dev->net->hard_header_len += extra; - dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu; - dev->hard_mtu = NC_MAX_PACKET; - return usbnet_get_endpoints (dev, intf); -} - -static const struct driver_info net1080_info = { - .description = "NetChip TurboCONNECT", - .flags = FLAG_FRAMING_NC, - .bind = net1080_bind, - .reset = net1080_reset, - .check_connect = net1080_check_connect, - .rx_fixup = net1080_rx_fixup, - .tx_fixup = net1080_tx_fixup, -}; - -static const struct usb_device_id products [] = { -{ - USB_DEVICE(0x0525, 0x1080), // NetChip ref design - .driver_info = (unsigned long) &net1080_info, -}, { - USB_DEVICE(0x06D0, 0x0622), // Laplink Gold - .driver_info = (unsigned long) &net1080_info, -}, - { }, // END -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver net1080_driver = { - .owner = THIS_MODULE, - .name = "net1080", - .id_table = products, - .probe = usbnet_probe, - .disconnect = usbnet_disconnect, - .suspend = usbnet_suspend, - .resume = usbnet_resume, -}; - -static int __init net1080_init(void) -{ - return usb_register(&net1080_driver); -} -module_init(net1080_init); - -static void __exit net1080_exit(void) -{ - usb_deregister(&net1080_driver); -} -module_exit(net1080_exit); - -MODULE_AUTHOR("David Brownell"); -MODULE_DESCRIPTION("NetChip 1080 based USB Host-to-Host Links"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c deleted file mode 100644 index 537eb181d98..00000000000 --- a/drivers/usb/net/pegasus.c +++ /dev/null @@ -1,1435 +0,0 @@ -/* - * Copyright (c) 1999-2005 Petko Manolov (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 version 2 as - * published by the Free Software Foundation. - * - * ChangeLog: - * .... Most of the time spent on reading sources & docs. - * v0.2.x First official release for the Linux kernel. - * v0.3.0 Beutified and structured, some bugs fixed. - * v0.3.x URBifying bulk requests and bugfixing. First relatively - * stable release. Still can touch device's registers only - * from top-halves. - * v0.4.0 Control messages remained unurbified are now URBs. - * Now we can touch the HW at any time. - * v0.4.9 Control urbs again use process context to wait. Argh... - * Some long standing bugs (enable_net_traffic) fixed. - * Also nasty trick about resubmiting control urb from - * interrupt context used. Please let me know how it - * behaves. Pegasus II support added since this version. - * 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 - * v0.5.5 rx socket buffers are in a pool and the their allocation - * is out of the interrupt routine. - */ - -#undef DEBUG - -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/mii.h> -#include <linux/usb.h> -#include <linux/module.h> -#include <asm/byteorder.h> -#include <asm/uaccess.h> -#include "pegasus.h" - -/* - * Version Information - */ -#define DRIVER_VERSION "v0.6.12 (2005/01/13)" -#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>" -#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver" - -static const char driver_name[] = "pegasus"; - -#undef 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; - -static struct usb_eth_dev usb_dev_id[] = { -#define PEGASUS_DEV(pn, vid, pid, flags) \ - {.name = pn, .vendor = vid, .device = pid, .private = flags}, -#include "pegasus.h" -#undef PEGASUS_DEV - {NULL, 0, 0, 0} -}; - -static struct usb_device_id pegasus_ids[] = { -#define PEGASUS_DEV(pn, vid, pid, flags) \ - {.match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = vid, .idProduct = pid}, -#include "pegasus.h" -#undef PEGASUS_DEV - {} -}; - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -module_param(loopback, bool, 0); -module_param(mii_mode, bool, 0); -MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)"); -MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0"); - -/* use ethtool to change the level for any given device */ -static int msg_level = -1; -module_param (msg_level, int, 0); -MODULE_PARM_DESC (msg_level, "Override default message level"); - -MODULE_DEVICE_TABLE(usb, pegasus_ids); - -static int update_eth_regs_async(pegasus_t *); -/* Aargh!!! I _really_ hate such tweaks */ -static void ctrl_callback(struct urb *urb, struct pt_regs *regs) -{ - pegasus_t *pegasus = urb->context; - - if (!pegasus) - return; - - switch (urb->status) { - case 0: - if (pegasus->flags & ETH_REGS_CHANGE) { - pegasus->flags &= ~ETH_REGS_CHANGE; - pegasus->flags |= ETH_REGS_CHANGED; - update_eth_regs_async(pegasus); - return; - } - break; - case -EINPROGRESS: - return; - case -ENOENT: - break; - default: - if (netif_msg_drv(pegasus)) - dev_err(&pegasus->intf->dev, "%s, status %d\n", - __FUNCTION__, urb->status); - } - pegasus->flags &= ~ETH_REGS_CHANGED; - wake_up(&pegasus->ctrl_wait); -} - -static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, - void *data) -{ - int ret; - char *buffer; - DECLARE_WAITQUEUE(wait, current); - - buffer = kmalloc(size, GFP_KERNEL); - if (!buffer) { - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "out of memory in %s\n", - __FUNCTION__); - return -ENOMEM; - } - add_wait_queue(&pegasus->ctrl_wait, &wait); - set_current_state(TASK_UNINTERRUPTIBLE); - while (pegasus->flags & ETH_REGS_CHANGED) - schedule(); - remove_wait_queue(&pegasus->ctrl_wait, &wait); - set_current_state(TASK_RUNNING); - - pegasus->dr.bRequestType = PEGASUS_REQT_READ; - pegasus->dr.bRequest = PEGASUS_REQ_GET_REGS; - pegasus->dr.wValue = cpu_to_le16(0); - pegasus->dr.wIndex = cpu_to_le16p(&indx); - pegasus->dr.wLength = cpu_to_le16p(&size); - pegasus->ctrl_urb->transfer_buffer_length = size; - - usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, - usb_rcvctrlpipe(pegasus->usb, 0), - (char *) &pegasus->dr, - buffer, size, ctrl_callback, pegasus); - - add_wait_queue(&pegasus->ctrl_wait, &wait); - set_current_state(TASK_UNINTERRUPTIBLE); - - /* using ATOMIC, we'd never wake up if we slept */ - if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { - if (netif_msg_drv(pegasus)) - dev_err(&pegasus->intf->dev, "%s, status %d\n", - __FUNCTION__, ret); - goto out; - } - - schedule(); -out: - remove_wait_queue(&pegasus->ctrl_wait, &wait); - memcpy(data, buffer, size); - kfree(buffer); - - return ret; -} - -static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, - void *data) -{ - int ret; - char *buffer; - DECLARE_WAITQUEUE(wait, current); - - buffer = kmalloc(size, GFP_KERNEL); - if (!buffer) { - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "out of memory in %s\n", - __FUNCTION__); - return -ENOMEM; - } - memcpy(buffer, data, size); - - add_wait_queue(&pegasus->ctrl_wait, &wait); - set_current_state(TASK_UNINTERRUPTIBLE); - while (pegasus->flags & ETH_REGS_CHANGED) - schedule(); - remove_wait_queue(&pegasus->ctrl_wait, &wait); - set_current_state(TASK_RUNNING); - - pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; - pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS; - pegasus->dr.wValue = cpu_to_le16(0); - pegasus->dr.wIndex = cpu_to_le16p(&indx); - pegasus->dr.wLength = cpu_to_le16p(&size); - pegasus->ctrl_urb->transfer_buffer_length = size; - - usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, - usb_sndctrlpipe(pegasus->usb, 0), - (char *) &pegasus->dr, - buffer, size, ctrl_callback, pegasus); - - add_wait_queue(&pegasus->ctrl_wait, &wait); - set_current_state(TASK_UNINTERRUPTIBLE); - - if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { - if (netif_msg_drv(pegasus)) - dev_err(&pegasus->intf->dev, "%s, status %d\n", - __FUNCTION__, ret); - goto out; - } - - schedule(); -out: - remove_wait_queue(&pegasus->ctrl_wait, &wait); - kfree(buffer); - - return ret; -} - -static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) -{ - int ret; - char *tmp; - DECLARE_WAITQUEUE(wait, current); - - tmp = kmalloc(1, GFP_KERNEL); - if (!tmp) { - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "out of memory in %s\n", - __FUNCTION__); - return -ENOMEM; - } - memcpy(tmp, &data, 1); - add_wait_queue(&pegasus->ctrl_wait, &wait); - set_current_state(TASK_UNINTERRUPTIBLE); - while (pegasus->flags & ETH_REGS_CHANGED) - schedule(); - remove_wait_queue(&pegasus->ctrl_wait, &wait); - set_current_state(TASK_RUNNING); - - pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; - pegasus->dr.bRequest = PEGASUS_REQ_SET_REG; - pegasus->dr.wValue = cpu_to_le16(data); - pegasus->dr.wIndex = cpu_to_le16p(&indx); - pegasus->dr.wLength = cpu_to_le16(1); - pegasus->ctrl_urb->transfer_buffer_length = 1; - - usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, - usb_sndctrlpipe(pegasus->usb, 0), - (char *) &pegasus->dr, - &tmp, 1, ctrl_callback, pegasus); - - add_wait_queue(&pegasus->ctrl_wait, &wait); - set_current_state(TASK_UNINTERRUPTIBLE); - - if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { - if (netif_msg_drv(pegasus)) - dev_err(&pegasus->intf->dev, "%s, status %d\n", - __FUNCTION__, ret); - goto out; - } - - schedule(); -out: - remove_wait_queue(&pegasus->ctrl_wait, &wait); - kfree(tmp); - - return ret; -} - -static int update_eth_regs_async(pegasus_t * pegasus) -{ - int ret; - - pegasus->dr.bRequestType = PEGASUS_REQT_WRITE; - pegasus->dr.bRequest = PEGASUS_REQ_SET_REGS; - pegasus->dr.wValue = 0; - pegasus->dr.wIndex = cpu_to_le16(EthCtrl0); - pegasus->dr.wLength = cpu_to_le16(3); - pegasus->ctrl_urb->transfer_buffer_length = 3; - - usb_fill_control_urb(pegasus->ctrl_urb, pegasus->usb, - usb_sndctrlpipe(pegasus->usb, 0), - (char *) &pegasus->dr, - pegasus->eth_regs, 3, ctrl_callback, pegasus); - - if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) - if (netif_msg_drv(pegasus)) - dev_err(&pegasus->intf->dev, "%s, status %d\n", - __FUNCTION__, ret); - - return ret; -} - -static int read_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 * regd) -{ - int i; - __u8 data[4] = { phy, 0, 0, indx }; - __le16 regdi; - int ret; - - ret = set_register(pegasus, PhyCtrl, 0); - ret = set_registers(pegasus, PhyAddr, sizeof (data), data); - ret = set_register(pegasus, PhyCtrl, (indx | PHY_READ)); - for (i = 0; i < REG_TIMEOUT; i++) { - ret = get_registers(pegasus, PhyCtrl, 1, data); - if (data[0] & PHY_DONE) - break; - } - if (i < REG_TIMEOUT) { - ret = get_registers(pegasus, PhyData, 2, ®di); - *regd = le16_to_cpu(regdi); - return 1; - } - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); - - return 0; -} - -static int mdio_read(struct net_device *dev, int phy_id, int loc) -{ - pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev); - u16 res; - - read_mii_word(pegasus, phy_id, loc, &res); - return (int)res; -} - -static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd) -{ - int i; - __u8 data[4] = { phy, 0, 0, indx }; - int ret; - - data[1] = (u8) regd; - data[2] = (u8) (regd >> 8); - ret = set_register(pegasus, PhyCtrl, 0); - ret = set_registers(pegasus, PhyAddr, sizeof(data), data); - ret = set_register(pegasus, PhyCtrl, (indx | PHY_WRITE)); - for (i = 0; i < REG_TIMEOUT; i++) { - ret = get_registers(pegasus, PhyCtrl, 1, data); - if (data[0] & PHY_DONE) - break; - } - if (i < REG_TIMEOUT) - return 0; - - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); - return 1; -} - -static void mdio_write(struct net_device *dev, int phy_id, int loc, int val) -{ - pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev); - - write_mii_word(pegasus, phy_id, loc, val); -} - -static int read_eprom_word(pegasus_t * pegasus, __u8 index, __u16 * retdata) -{ - int i; - __u8 tmp; - __le16 retdatai; - int ret; - - ret = set_register(pegasus, EpromCtrl, 0); - ret = set_register(pegasus, EpromOffset, index); - ret = set_register(pegasus, EpromCtrl, EPROM_READ); - - for (i = 0; i < REG_TIMEOUT; i++) { - ret = get_registers(pegasus, EpromCtrl, 1, &tmp); - if (tmp & EPROM_DONE) - break; - } - if (i < REG_TIMEOUT) { - ret = get_registers(pegasus, EpromData, 2, &retdatai); - *retdata = le16_to_cpu(retdatai); - return 0; - } - - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); - return -1; -} - -#ifdef PEGASUS_WRITE_EEPROM -static inline void enable_eprom_write(pegasus_t * pegasus) -{ - __u8 tmp; - int ret; - - ret = get_registers(pegasus, EthCtrl2, 1, &tmp); - ret = set_register(pegasus, EthCtrl2, tmp | EPROM_WR_ENABLE); -} - -static inline void disable_eprom_write(pegasus_t * pegasus) -{ - __u8 tmp; - int ret; - - ret = get_registers(pegasus, EthCtrl2, 1, &tmp); - ret = set_register(pegasus, EpromCtrl, 0); - ret = set_register(pegasus, EthCtrl2, tmp & ~EPROM_WR_ENABLE); -} - -static int write_eprom_word(pegasus_t * pegasus, __u8 index, __u16 data) -{ - int i; - __u8 tmp, d[4] = { 0x3f, 0, 0, EPROM_WRITE }; - int ret; - - ret = set_registers(pegasus, EpromOffset, 4, d); - enable_eprom_write(pegasus); - ret = set_register(pegasus, EpromOffset, index); - ret = set_registers(pegasus, EpromData, 2, &data); - ret = set_register(pegasus, EpromCtrl, EPROM_WRITE); - - for (i = 0; i < REG_TIMEOUT; i++) { - ret = get_registers(pegasus, EpromCtrl, 1, &tmp); - if (tmp & EPROM_DONE) - break; - } - disable_eprom_write(pegasus); - if (i < REG_TIMEOUT) - return 0; - if (netif_msg_drv(pegasus)) - dev_warn(&pegasus->intf->dev, "fail %s\n", __FUNCTION__); - return -1; -} -#endif /* PEGASUS_WRITE_EEPROM */ - -static inline void get_node_id(pegasus_t * pegasus, __u8 * id) -{ - int i; - __u16 w16; - - for (i = 0; i < 3; i++) { - read_eprom_word(pegasus, i, &w16); - ((__le16 *) id)[i] = cpu_to_le16p(&w16); - } -} - -static void set_ethernet_addr(pegasus_t * pegasus) -{ - __u8 node_id[6]; - int ret; - - get_node_id(pegasus, node_id); - ret = set_registers(pegasus, EthID, sizeof (node_id), node_id); - memcpy(pegasus->net->dev_addr, node_id, sizeof (node_id)); -} - -static inline int reset_mac(pegasus_t * pegasus) -{ - __u8 data = 0x8; - int i; - int ret; - - ret = set_register(pegasus, EthCtrl1, data); - for (i = 0; i < REG_TIMEOUT; i++) { - ret = get_registers(pegasus, EthCtrl1, 1, &data); - if (~data & 0x08) { - if (loopback & 1) - break; - if (mii_mode && (pegasus->features & HAS_HOME_PNA)) - ret = set_register(pegasus, Gpio1, 0x34); - else - ret = set_register(pegasus, Gpio1, 0x26); - ret = set_register(pegasus, Gpio0, pegasus->features); - ret = set_register(pegasus, Gpio0, DEFAULT_GPIO_SET); - break; - } - } - if (i == REG_TIMEOUT) - return 1; - - if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || - usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK) { - ret = set_register(pegasus, Gpio0, 0x24); - ret = set_register(pegasus, Gpio0, 0x26); - } - if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_ELCON) { - __u16 auxmode; - read_mii_word(pegasus, 3, 0x1b, &auxmode); - write_mii_word(pegasus, 3, 0x1b, auxmode | 4); - } - - return 0; -} - -static int enable_net_traffic(struct net_device *dev, struct usb_device *usb) -{ - __u16 linkpart; - __u8 data[4]; - pegasus_t *pegasus = netdev_priv(dev); - int ret; - - read_mii_word(pegasus, pegasus->phy, MII_LPA, &linkpart); - data[0] = 0xc9; - data[1] = 0; - if (linkpart & (ADVERTISE_100FULL | ADVERTISE_10FULL)) - data[1] |= 0x20; /* set full duplex */ - if (linkpart & (ADVERTISE_100FULL | ADVERTISE_100HALF)) - data[1] |= 0x10; /* set 100 Mbps */ - if (mii_mode) - data[1] = 0; - data[2] = (loopback & 1) ? 0x09 : 0x01; - - memcpy(pegasus->eth_regs, data, sizeof (data)); - ret = set_registers(pegasus, EthCtrl0, 3, data); - - if (usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || - 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); - } - - return 0; -} - -static void fill_skb_pool(pegasus_t * pegasus) -{ - int i; - - for (i = 0; i < RX_SKBS; i++) { - if (pegasus->rx_pool[i]) - continue; - pegasus->rx_pool[i] = dev_alloc_skb(PEGASUS_MTU + 2); - /* - ** we give up if the allocation fail. the tasklet will be - ** rescheduled again anyway... - */ - if (pegasus->rx_pool[i] == NULL) - return; - pegasus->rx_pool[i]->dev = pegasus->net; - skb_reserve(pegasus->rx_pool[i], 2); - } -} - -static void free_skb_pool(pegasus_t * pegasus) -{ - int i; - - for (i = 0; i < RX_SKBS; i++) { - if (pegasus->rx_pool[i]) { - dev_kfree_skb(pegasus->rx_pool[i]); - pegasus->rx_pool[i] = NULL; - } - } -} - -static inline struct sk_buff *pull_skb(pegasus_t * pegasus) -{ - int i; - struct sk_buff *skb; - - for (i = 0; i < RX_SKBS; i++) { - if (likely(pegasus->rx_pool[i] != NULL)) { - skb = pegasus->rx_pool[i]; - pegasus->rx_pool[i] = NULL; - return skb; - } - } - return NULL; -} - -static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) -{ - pegasus_t *pegasus = urb->context; - struct net_device *net; - int rx_status, count = urb->actual_length; - u8 *buf = urb->transfer_buffer; - __u16 pkt_len; - - if (!pegasus) - return; - - net = pegasus->net; - if (!netif_device_present(net) || !netif_running(net)) - return; - - switch (urb->status) { - case 0: - break; - case -ETIMEDOUT: - if (netif_msg_rx_err(pegasus)) - pr_debug("%s: reset MAC\n", net->name); - pegasus->flags &= ~PEGASUS_RX_BUSY; - break; - case -EPIPE: /* stall, or disconnect from TT */ - /* FIXME schedule work to clear the halt */ - if (netif_msg_rx_err(pegasus)) - printk(KERN_WARNING "%s: no rx stall recovery\n", - net->name); - return; - case -ENOENT: - case -ECONNRESET: - case -ESHUTDOWN: - if (netif_msg_ifdown(pegasus)) - pr_debug("%s: rx unlink, %d\n", net->name, urb->status); - return; - default: - if (netif_msg_rx_err(pegasus)) - pr_debug("%s: RX status %d\n", net->name, urb->status); - goto goon; - } - - if (!count || count < 4) - goto goon; - - rx_status = buf[count - 2]; - if (rx_status & 0x1e) { - if (netif_msg_rx_err(pegasus)) - pr_debug("%s: RX packet error %x\n", - net->name, rx_status); - pegasus->stats.rx_errors++; - if (rx_status & 0x06) // long or runt - pegasus->stats.rx_length_errors++; - if (rx_status & 0x08) - pegasus->stats.rx_crc_errors++; - if (rx_status & 0x10) // extra bits - pegasus->stats.rx_frame_errors++; - goto goon; - } - if (pegasus->chip == 0x8513) { - pkt_len = le32_to_cpu(*(__le32 *)urb->transfer_buffer); - pkt_len &= 0x0fff; - pegasus->rx_skb->data += 2; - } else { - pkt_len = buf[count - 3] << 8; - pkt_len += buf[count - 4]; - pkt_len &= 0xfff; - pkt_len -= 8; - } - - /* - * If the packet is unreasonably long, quietly drop it rather than - * kernel panicing by calling skb_put. - */ - if (pkt_len > PEGASUS_MTU) - goto goon; - - /* - * at this point we are sure pegasus->rx_skb != NULL - * so we go ahead and pass up the packet. - */ - skb_put(pegasus->rx_skb, pkt_len); - pegasus->rx_skb->protocol = eth_type_trans(pegasus->rx_skb, net); - netif_rx(pegasus->rx_skb); - pegasus->stats.rx_packets++; - pegasus->stats.rx_bytes += pkt_len; - - if (pegasus->flags & PEGASUS_UNPLUG) - return; - - spin_lock(&pegasus->rx_pool_lock); - pegasus->rx_skb = pull_skb(pegasus); - spin_unlock(&pegasus->rx_pool_lock); - - if (pegasus->rx_skb == NULL) - goto tl_sched; -goon: - usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, - usb_rcvbulkpipe(pegasus->usb, 1), - pegasus->rx_skb->data, PEGASUS_MTU + 8, - read_bulk_callback, pegasus); - if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { - pegasus->flags |= PEGASUS_RX_URB_FAIL; - goto tl_sched; - } else { - pegasus->flags &= ~PEGASUS_RX_URB_FAIL; - } - - return; - -tl_sched: - tasklet_schedule(&pegasus->rx_tl); -} - -static void rx_fixup(unsigned long data) -{ - pegasus_t *pegasus; - unsigned long flags; - - pegasus = (pegasus_t *) data; - if (pegasus->flags & PEGASUS_UNPLUG) - return; - - spin_lock_irqsave(&pegasus->rx_pool_lock, flags); - fill_skb_pool(pegasus); - if (pegasus->flags & PEGASUS_RX_URB_FAIL) - if (pegasus->rx_skb) - goto try_again; - if (pegasus->rx_skb == NULL) { - pegasus->rx_skb = pull_skb(pegasus); - } - if (pegasus->rx_skb == NULL) { - if (netif_msg_rx_err(pegasus)) - printk(KERN_WARNING "%s: low on memory\n", - pegasus->net->name); - tasklet_schedule(&pegasus->rx_tl); - goto done; - } - usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, - usb_rcvbulkpipe(pegasus->usb, 1), - pegasus->rx_skb->data, PEGASUS_MTU + 8, - read_bulk_callback, pegasus); -try_again: - if (usb_submit_urb(pegasus->rx_urb, GFP_ATOMIC)) { - pegasus->flags |= PEGASUS_RX_URB_FAIL; - tasklet_schedule(&pegasus->rx_tl); - } else { - pegasus->flags &= ~PEGASUS_RX_URB_FAIL; - } -done: - spin_unlock_irqrestore(&pegasus->rx_pool_lock, flags); -} - -static void write_bulk_callback(struct urb *urb, struct pt_regs *regs) -{ - pegasus_t *pegasus = urb->context; - struct net_device *net = pegasus->net; - - if (!pegasus) - return; - - if (!netif_device_present(net) || !netif_running(net)) - return; - - switch (urb->status) { - case -EPIPE: - /* FIXME schedule_work() to clear the tx halt */ - netif_stop_queue(net); - if (netif_msg_tx_err(pegasus)) - printk(KERN_WARNING "%s: no tx stall recovery\n", - net->name); - return; - case -ENOENT: - case -ECONNRESET: - case -ESHUTDOWN: - if (netif_msg_ifdown(pegasus)) - pr_debug("%s: tx unlink, %d\n", net->name, urb->status); - return; - default: - if (netif_msg_tx_err(pegasus)) - pr_info("%s: TX status %d\n", net->name, urb->status); - /* FALL THROUGH */ - case 0: - break; - } - - net->trans_start = jiffies; - netif_wake_queue(net); -} - -static void intr_callback(struct urb *urb, struct pt_regs *regs) -{ - pegasus_t *pegasus = urb->context; - struct net_device *net; - int status; - - if (!pegasus) - return; - net = pegasus->net; - - switch (urb->status) { - case 0: - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - default: - /* some Pegasus-I products report LOTS of data - * toggle errors... avoid log spamming - */ - if (netif_msg_timer(pegasus)) - pr_debug("%s: intr status %d\n", net->name, - urb->status); - } - - if (urb->actual_length >= 6) { - u8 * d = urb->transfer_buffer; - - /* byte 0 == tx_status1, reg 2B */ - if (d[0] & (TX_UNDERRUN|EXCESSIVE_COL - |LATE_COL|JABBER_TIMEOUT)) { - pegasus->stats.tx_errors++; - if (d[0] & TX_UNDERRUN) - pegasus->stats.tx_fifo_errors++; - if (d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT)) - pegasus->stats.tx_aborted_errors++; - if (d[0] & LATE_COL) - pegasus->stats.tx_window_errors++; - } - - /* d[5].LINK_STATUS lies on some adapters. - * d[0].NO_CARRIER kicks in only with failed TX. - * ... so monitoring with MII may be safest. - */ - if (d[0] & NO_CARRIER) - netif_carrier_off(net); - else - netif_carrier_on(net); - - /* bytes 3-4 == rx_lostpkt, reg 2E/2F */ - pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4]; - } - - status = usb_submit_urb(urb, SLAB_ATOMIC); - if (status && netif_msg_timer(pegasus)) - printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n", - net->name, status); -} - -static void pegasus_tx_timeout(struct net_device *net) -{ - pegasus_t *pegasus = netdev_priv(net); - if (netif_msg_timer(pegasus)) - printk(KERN_WARNING "%s: tx timeout\n", net->name); - usb_unlink_urb(pegasus->tx_urb); - pegasus->stats.tx_errors++; -} - -static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) -{ - pegasus_t *pegasus = netdev_priv(net); - int count = ((skb->len + 2) & 0x3f) ? skb->len + 2 : skb->len + 3; - int res; - __u16 l16 = skb->len; - - netif_stop_queue(net); - - ((__le16 *) pegasus->tx_buff)[0] = cpu_to_le16(l16); - memcpy(pegasus->tx_buff + 2, skb->data, skb->len); - usb_fill_bulk_urb(pegasus->tx_urb, pegasus->usb, - usb_sndbulkpipe(pegasus->usb, 2), - pegasus->tx_buff, count, - write_bulk_callback, pegasus); - if ((res = usb_submit_urb(pegasus->tx_urb, GFP_ATOMIC))) { - if (netif_msg_tx_err(pegasus)) - printk(KERN_WARNING "%s: fail tx, %d\n", - net->name, res); - switch (res) { - case -EPIPE: /* stall, or disconnect from TT */ - /* cleanup should already have been scheduled */ - break; - case -ENODEV: /* disconnect() upcoming */ - break; - default: - pegasus->stats.tx_errors++; - netif_start_queue(net); - } - } else { - pegasus->stats.tx_packets++; - pegasus->stats.tx_bytes += skb->len; - net->trans_start = jiffies; - } - dev_kfree_skb(skb); - - return 0; -} - -static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev) -{ - return &((pegasus_t *) netdev_priv(dev))->stats; -} - -static inline void disable_net_traffic(pegasus_t * pegasus) -{ - int tmp = 0; - int ret; - - ret = set_registers(pegasus, EthCtrl0, 2, &tmp); -} - -static inline void get_interrupt_interval(pegasus_t * pegasus) -{ - __u8 data[2]; - - read_eprom_word(pegasus, 4, (__u16 *) data); - if (pegasus->usb->speed != USB_SPEED_HIGH) { - if (data[1] < 0x80) { - if (netif_msg_timer(pegasus)) - dev_info(&pegasus->intf->dev, "intr interval " - "changed from %ums to %ums\n", - data[1], 0x80); - data[1] = 0x80; -#ifdef PEGASUS_WRITE_EEPROM - write_eprom_word(pegasus, 4, *(__u16 *) data); -#endif - } - } - pegasus->intr_interval = data[1]; -} - -static void set_carrier(struct net_device *net) -{ - pegasus_t *pegasus = netdev_priv(net); - u16 tmp; - - if (!read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp)) - return; - - if (tmp & BMSR_LSTATUS) - netif_carrier_on(net); - else - netif_carrier_off(net); -} - -static void free_all_urbs(pegasus_t * pegasus) -{ - usb_free_urb(pegasus->intr_urb); - usb_free_urb(pegasus->tx_urb); - usb_free_urb(pegasus->rx_urb); - usb_free_urb(pegasus->ctrl_urb); -} - -static void unlink_all_urbs(pegasus_t * pegasus) -{ - usb_kill_urb(pegasus->intr_urb); - usb_kill_urb(pegasus->tx_urb); - usb_kill_urb(pegasus->rx_urb); - usb_kill_urb(pegasus->ctrl_urb); -} - -static int alloc_urbs(pegasus_t * pegasus) -{ - pegasus->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!pegasus->ctrl_urb) { - return 0; - } - pegasus->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!pegasus->rx_urb) { - usb_free_urb(pegasus->ctrl_urb); - return 0; - } - pegasus->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!pegasus->tx_urb) { - usb_free_urb(pegasus->rx_urb); - usb_free_urb(pegasus->ctrl_urb); - return 0; - } - pegasus->intr_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!pegasus->intr_urb) { - usb_free_urb(pegasus->tx_urb); - usb_free_urb(pegasus->rx_urb); - usb_free_urb(pegasus->ctrl_urb); - return 0; - } - - return 1; -} - -static int pegasus_open(struct net_device *net) -{ - pegasus_t *pegasus = netdev_priv(net); - int res; - - if (pegasus->rx_skb == NULL) - pegasus->rx_skb = pull_skb(pegasus); - /* - ** Note: no point to free the pool. it is empty :-) - */ - if (!pegasus->rx_skb) - return -ENOMEM; - - res = set_registers(pegasus, EthID, 6, net->dev_addr); - - usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb, - usb_rcvbulkpipe(pegasus->usb, 1), - pegasus->rx_skb->data, PEGASUS_MTU + 8, - read_bulk_callback, pegasus); - if ((res = usb_submit_urb(pegasus->rx_urb, GFP_KERNEL))) { - if (netif_msg_ifup(pegasus)) - pr_debug("%s: failed rx_urb, %d", net->name, res); - goto exit; - } - - usb_fill_int_urb(pegasus->intr_urb, pegasus->usb, - usb_rcvintpipe(pegasus->usb, 3), - pegasus->intr_buff, sizeof (pegasus->intr_buff), - intr_callback, pegasus, pegasus->intr_interval); - if ((res = usb_submit_urb(pegasus->intr_urb, GFP_KERNEL))) { - if (netif_msg_ifup(pegasus)) - pr_debug("%s: failed intr_urb, %d\n", net->name, res); - usb_kill_urb(pegasus->rx_urb); - goto exit; - } - if ((res = enable_net_traffic(net, pegasus->usb))) { - if (netif_msg_ifup(pegasus)) - pr_debug("%s: can't enable_net_traffic() - %d\n", - net->name, res); - res = -EIO; - usb_kill_urb(pegasus->rx_urb); - usb_kill_urb(pegasus->intr_urb); - free_skb_pool(pegasus); - goto exit; - } - set_carrier(net); - netif_start_queue(net); - if (netif_msg_ifup(pegasus)) - pr_debug("%s: open\n", net->name); - res = 0; -exit: - return res; -} - -static int pegasus_close(struct net_device *net) -{ - pegasus_t *pegasus = netdev_priv(net); - - netif_stop_queue(net); - if (!(pegasus->flags & PEGASUS_UNPLUG)) - disable_net_traffic(pegasus); - tasklet_kill(&pegasus->rx_tl); - unlink_all_urbs(pegasus); - - return 0; -} - -static void pegasus_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - pegasus_t *pegasus = netdev_priv(dev); - strncpy(info->driver, driver_name, sizeof (info->driver) - 1); - strncpy(info->version, DRIVER_VERSION, sizeof (info->version) - 1); - usb_make_path(pegasus->usb, info->bus_info, sizeof (info->bus_info)); -} - -/* also handles three patterns of some kind in hardware */ -#define WOL_SUPPORTED (WAKE_MAGIC|WAKE_PHY) - -static void -pegasus_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - pegasus_t *pegasus = netdev_priv(dev); - - wol->supported = WAKE_MAGIC | WAKE_PHY; - wol->wolopts = pegasus->wolopts; -} - -static int -pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - pegasus_t *pegasus = netdev_priv(dev); - u8 reg78 = 0x04; - - if (wol->wolopts & ~WOL_SUPPORTED) - return -EINVAL; - - if (wol->wolopts & WAKE_MAGIC) - reg78 |= 0x80; - if (wol->wolopts & WAKE_PHY) - reg78 |= 0x40; - /* FIXME this 0x10 bit still needs to get set in the chip... */ - if (wol->wolopts) - pegasus->eth_regs[0] |= 0x10; - else - pegasus->eth_regs[0] &= ~0x10; - pegasus->wolopts = wol->wolopts; - return set_register(pegasus, WakeupControl, reg78); -} - -static inline void pegasus_reset_wol(struct net_device *dev) -{ - struct ethtool_wolinfo wol; - - memset(&wol, 0, sizeof wol); - (void) pegasus_set_wol(dev, &wol); -} - -static int -pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - pegasus_t *pegasus; - - if (in_atomic()) - return 0; - - pegasus = netdev_priv(dev); - mii_ethtool_gset(&pegasus->mii, ecmd); - - return 0; -} - -static int -pegasus_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - pegasus_t *pegasus = netdev_priv(dev); - return mii_ethtool_sset(&pegasus->mii, ecmd); -} - -static int pegasus_nway_reset(struct net_device *dev) -{ - pegasus_t *pegasus = netdev_priv(dev); - return mii_nway_restart(&pegasus->mii); -} - -static u32 pegasus_get_link(struct net_device *dev) -{ - pegasus_t *pegasus = netdev_priv(dev); - return mii_link_ok(&pegasus->mii); -} - -static u32 pegasus_get_msglevel(struct net_device *dev) -{ - pegasus_t *pegasus = netdev_priv(dev); - return pegasus->msg_enable; -} - -static void pegasus_set_msglevel(struct net_device *dev, u32 v) -{ - pegasus_t *pegasus = netdev_priv(dev); - pegasus->msg_enable = v; -} - -static struct ethtool_ops ops = { - .get_drvinfo = pegasus_get_drvinfo, - .get_settings = pegasus_get_settings, - .set_settings = pegasus_set_settings, - .nway_reset = pegasus_nway_reset, - .get_link = pegasus_get_link, - .get_msglevel = pegasus_get_msglevel, - .set_msglevel = pegasus_set_msglevel, - .get_wol = pegasus_get_wol, - .set_wol = pegasus_set_wol, -}; - -static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) -{ - __u16 *data = (__u16 *) & rq->ifr_ifru; - pegasus_t *pegasus = netdev_priv(net); - int res; - - switch (cmd) { - case SIOCDEVPRIVATE: - data[0] = pegasus->phy; - case SIOCDEVPRIVATE + 1: - read_mii_word(pegasus, data[0], data[1] & 0x1f, &data[3]); - res = 0; - break; - case SIOCDEVPRIVATE + 2: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]); - res = 0; - break; - default: - res = -EOPNOTSUPP; - } - return res; -} - -static void pegasus_set_multicast(struct net_device *net) -{ - pegasus_t *pegasus = netdev_priv(net); - - if (net->flags & IFF_PROMISC) { - pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS; - if (netif_msg_link(pegasus)) - pr_info("%s: Promiscuous mode enabled.\n", net->name); - } else if (net->mc_count || - (net->flags & IFF_ALLMULTI)) { - pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST; - pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; - if (netif_msg_link(pegasus)) - pr_info("%s: set allmulti\n", net->name); - } else { - pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST; - pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS; - } - - pegasus->flags |= ETH_REGS_CHANGE; - ctrl_callback(pegasus->ctrl_urb, NULL); -} - -static __u8 mii_phy_probe(pegasus_t * pegasus) -{ - int i; - __u16 tmp; - - for (i = 0; i < 32; i++) { - read_mii_word(pegasus, i, MII_BMSR, &tmp); - if (tmp == 0 || tmp == 0xffff || (tmp & BMSR_MEDIA) == 0) - continue; - else - return i; - } - - return 0xff; -} - -static inline void setup_pegasus_II(pegasus_t * pegasus) -{ - __u8 data = 0xa5; - int ret; - - ret = set_register(pegasus, Reg1d, 0); - ret = set_register(pegasus, Reg7b, 1); - mdelay(100); - if ((pegasus->features & HAS_HOME_PNA) && mii_mode) - ret = set_register(pegasus, Reg7b, 0); - else - ret = set_register(pegasus, Reg7b, 2); - - ret = set_register(pegasus, 0x83, data); - ret = get_registers(pegasus, 0x83, 1, &data); - - if (data == 0xa5) { - pegasus->chip = 0x8513; - } else { - pegasus->chip = 0; - } - - ret = set_register(pegasus, 0x80, 0xc0); - ret = set_register(pegasus, 0x83, 0xff); - ret = set_register(pegasus, 0x84, 0x01); - - if (pegasus->features & HAS_HOME_PNA && mii_mode) - ret = set_register(pegasus, Reg81, 6); - else - ret = set_register(pegasus, Reg81, 2); -} - - -static struct workqueue_struct *pegasus_workqueue = NULL; -#define CARRIER_CHECK_DELAY (2 * HZ) - -static void check_carrier(void *data) -{ - pegasus_t *pegasus = data; - set_carrier(pegasus->net); - if (!(pegasus->flags & PEGASUS_UNPLUG)) { - queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, - CARRIER_CHECK_DELAY); - } -} - -static int pegasus_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct net_device *net; - pegasus_t *pegasus; - int dev_index = id - pegasus_ids; - int res = -ENOMEM; - - usb_get_dev(dev); - net = alloc_etherdev(sizeof(struct pegasus)); - if (!net) { - dev_err(&intf->dev, "can't allocate %s\n", "device"); - goto out; - } - - pegasus = netdev_priv(net); - memset(pegasus, 0, sizeof (struct pegasus)); - pegasus->dev_index = dev_index; - init_waitqueue_head(&pegasus->ctrl_wait); - - if (!alloc_urbs(pegasus)) { - dev_err(&intf->dev, "can't allocate %s\n", "urbs"); - goto out1; - } - - tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus); - - INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus); - - pegasus->intf = intf; - pegasus->usb = dev; - pegasus->net = net; - SET_MODULE_OWNER(net); - net->open = pegasus_open; - net->stop = pegasus_close; - net->watchdog_timeo = PEGASUS_TX_TIMEOUT; - net->tx_timeout = pegasus_tx_timeout; - net->do_ioctl = pegasus_ioctl; - net->hard_start_xmit = pegasus_start_xmit; - net->set_multicast_list = pegasus_set_multicast; - net->get_stats = pegasus_netdev_stats; - SET_ETHTOOL_OPS(net, &ops); - pegasus->mii.dev = net; - pegasus->mii.mdio_read = mdio_read; - pegasus->mii.mdio_write = mdio_write; - pegasus->mii.phy_id_mask = 0x1f; - pegasus->mii.reg_num_mask = 0x1f; - spin_lock_init(&pegasus->rx_pool_lock); - pegasus->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV - | NETIF_MSG_PROBE | NETIF_MSG_LINK); - - pegasus->features = usb_dev_id[dev_index].private; - get_interrupt_interval(pegasus); - if (reset_mac(pegasus)) { - dev_err(&intf->dev, "can't reset MAC\n"); - res = -EIO; - goto out2; - } - set_ethernet_addr(pegasus); - fill_skb_pool(pegasus); - if (pegasus->features & PEGASUS_II) { - dev_info(&intf->dev, "setup Pegasus II specific registers\n"); - setup_pegasus_II(pegasus); - } - pegasus->phy = mii_phy_probe(pegasus); - if (pegasus->phy == 0xff) { - dev_warn(&intf->dev, "can't locate MII phy, using default\n"); - pegasus->phy = 1; - } - pegasus->mii.phy_id = pegasus->phy; - usb_set_intfdata(intf, pegasus); - SET_NETDEV_DEV(net, &intf->dev); - pegasus_reset_wol(net); - res = register_netdev(net); - if (res) - goto out3; - queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, - CARRIER_CHECK_DELAY); - - dev_info(&intf->dev, "%s, %s, %02x:%02x:%02x:%02x:%02x:%02x\n", - net->name, - usb_dev_id[dev_index].name, - net->dev_addr [0], net->dev_addr [1], - net->dev_addr [2], net->dev_addr [3], - net->dev_addr [4], net->dev_addr [5]); - return 0; - -out3: - usb_set_intfdata(intf, NULL); - free_skb_pool(pegasus); -out2: - free_all_urbs(pegasus); -out1: - free_netdev(net); -out: - usb_put_dev(dev); - return res; -} - -static void pegasus_disconnect(struct usb_interface *intf) -{ - struct pegasus *pegasus = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - if (!pegasus) { - dev_dbg(&intf->dev, "unregistering non-bound device?\n"); - return; - } - - pegasus->flags |= PEGASUS_UNPLUG; - cancel_delayed_work(&pegasus->carrier_check); - unregister_netdev(pegasus->net); - usb_put_dev(interface_to_usbdev(intf)); - unlink_all_urbs(pegasus); - free_all_urbs(pegasus); - free_skb_pool(pegasus); - if (pegasus->rx_skb) - dev_kfree_skb(pegasus->rx_skb); - free_netdev(pegasus->net); -} - -static int pegasus_suspend (struct usb_interface *intf, pm_message_t message) -{ - struct pegasus *pegasus = usb_get_intfdata(intf); - - netif_device_detach (pegasus->net); - if (netif_running(pegasus->net)) { - cancel_delayed_work(&pegasus->carrier_check); - - usb_kill_urb(pegasus->rx_urb); - usb_kill_urb(pegasus->intr_urb); - } - return 0; -} - -static int pegasus_resume (struct usb_interface *intf) -{ - struct pegasus *pegasus = usb_get_intfdata(intf); - - netif_device_attach (pegasus->net); - if (netif_running(pegasus->net)) { - pegasus->rx_urb->status = 0; - pegasus->rx_urb->actual_length = 0; - read_bulk_callback(pegasus->rx_urb, NULL); - - pegasus->intr_urb->status = 0; - pegasus->intr_urb->actual_length = 0; - intr_callback(pegasus->intr_urb, NULL); - - queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, - CARRIER_CHECK_DELAY); - } - return 0; -} - -static struct usb_driver pegasus_driver = { - .name = driver_name, - .probe = pegasus_probe, - .disconnect = pegasus_disconnect, - .id_table = pegasus_ids, - .suspend = pegasus_suspend, - .resume = pegasus_resume, -}; - -static int __init pegasus_init(void) -{ - pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION); - pegasus_workqueue = create_singlethread_workqueue("pegasus"); - if (!pegasus_workqueue) - return -ENOMEM; - return usb_register(&pegasus_driver); -} - -static void __exit pegasus_exit(void) -{ - destroy_workqueue(pegasus_workqueue); - usb_deregister(&pegasus_driver); -} - -module_init(pegasus_init); -module_exit(pegasus_exit); diff --git a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h deleted file mode 100644 index 9fbd59b55cb..00000000000 --- a/drivers/usb/net/pegasus.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 1999-2003 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 version 2 as published - * by the Free Software Foundation. - */ - - -#ifndef PEGASUS_DEV - -#define PEGASUS_II 0x80000000 -#define HAS_HOME_PNA 0x40000000 - -#define PEGASUS_MTU 1536 -#define RX_SKBS 4 - -#define EPROM_WRITE 0x01 -#define EPROM_READ 0x02 -#define EPROM_DONE 0x04 -#define EPROM_WR_ENABLE 0x10 -#define EPROM_LOAD 0x20 - -#define PHY_DONE 0x80 -#define PHY_READ 0x40 -#define PHY_WRITE 0x20 -#define DEFAULT_GPIO_RESET 0x24 -#define LINKSYS_GPIO_RESET 0x24 -#define DEFAULT_GPIO_SET 0x26 - -#define PEGASUS_PRESENT 0x00000001 -#define PEGASUS_TX_BUSY 0x00000004 -#define PEGASUS_RX_BUSY 0x00000008 -#define CTRL_URB_RUNNING 0x00000010 -#define CTRL_URB_SLEEP 0x00000020 -#define PEGASUS_UNPLUG 0x00000040 -#define PEGASUS_RX_URB_FAIL 0x00000080 -#define ETH_REGS_CHANGE 0x40000000 -#define ETH_REGS_CHANGED 0x80000000 - -#define RX_MULTICAST 2 -#define RX_PROMISCUOUS 4 - -#define REG_TIMEOUT (HZ) -#define PEGASUS_TX_TIMEOUT (HZ*10) - -#define TX_UNDERRUN 0x80 -#define EXCESSIVE_COL 0x40 -#define LATE_COL 0x20 -#define NO_CARRIER 0x10 -#define LOSS_CARRIER 0x08 -#define JABBER_TIMEOUT 0x04 - -#define LINK_STATUS 0x01 - -#define PEGASUS_REQT_READ 0xc0 -#define PEGASUS_REQT_WRITE 0x40 -#define PEGASUS_REQ_GET_REGS 0xf0 -#define PEGASUS_REQ_SET_REGS 0xf1 -#define PEGASUS_REQ_SET_REG PEGASUS_REQ_SET_REGS - -enum pegasus_registers { - EthCtrl0 = 0, - EthCtrl1 = 1, - EthCtrl2 = 2, - EthID = 0x10, - Reg1d = 0x1d, - EpromOffset = 0x20, - EpromData = 0x21, /* 0x21 low, 0x22 high byte */ - EpromCtrl = 0x23, - PhyAddr = 0x25, - PhyData = 0x26, /* 0x26 low, 0x27 high byte */ - PhyCtrl = 0x28, - UsbStst = 0x2a, - EthTxStat0 = 0x2b, - EthTxStat1 = 0x2c, - EthRxStat = 0x2d, - WakeupControl = 0x78, - Reg7b = 0x7b, - Gpio0 = 0x7e, - Gpio1 = 0x7f, - Reg81 = 0x81, -}; - - -typedef struct pegasus { - struct usb_device *usb; - struct usb_interface *intf; - struct net_device *net; - struct net_device_stats stats; - struct mii_if_info mii; - unsigned flags; - unsigned features; - u32 msg_enable; - u32 wolopts; - int dev_index; - int intr_interval; - struct tasklet_struct rx_tl; - struct work_struct carrier_check; - struct urb *ctrl_urb, *rx_urb, *tx_urb, *intr_urb; - struct sk_buff *rx_pool[RX_SKBS]; - struct sk_buff *rx_skb; - struct usb_ctrlrequest dr; - wait_queue_head_t ctrl_wait; - spinlock_t rx_pool_lock; - int chip; - unsigned char intr_buff[8]; - __u8 tx_buff[PEGASUS_MTU]; - __u8 eth_regs[4]; - __u8 phy; - __u8 gpio_res; -} pegasus_t; - - -struct usb_eth_dev { - char *name; - __u16 vendor; - __u16 device; - __u32 private; /* LSB is gpio reset value */ -}; - -#define VENDOR_3COM 0x0506 -#define VENDOR_ABOCOM 0x07b8 -#define VENDOR_ACCTON 0x083a -#define VENDOR_ADMTEK 0x07a6 -#define VENDOR_AEILAB 0x3334 -#define VENDOR_ALLIEDTEL 0x07c9 -#define VENDOR_ATEN 0x0557 -#define VENDOR_BELKIN 0x050d -#define VENDOR_BILLIONTON 0x08dd -#define VENDOR_COMPAQ 0x049f -#define VENDOR_COREGA 0x07aa -#define VENDOR_DLINK 0x2001 -#define VENDOR_ELCON 0x0db7 -#define VENDOR_ELSA 0x05cc -#define VENDOR_GIGABYTE 0x1044 -#define VENDOR_HAWKING 0x0e66 -#define VENDOR_HP 0x03f0 -#define VENDOR_IODATA 0x04bb -#define VENDOR_KINGSTON 0x0951 -#define VENDOR_LANEED 0x056e -#define VENDOR_LINKSYS 0x066b -#define VENDOR_MELCO 0x0411 -#define VENDOR_MICROSOFT 0x045e -#define VENDOR_MOBILITY 0x1342 -#define VENDOR_NETGEAR 0x0846 -#define VENDOR_OCT 0x0b39 -#define VENDOR_SMARTBRIDGES 0x08d1 -#define VENDOR_SMC 0x0707 -#define VENDOR_SOHOWARE 0x15e8 -#define VENDOR_SIEMENS 0x067c - - -#else /* PEGASUS_DEV */ - -PEGASUS_DEV( "3Com USB Ethernet 3C460B", VENDOR_3COM, 0x4601, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "ATEN USB Ethernet UC-110T", VENDOR_ATEN, 0x2007, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x110c, - DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) -PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4104, - DEFAULT_GPIO_RESET | HAS_HOME_PNA ) -PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4004, - DEFAULT_GPIO_RESET | HAS_HOME_PNA ) -PEGASUS_DEV( "USB HPNA/Ethernet", VENDOR_ABOCOM, 0x4007, - DEFAULT_GPIO_RESET | HAS_HOME_PNA ) -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4102, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x4002, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400b, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400c, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0xabc1, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Philips USB 10/100 Ethernet", VENDOR_ACCTON, 0xb004, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet", - VENDOR_ADMTEK, 0x8511, - DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) -PEGASUS_DEV( "ADMtek ADM8513 \"Pegasus II\" USB Ethernet", - VENDOR_ADMTEK, 0x8513, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "ADMtek ADM8515 \"Pegasus II\" USB-2.0 Ethernet", - VENDOR_ADMTEK, 0x8515, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation 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( "AEI USB Fast Ethernet Adapter", VENDOR_AEILAB, 0x1701, - 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, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987, - DEFAULT_GPIO_RESET | HAS_HOME_PNA ) -PEGASUS_DEV( "iPAQ Networking 10/100 USB", VENDOR_COMPAQ, 0x8511, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Billionton USBEL-100", VENDOR_BILLIONTON, 0x0988, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "Corega FEter USB-TXS", VENDOR_COREGA, 0x000d, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4001, - LINKSYS_GPIO_RESET ) -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4002, - LINKSYS_GPIO_RESET ) -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x4102, - LINKSYS_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x400b, - LINKSYS_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK, 0x200c, - LINKSYS_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK, 0x4003, - DEFAULT_GPIO_RESET | HAS_HOME_PNA ) -PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "GOLDPFEIL USB Adapter", VENDOR_ELCON, 0x0002, - DEFAULT_GPIO_RESET | PEGASUS_II | HAS_HOME_PNA ) -PEGASUS_DEV( "EasiDock Ethernet", VENDOR_MOBILITY, 0x0304, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "GIGABYTE GN-BR402W Wireless Router", VENDOR_GIGABYTE, 0x8002, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "HP hn210c Ethernet USB", VENDOR_HP, 0x811c, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Kingston KNU101TX Ethernet", VENDOR_KINGSTON, 0x000a, - DEFAULT_GPIO_RESET) -PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "LANEED USB Ethernet LD-USBL/TX", VENDOR_LANEED, 0x4005, - DEFAULT_GPIO_RESET | PEGASUS_II) -PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x400b, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "LANEED USB Ethernet LD-USB/T", VENDOR_LANEED, 0xabc1, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x200c, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x2202, - LINKSYS_GPIO_RESET ) -PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2203, - LINKSYS_GPIO_RESET ) -PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2204, - LINKSYS_GPIO_RESET | HAS_HOME_PNA ) -PEGASUS_DEV( "Linksys USB10T Ethernet Adapter", VENDOR_LINKSYS, 0x2206, - LINKSYS_GPIO_RESET | PEGASUS_II) -PEGASUS_DEV( "Linksys USB USB100TX", VENDOR_LINKSYS, 0x400b, - LINKSYS_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x200c, - LINKSYS_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0005, - DEFAULT_GPIO_RESET ) -PEGASUS_DEV( "MELCO/BUFFALO LUA2-TX", VENDOR_MELCO, 0x0009, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "Microsoft MN-110", VENDOR_MICROSOFT, 0x007a, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "NETGEAR FA101", VENDOR_NETGEAR, 0x1020, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "OCT Inc.", VENDOR_OCT, 0x0109, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "OCT USB TO Ethernet", VENDOR_OCT, 0x0901, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003, - 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( "SOHOware NUB110 Ethernet", VENDOR_SOHOWARE, 0x9110, - DEFAULT_GPIO_RESET | PEGASUS_II ) -PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_SIEMENS, 0x1001, - DEFAULT_GPIO_RESET | PEGASUS_II ) - - -#endif /* PEGASUS_DEV */ diff --git a/drivers/usb/net/plusb.c b/drivers/usb/net/plusb.c deleted file mode 100644 index 74c2b3581c7..00000000000 --- a/drivers/usb/net/plusb.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * PL-2301/2302 USB host-to-host link cables - * Copyright (C) 2000-2005 by David Brownell - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include <linux/config.h> -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#endif -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/workqueue.h> -#include <linux/mii.h> -#include <linux/usb.h> - -#include "usbnet.h" - - -/* - * Prolific PL-2301/PL-2302 driver ... http://www.prolifictech.com - * - * The protocol and handshaking used here should be bug-compatible - * with the Linux 2.2 "plusb" driver, by Deti Fliegl. - * - * HEADS UP: this handshaking isn't all that robust. This driver - * gets confused easily if you unplug one end of the cable then - * try to connect it again; you'll need to restart both ends. The - * "naplink" software (used by some PlayStation/2 deveopers) does - * the handshaking much better! Also, sometimes this hardware - * seems to get wedged under load. Prolific docs are weak, and - * don't identify differences between PL2301 and PL2302, much less - * anything to explain the different PL2302 versions observed. - */ - -/* - * Bits 0-4 can be used for software handshaking; they're set from - * one end, cleared from the other, "read" with the interrupt byte. - */ -#define PL_S_EN (1<<7) /* (feature only) suspend enable */ -/* reserved bit -- rx ready (6) ? */ -#define PL_TX_READY (1<<5) /* (interrupt only) transmit ready */ -#define PL_RESET_OUT (1<<4) /* reset output pipe */ -#define PL_RESET_IN (1<<3) /* reset input pipe */ -#define PL_TX_C (1<<2) /* transmission complete */ -#define PL_TX_REQ (1<<1) /* transmission received */ -#define PL_PEER_E (1<<0) /* peer exists */ - -static inline int -pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index) -{ - return usb_control_msg(dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - req, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - val, index, - NULL, 0, - USB_CTRL_GET_TIMEOUT); -} - -static inline int -pl_clear_QuickLink_features(struct usbnet *dev, int val) -{ - return pl_vendor_req(dev, 1, (u8) val, 0); -} - -static inline int -pl_set_QuickLink_features(struct usbnet *dev, int val) -{ - return pl_vendor_req(dev, 3, (u8) val, 0); -} - -static int pl_reset(struct usbnet *dev) -{ - /* some units seem to need this reset, others reject it utterly. - * FIXME be more like "naplink" or windows drivers. - */ - (void) pl_set_QuickLink_features(dev, - PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E); - return 0; -} - -static const struct driver_info prolific_info = { - .description = "Prolific PL-2301/PL-2302", - .flags = FLAG_NO_SETINT, - /* some PL-2302 versions seem to fail usb_set_interface() */ - .reset = pl_reset, -}; - - -/*-------------------------------------------------------------------------*/ - -/* - * Proilific's name won't normally be on the cables, and - * may not be on the device. - */ - -static const struct usb_device_id products [] = { - -{ - USB_DEVICE(0x067b, 0x0000), // PL-2301 - .driver_info = (unsigned long) &prolific_info, -}, { - USB_DEVICE(0x067b, 0x0001), // PL-2302 - .driver_info = (unsigned long) &prolific_info, -}, - - { }, // END -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver plusb_driver = { - .owner = THIS_MODULE, - .name = "plusb", - .id_table = products, - .probe = usbnet_probe, - .disconnect = usbnet_disconnect, - .suspend = usbnet_suspend, - .resume = usbnet_resume, -}; - -static int __init plusb_init(void) -{ - return usb_register(&plusb_driver); -} -module_init(plusb_init); - -static void __exit plusb_exit(void) -{ - usb_deregister(&plusb_driver); -} -module_exit(plusb_exit); - -MODULE_AUTHOR("David Brownell"); -MODULE_DESCRIPTION("Prolific PL-2301/2302 USB Host to Host Link Driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/net/rndis_host.c b/drivers/usb/net/rndis_host.c deleted file mode 100644 index b5a925dc1be..00000000000 --- a/drivers/usb/net/rndis_host.c +++ /dev/null @@ -1,615 +0,0 @@ -/* - * Host Side support for RNDIS Networking Links - * Copyright (C) 2005 by David Brownell - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include <linux/config.h> -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#endif -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/workqueue.h> -#include <linux/mii.h> -#include <linux/usb.h> -#include <linux/usb_cdc.h> - -#include "usbnet.h" - - -/* - * RNDIS is NDIS remoted over USB. It's a MSFT variant of CDC ACM ... of - * course ACM was intended for modems, not Ethernet links! USB's standard - * for Ethernet links is "CDC Ethernet", which is significantly simpler. - */ - -/* - * CONTROL uses CDC "encapsulated commands" with funky notifications. - * - control-out: SEND_ENCAPSULATED - * - interrupt-in: RESPONSE_AVAILABLE - * - control-in: GET_ENCAPSULATED - * - * We'll try to ignore the RESPONSE_AVAILABLE notifications. - */ -struct rndis_msg_hdr { - __le32 msg_type; /* RNDIS_MSG_* */ - __le32 msg_len; - // followed by data that varies between messages - __le32 request_id; - __le32 status; - // ... and more -} __attribute__ ((packed)); - -/* RNDIS defines this (absurdly huge) control timeout */ -#define RNDIS_CONTROL_TIMEOUT_MS (10 * 1000) - - -#define ccpu2 __constant_cpu_to_le32 - -#define RNDIS_MSG_COMPLETION ccpu2(0x80000000) - -/* codes for "msg_type" field of rndis messages; - * only the data channel uses packet messages (maybe batched); - * everything else goes on the control channel. - */ -#define RNDIS_MSG_PACKET ccpu2(0x00000001) /* 1-N packets */ -#define RNDIS_MSG_INIT ccpu2(0x00000002) -#define RNDIS_MSG_INIT_C (RNDIS_MSG_INIT|RNDIS_MSG_COMPLETION) -#define RNDIS_MSG_HALT ccpu2(0x00000003) -#define RNDIS_MSG_QUERY ccpu2(0x00000004) -#define RNDIS_MSG_QUERY_C (RNDIS_MSG_QUERY|RNDIS_MSG_COMPLETION) -#define RNDIS_MSG_SET ccpu2(0x00000005) -#define RNDIS_MSG_SET_C (RNDIS_MSG_SET|RNDIS_MSG_COMPLETION) -#define RNDIS_MSG_RESET ccpu2(0x00000006) -#define RNDIS_MSG_RESET_C (RNDIS_MSG_RESET|RNDIS_MSG_COMPLETION) -#define RNDIS_MSG_INDICATE ccpu2(0x00000007) -#define RNDIS_MSG_KEEPALIVE ccpu2(0x00000008) -#define RNDIS_MSG_KEEPALIVE_C (RNDIS_MSG_KEEPALIVE|RNDIS_MSG_COMPLETION) - -/* codes for "status" field of completion messages */ -#define RNDIS_STATUS_SUCCESS ccpu2(0x00000000) -#define RNDIS_STATUS_FAILURE ccpu2(0xc0000001) -#define RNDIS_STATUS_INVALID_DATA ccpu2(0xc0010015) -#define RNDIS_STATUS_NOT_SUPPORTED ccpu2(0xc00000bb) -#define RNDIS_STATUS_MEDIA_CONNECT ccpu2(0x4001000b) -#define RNDIS_STATUS_MEDIA_DISCONNECT ccpu2(0x4001000c) - - -struct rndis_data_hdr { - __le32 msg_type; /* RNDIS_MSG_PACKET */ - __le32 msg_len; // rndis_data_hdr + data_len + pad - __le32 data_offset; // 36 -- right after header - __le32 data_len; // ... real packet size - - __le32 oob_data_offset; // zero - __le32 oob_data_len; // zero - __le32 num_oob; // zero - __le32 packet_data_offset; // zero - - __le32 packet_data_len; // zero - __le32 vc_handle; // zero - __le32 reserved; // zero -} __attribute__ ((packed)); - -struct rndis_init { /* OUT */ - // header and: - __le32 msg_type; /* RNDIS_MSG_INIT */ - __le32 msg_len; // 24 - __le32 request_id; - __le32 major_version; // of rndis (1.0) - __le32 minor_version; - __le32 max_transfer_size; -} __attribute__ ((packed)); - -struct rndis_init_c { /* IN */ - // header and: - __le32 msg_type; /* RNDIS_MSG_INIT_C */ - __le32 msg_len; - __le32 request_id; - __le32 status; - __le32 major_version; // of rndis (1.0) - __le32 minor_version; - __le32 device_flags; - __le32 medium; // zero == 802.3 - __le32 max_packets_per_message; - __le32 max_transfer_size; - __le32 packet_alignment; // max 7; (1<<n) bytes - __le32 af_list_offset; // zero - __le32 af_list_size; // zero -} __attribute__ ((packed)); - -struct rndis_halt { /* OUT (no reply) */ - // header and: - __le32 msg_type; /* RNDIS_MSG_HALT */ - __le32 msg_len; - __le32 request_id; -} __attribute__ ((packed)); - -struct rndis_query { /* OUT */ - // header and: - __le32 msg_type; /* RNDIS_MSG_QUERY */ - __le32 msg_len; - __le32 request_id; - __le32 oid; - __le32 len; - __le32 offset; -/*?*/ __le32 handle; // zero -} __attribute__ ((packed)); - -struct rndis_query_c { /* IN */ - // header and: - __le32 msg_type; /* RNDIS_MSG_QUERY_C */ - __le32 msg_len; - __le32 request_id; - __le32 status; - __le32 len; - __le32 offset; -} __attribute__ ((packed)); - -struct rndis_set { /* OUT */ - // header and: - __le32 msg_type; /* RNDIS_MSG_SET */ - __le32 msg_len; - __le32 request_id; - __le32 oid; - __le32 len; - __le32 offset; -/*?*/ __le32 handle; // zero -} __attribute__ ((packed)); - -struct rndis_set_c { /* IN */ - // header and: - __le32 msg_type; /* RNDIS_MSG_SET_C */ - __le32 msg_len; - __le32 request_id; - __le32 status; -} __attribute__ ((packed)); - -struct rndis_reset { /* IN */ - // header and: - __le32 msg_type; /* RNDIS_MSG_RESET */ - __le32 msg_len; - __le32 reserved; -} __attribute__ ((packed)); - -struct rndis_reset_c { /* OUT */ - // header and: - __le32 msg_type; /* RNDIS_MSG_RESET_C */ - __le32 msg_len; - __le32 status; - __le32 addressing_lost; -} __attribute__ ((packed)); - -struct rndis_indicate { /* IN (unrequested) */ - // header and: - __le32 msg_type; /* RNDIS_MSG_INDICATE */ - __le32 msg_len; - __le32 status; - __le32 length; - __le32 offset; -/**/ __le32 diag_status; - __le32 error_offset; -/**/ __le32 message; -} __attribute__ ((packed)); - -struct rndis_keepalive { /* OUT (optionally IN) */ - // header and: - __le32 msg_type; /* RNDIS_MSG_KEEPALIVE */ - __le32 msg_len; - __le32 request_id; -} __attribute__ ((packed)); - -struct rndis_keepalive_c { /* IN (optionally OUT) */ - // header and: - __le32 msg_type; /* RNDIS_MSG_KEEPALIVE_C */ - __le32 msg_len; - __le32 request_id; - __le32 status; -} __attribute__ ((packed)); - -/* NOTE: about 30 OIDs are "mandatory" for peripherals to support ... and - * there are gobs more that may optionally be supported. We'll avoid as much - * of that mess as possible. - */ -#define OID_802_3_PERMANENT_ADDRESS ccpu2(0x01010101) -#define OID_GEN_CURRENT_PACKET_FILTER ccpu2(0x0001010e) - -/* - * RNDIS notifications from device: command completion; "reverse" - * keepalives; etc - */ -static void rndis_status(struct usbnet *dev, struct urb *urb) -{ - devdbg(dev, "rndis status urb, len %d stat %d", - urb->actual_length, urb->status); - // FIXME for keepalives, respond immediately (asynchronously) - // if not an RNDIS status, do like cdc_status(dev,urb) does -} - -/* - * RPC done RNDIS-style. Caller guarantees: - * - message is properly byteswapped - * - there's no other request pending - * - buf can hold up to 1KB response (required by RNDIS spec) - * On return, the first few entries are already byteswapped. - * - * Call context is likely probe(), before interface name is known, - * which is why we won't try to use it in the diagnostics. - */ -static int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) -{ - struct cdc_state *info = (void *) &dev->data; - int retval; - unsigned count; - __le32 rsp; - u32 xid = 0, msg_len, request_id; - - /* REVISIT when this gets called from contexts other than probe() or - * disconnect(): either serialize, or dispatch responses on xid - */ - - /* Issue the request; don't bother byteswapping our xid */ - if (likely(buf->msg_type != RNDIS_MSG_HALT - && buf->msg_type != RNDIS_MSG_RESET)) { - xid = dev->xid++; - if (!xid) - xid = dev->xid++; - buf->request_id = (__force __le32) xid; - } - retval = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - USB_CDC_SEND_ENCAPSULATED_COMMAND, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, info->u->bMasterInterface0, - buf, le32_to_cpu(buf->msg_len), - RNDIS_CONTROL_TIMEOUT_MS); - if (unlikely(retval < 0 || xid == 0)) - return retval; - - // FIXME Seems like some devices discard responses when - // we time out and cancel our "get response" requests... - // so, this is fragile. Probably need to poll for status. - - /* ignore status endpoint, just poll the control channel; - * the request probably completed immediately - */ - rsp = buf->msg_type | RNDIS_MSG_COMPLETION; - for (count = 0; count < 10; count++) { - memset(buf, 0, 1024); - retval = usb_control_msg(dev->udev, - usb_rcvctrlpipe(dev->udev, 0), - USB_CDC_GET_ENCAPSULATED_RESPONSE, - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, info->u->bMasterInterface0, - buf, 1024, - RNDIS_CONTROL_TIMEOUT_MS); - if (likely(retval >= 8)) { - msg_len = le32_to_cpu(buf->msg_len); - request_id = (__force u32) buf->request_id; - if (likely(buf->msg_type == rsp)) { - if (likely(request_id == xid)) { - if (unlikely(rsp == RNDIS_MSG_RESET_C)) - return 0; - if (likely(RNDIS_STATUS_SUCCESS - == buf->status)) - return 0; - dev_dbg(&info->control->dev, - "rndis reply status %08x\n", - le32_to_cpu(buf->status)); - return -EL3RST; - } - dev_dbg(&info->control->dev, - "rndis reply id %d expected %d\n", - request_id, xid); - /* then likely retry */ - } else switch (buf->msg_type) { - case RNDIS_MSG_INDICATE: { /* fault */ - // struct rndis_indicate *msg = (void *)buf; - dev_info(&info->control->dev, - "rndis fault indication\n"); - } - break; - case RNDIS_MSG_KEEPALIVE: { /* ping */ - struct rndis_keepalive_c *msg = (void *)buf; - - msg->msg_type = RNDIS_MSG_KEEPALIVE_C; - msg->msg_len = ccpu2(sizeof *msg); - msg->status = RNDIS_STATUS_SUCCESS; - retval = usb_control_msg(dev->udev, - usb_sndctrlpipe(dev->udev, 0), - USB_CDC_SEND_ENCAPSULATED_COMMAND, - USB_TYPE_CLASS | USB_RECIP_INTERFACE, - 0, info->u->bMasterInterface0, - msg, sizeof *msg, - RNDIS_CONTROL_TIMEOUT_MS); - if (unlikely(retval < 0)) - dev_dbg(&info->control->dev, - "rndis keepalive err %d\n", - retval); - } - break; - default: - dev_dbg(&info->control->dev, - "unexpected rndis msg %08x len %d\n", - le32_to_cpu(buf->msg_type), msg_len); - } - } else { - /* device probably issued a protocol stall; ignore */ - dev_dbg(&info->control->dev, - "rndis response error, code %d\n", retval); - } - msleep(2); - } - dev_dbg(&info->control->dev, "rndis response timeout\n"); - return -ETIMEDOUT; -} - -static int rndis_bind(struct usbnet *dev, struct usb_interface *intf) -{ - int retval; - struct net_device *net = dev->net; - union { - void *buf; - struct rndis_msg_hdr *header; - struct rndis_init *init; - struct rndis_init_c *init_c; - struct rndis_query *get; - struct rndis_query_c *get_c; - struct rndis_set *set; - struct rndis_set_c *set_c; - } u; - u32 tmp; - - /* we can't rely on i/o from stack working, or stack allocation */ - u.buf = kmalloc(1024, GFP_KERNEL); - if (!u.buf) - return -ENOMEM; - retval = usbnet_generic_cdc_bind(dev, intf); - if (retval < 0) - goto done; - - net->hard_header_len += sizeof (struct rndis_data_hdr); - - /* initialize; max transfer is 16KB at full speed */ - u.init->msg_type = RNDIS_MSG_INIT; - u.init->msg_len = ccpu2(sizeof *u.init); - u.init->major_version = ccpu2(1); - u.init->minor_version = ccpu2(0); - u.init->max_transfer_size = ccpu2(net->mtu + net->hard_header_len); - - retval = rndis_command(dev, u.header); - if (unlikely(retval < 0)) { - /* it might not even be an RNDIS device!! */ - dev_err(&intf->dev, "RNDIS init failed, %d\n", retval); -fail: - usb_driver_release_interface(driver_of(intf), - ((struct cdc_state *)&(dev->data))->data); - goto done; - } - dev->hard_mtu = le32_to_cpu(u.init_c->max_transfer_size); - /* REVISIT: peripheral "alignment" request is ignored ... */ - dev_dbg(&intf->dev, "hard mtu %u, align %d\n", dev->hard_mtu, - 1 << le32_to_cpu(u.init_c->packet_alignment)); - - /* get designated host ethernet address */ - memset(u.get, 0, sizeof *u.get); - u.get->msg_type = RNDIS_MSG_QUERY; - u.get->msg_len = ccpu2(sizeof *u.get); - u.get->oid = OID_802_3_PERMANENT_ADDRESS; - - retval = rndis_command(dev, u.header); - if (unlikely(retval < 0)) { - dev_err(&intf->dev, "rndis get ethaddr, %d\n", retval); - goto fail; - } - tmp = le32_to_cpu(u.get_c->offset); - if (unlikely((tmp + 8) > (1024 - ETH_ALEN) - || u.get_c->len != ccpu2(ETH_ALEN))) { - dev_err(&intf->dev, "rndis ethaddr off %d len %d ?\n", - tmp, le32_to_cpu(u.get_c->len)); - retval = -EDOM; - goto fail; - } - memcpy(net->dev_addr, tmp + (char *)&u.get_c->request_id, ETH_ALEN); - - /* set a nonzero filter to enable data transfers */ - memset(u.set, 0, sizeof *u.set); - u.set->msg_type = RNDIS_MSG_SET; - u.set->msg_len = ccpu2(4 + sizeof *u.set); - u.set->oid = OID_GEN_CURRENT_PACKET_FILTER; - u.set->len = ccpu2(4); - u.set->offset = ccpu2((sizeof *u.set) - 8); - *(__le32 *)(u.buf + sizeof *u.set) = ccpu2(DEFAULT_FILTER); - - retval = rndis_command(dev, u.header); - if (unlikely(retval < 0)) { - dev_err(&intf->dev, "rndis set packet filter, %d\n", retval); - goto fail; - } - - retval = 0; -done: - kfree(u.buf); - return retval; -} - -static void rndis_unbind(struct usbnet *dev, struct usb_interface *intf) -{ - struct rndis_halt *halt; - - /* try to clear any rndis state/activity (no i/o from stack!) */ - halt = kcalloc(1, sizeof *halt, SLAB_KERNEL); - if (halt) { - halt->msg_type = RNDIS_MSG_HALT; - halt->msg_len = ccpu2(sizeof *halt); - (void) rndis_command(dev, (void *)halt); - kfree(halt); - } - - return usbnet_cdc_unbind(dev, intf); -} - -/* - * DATA -- host must not write zlps - */ -static int rndis_rx_fixup(struct usbnet *dev, struct sk_buff *skb) -{ - /* peripheral may have batched packets to us... */ - while (likely(skb->len)) { - struct rndis_data_hdr *hdr = (void *)skb->data; - struct sk_buff *skb2; - u32 msg_len, data_offset, data_len; - - msg_len = le32_to_cpu(hdr->msg_len); - data_offset = le32_to_cpu(hdr->data_offset); - data_len = le32_to_cpu(hdr->data_len); - - /* don't choke if we see oob, per-packet data, etc */ - if (unlikely(hdr->msg_type != RNDIS_MSG_PACKET - || skb->len < msg_len - || (data_offset + data_len + 8) > msg_len)) { - dev->stats.rx_frame_errors++; - devdbg(dev, "bad rndis message %d/%d/%d/%d, len %d", - le32_to_cpu(hdr->msg_type), - msg_len, data_offset, data_len, skb->len); - return 0; - } - skb_pull(skb, 8 + data_offset); - - /* at most one packet left? */ - if (likely((data_len - skb->len) <= sizeof *hdr)) { - skb_trim(skb, data_len); - break; - } - - /* try to return all the packets in the batch */ - skb2 = skb_clone(skb, GFP_ATOMIC); - if (unlikely(!skb2)) - break; - skb_pull(skb, msg_len - sizeof *hdr); - skb_trim(skb2, data_len); - usbnet_skb_return(dev, skb2); - } - - /* caller will usbnet_skb_return the remaining packet */ - return 1; -} - -static struct sk_buff * -rndis_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) -{ - struct rndis_data_hdr *hdr; - struct sk_buff *skb2; - unsigned len = skb->len; - - if (likely(!skb_cloned(skb))) { - int room = skb_headroom(skb); - - /* enough head room as-is? */ - if (unlikely((sizeof *hdr) <= room)) - goto fill; - - /* enough room, but needs to be readjusted? */ - room += skb_tailroom(skb); - if (likely((sizeof *hdr) <= room)) { - skb->data = memmove(skb->head + sizeof *hdr, - skb->data, len); - skb->tail = skb->data + len; - goto fill; - } - } - - /* create a new skb, with the correct size (and tailpad) */ - skb2 = skb_copy_expand(skb, sizeof *hdr, 1, flags); - dev_kfree_skb_any(skb); - if (unlikely(!skb2)) - return skb2; - skb = skb2; - - /* fill out the RNDIS header. we won't bother trying to batch - * packets; Linux minimizes wasted bandwidth through tx queues. - */ -fill: - hdr = (void *) __skb_push(skb, sizeof *hdr); - memset(hdr, 0, sizeof *hdr); - hdr->msg_type = RNDIS_MSG_PACKET; - hdr->msg_len = cpu_to_le32(skb->len); - hdr->data_offset = ccpu2(sizeof(*hdr) - 8); - hdr->data_len = cpu_to_le32(len); - - /* FIXME make the last packet always be short ... */ - return skb; -} - - -static const struct driver_info rndis_info = { - .description = "RNDIS device", - .flags = FLAG_ETHER | FLAG_FRAMING_RN, - .bind = rndis_bind, - .unbind = rndis_unbind, - .status = rndis_status, - .rx_fixup = rndis_rx_fixup, - .tx_fixup = rndis_tx_fixup, -}; - -#undef ccpu2 - - -/*-------------------------------------------------------------------------*/ - -static const struct usb_device_id products [] = { -{ - /* RNDIS is MSFT's un-official variant of CDC ACM */ - USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), - .driver_info = (unsigned long) &rndis_info, -}, - { }, // END -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver rndis_driver = { - .owner = THIS_MODULE, - .name = "rndis_host", - .id_table = products, - .probe = usbnet_probe, - .disconnect = usbnet_disconnect, - .suspend = usbnet_suspend, - .resume = usbnet_resume, -}; - -static int __init rndis_init(void) -{ - return usb_register(&rndis_driver); -} -module_init(rndis_init); - -static void __exit rndis_exit(void) -{ - usb_deregister(&rndis_driver); -} -module_exit(rndis_exit); - -MODULE_AUTHOR("David Brownell"); -MODULE_DESCRIPTION("USB Host side RNDIS driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c deleted file mode 100644 index 787dd3591d6..00000000000 --- a/drivers/usb/net/rtl8150.c +++ /dev/null @@ -1,940 +0,0 @@ -/* - * Copyright (c) 2002 Petko Manolov (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 - * version 2 as published by the Free Software Foundation. - */ - -#include <linux/config.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/signal.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/mii.h> -#include <linux/ethtool.h> -#include <linux/usb.h> -#include <asm/uaccess.h> - -/* Version Information */ -#define DRIVER_VERSION "v0.6.2 (2004/08/27)" -#define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>" -#define DRIVER_DESC "rtl8150 based usb-ethernet driver" - -#define IDR 0x0120 -#define MAR 0x0126 -#define CR 0x012e -#define TCR 0x012f -#define RCR 0x0130 -#define TSR 0x0132 -#define RSR 0x0133 -#define CON0 0x0135 -#define CON1 0x0136 -#define MSR 0x0137 -#define PHYADD 0x0138 -#define PHYDAT 0x0139 -#define PHYCNT 0x013b -#define GPPC 0x013d -#define BMCR 0x0140 -#define BMSR 0x0142 -#define ANAR 0x0144 -#define ANLP 0x0146 -#define AER 0x0148 -#define CSCR 0x014C /* This one has the link status */ -#define CSCR_LINK_STATUS (1 << 3) - -#define IDR_EEPROM 0x1202 - -#define PHY_READ 0 -#define PHY_WRITE 0x20 -#define PHY_GO 0x40 - -#define MII_TIMEOUT 10 -#define INTBUFSIZE 8 - -#define RTL8150_REQT_READ 0xc0 -#define RTL8150_REQT_WRITE 0x40 -#define RTL8150_REQ_GET_REGS 0x05 -#define RTL8150_REQ_SET_REGS 0x05 - - -/* Transmit status register errors */ -#define TSR_ECOL (1<<5) -#define TSR_LCOL (1<<4) -#define TSR_LOSS_CRS (1<<3) -#define TSR_JBR (1<<2) -#define TSR_ERRORS (TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR) -/* Receive status register errors */ -#define RSR_CRC (1<<2) -#define RSR_FAE (1<<1) -#define RSR_ERRORS (RSR_CRC | RSR_FAE) - -/* Media status register definitions */ -#define MSR_DUPLEX (1<<4) -#define MSR_SPEED (1<<3) -#define MSR_LINK (1<<2) - -/* Interrupt pipe data */ -#define INT_TSR 0x00 -#define INT_RSR 0x01 -#define INT_MSR 0x02 -#define INT_WAKSR 0x03 -#define INT_TXOK_CNT 0x04 -#define INT_RXLOST_CNT 0x05 -#define INT_CRERR_CNT 0x06 -#define INT_COL_CNT 0x07 - -/* Transmit status register errors */ -#define TSR_ECOL (1<<5) -#define TSR_LCOL (1<<4) -#define TSR_LOSS_CRS (1<<3) -#define TSR_JBR (1<<2) -#define TSR_ERRORS (TSR_ECOL | TSR_LCOL | TSR_LOSS_CRS | TSR_JBR) -/* Receive status register errors */ -#define RSR_CRC (1<<2) -#define RSR_FAE (1<<1) -#define RSR_ERRORS (RSR_CRC | RSR_FAE) - -/* Media status register definitions */ -#define MSR_DUPLEX (1<<4) -#define MSR_SPEED (1<<3) -#define MSR_LINK (1<<2) - -/* Interrupt pipe data */ -#define INT_TSR 0x00 -#define INT_RSR 0x01 -#define INT_MSR 0x02 -#define INT_WAKSR 0x03 -#define INT_TXOK_CNT 0x04 -#define INT_RXLOST_CNT 0x05 -#define INT_CRERR_CNT 0x06 -#define INT_COL_CNT 0x07 - - -#define RTL8150_MTU 1540 -#define RTL8150_TX_TIMEOUT (HZ) -#define RX_SKB_POOL_SIZE 4 - -/* rtl8150 flags */ -#define RTL8150_HW_CRC 0 -#define RX_REG_SET 1 -#define RTL8150_UNPLUG 2 -#define RX_URB_FAIL 3 - -/* Define these values to match your device */ -#define VENDOR_ID_REALTEK 0x0bda -#define VENDOR_ID_MELCO 0x0411 -#define VENDOR_ID_MICRONET 0x3980 -#define VENDOR_ID_LONGSHINE 0x07b8 - -#define PRODUCT_ID_RTL8150 0x8150 -#define PRODUCT_ID_LUAKTX 0x0012 -#define PRODUCT_ID_LCS8138TX 0x401a -#define PRODUCT_ID_SP128AR 0x0003 - -#undef EEPROM_WRITE - -/* table of devices that work with this driver */ -static struct usb_device_id rtl8150_table[] = { - {USB_DEVICE(VENDOR_ID_REALTEK, PRODUCT_ID_RTL8150)}, - {USB_DEVICE(VENDOR_ID_MELCO, PRODUCT_ID_LUAKTX)}, - {USB_DEVICE(VENDOR_ID_MICRONET, PRODUCT_ID_SP128AR)}, - {USB_DEVICE(VENDOR_ID_LONGSHINE, PRODUCT_ID_LCS8138TX)}, - {} -}; - -MODULE_DEVICE_TABLE(usb, rtl8150_table); - -struct rtl8150 { - unsigned long flags; - struct usb_device *udev; - struct tasklet_struct tl; - struct net_device_stats stats; - struct net_device *netdev; - struct urb *rx_urb, *tx_urb, *intr_urb, *ctrl_urb; - struct sk_buff *tx_skb, *rx_skb; - struct sk_buff *rx_skb_pool[RX_SKB_POOL_SIZE]; - spinlock_t rx_pool_lock; - struct usb_ctrlrequest dr; - int intr_interval; - __le16 rx_creg; - u8 *intr_buff; - u8 phy; -}; - -typedef struct rtl8150 rtl8150_t; - -static void fill_skb_pool(rtl8150_t *); -static void free_skb_pool(rtl8150_t *); -static inline struct sk_buff *pull_skb(rtl8150_t *); -static void rtl8150_disconnect(struct usb_interface *intf); -static int rtl8150_probe(struct usb_interface *intf, - const struct usb_device_id *id); - -static const char driver_name [] = "rtl8150"; - -static struct usb_driver rtl8150_driver = { - .owner = THIS_MODULE, - .name = driver_name, - .probe = rtl8150_probe, - .disconnect = rtl8150_disconnect, - .id_table = rtl8150_table, -}; - -/* -** -** device related part of the code -** -*/ -static int get_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) -{ - return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), - RTL8150_REQ_GET_REGS, RTL8150_REQT_READ, - indx, 0, data, size, 500); -} - -static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data) -{ - return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), - RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE, - indx, 0, data, size, 500); -} - -static void ctrl_callback(struct urb *urb, struct pt_regs *regs) -{ - rtl8150_t *dev; - - switch (urb->status) { - case 0: - break; - case -EINPROGRESS: - break; - case -ENOENT: - break; - default: - warn("ctrl urb status %d", urb->status); - } - dev = urb->context; - clear_bit(RX_REG_SET, &dev->flags); -} - -static int async_set_registers(rtl8150_t * dev, u16 indx, u16 size) -{ - int ret; - - if (test_bit(RX_REG_SET, &dev->flags)) - return -EAGAIN; - - dev->dr.bRequestType = RTL8150_REQT_WRITE; - dev->dr.bRequest = RTL8150_REQ_SET_REGS; - dev->dr.wValue = cpu_to_le16(indx); - dev->dr.wIndex = 0; - dev->dr.wLength = cpu_to_le16(size); - dev->ctrl_urb->transfer_buffer_length = size; - usb_fill_control_urb(dev->ctrl_urb, dev->udev, - usb_sndctrlpipe(dev->udev, 0), (char *) &dev->dr, - &dev->rx_creg, size, ctrl_callback, dev); - if ((ret = usb_submit_urb(dev->ctrl_urb, GFP_ATOMIC))) - err("control request submission failed: %d", ret); - else - set_bit(RX_REG_SET, &dev->flags); - - return ret; -} - -static int read_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 * reg) -{ - int i; - u8 data[3], tmp; - - data[0] = phy; - data[1] = data[2] = 0; - tmp = indx | PHY_READ | PHY_GO; - i = 0; - - set_registers(dev, PHYADD, sizeof(data), data); - set_registers(dev, PHYCNT, 1, &tmp); - do { - get_registers(dev, PHYCNT, 1, data); - } while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT)); - - if (i < MII_TIMEOUT) { - get_registers(dev, PHYDAT, 2, data); - *reg = data[0] | (data[1] << 8); - return 0; - } else - return 1; -} - -static int write_mii_word(rtl8150_t * dev, u8 phy, __u8 indx, u16 reg) -{ - int i; - u8 data[3], tmp; - - data[0] = phy; - *(data + 1) = cpu_to_le16p(®); - tmp = indx | PHY_WRITE | PHY_GO; - i = 0; - - set_registers(dev, PHYADD, sizeof(data), data); - set_registers(dev, PHYCNT, 1, &tmp); - do { - get_registers(dev, PHYCNT, 1, data); - } while ((data[0] & PHY_GO) && (i++ < MII_TIMEOUT)); - - if (i < MII_TIMEOUT) - return 0; - else - return 1; -} - -static inline void set_ethernet_addr(rtl8150_t * dev) -{ - u8 node_id[6]; - - get_registers(dev, IDR, sizeof(node_id), node_id); - memcpy(dev->netdev->dev_addr, node_id, sizeof(node_id)); -} - -static int rtl8150_set_mac_address(struct net_device *netdev, void *p) -{ - struct sockaddr *addr = p; - rtl8150_t *dev = netdev_priv(netdev); - int i; - - if (netif_running(netdev)) - return -EBUSY; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - dbg("%s: Setting MAC address to ", netdev->name); - for (i = 0; i < 5; i++) - dbg("%02X:", netdev->dev_addr[i]); - dbg("%02X\n", netdev->dev_addr[i]); - /* Set the IDR registers. */ - set_registers(dev, IDR, sizeof(netdev->dev_addr), netdev->dev_addr); -#ifdef EEPROM_WRITE - { - u8 cr; - /* Get the CR contents. */ - get_registers(dev, CR, 1, &cr); - /* Set the WEPROM bit (eeprom write enable). */ - cr |= 0x20; - set_registers(dev, CR, 1, &cr); - /* Write the MAC address into eeprom. Eeprom writes must be word-sized, - so we need to split them up. */ - for (i = 0; i * 2 < netdev->addr_len; i++) { - set_registers(dev, IDR_EEPROM + (i * 2), 2, - netdev->dev_addr + (i * 2)); - } - /* Clear the WEPROM bit (preventing accidental eeprom writes). */ - cr &= 0xdf; - set_registers(dev, CR, 1, &cr); - } -#endif - return 0; -} - -static int rtl8150_reset(rtl8150_t * dev) -{ - u8 data = 0x10; - int i = HZ; - - set_registers(dev, CR, 1, &data); - do { - get_registers(dev, CR, 1, &data); - } while ((data & 0x10) && --i); - - return (i > 0) ? 1 : 0; -} - -static int alloc_all_urbs(rtl8150_t * dev) -{ - dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->rx_urb) - return 0; - dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->tx_urb) { - usb_free_urb(dev->rx_urb); - return 0; - } - dev->intr_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->intr_urb) { - usb_free_urb(dev->rx_urb); - usb_free_urb(dev->tx_urb); - return 0; - } - dev->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->intr_urb) { - usb_free_urb(dev->rx_urb); - usb_free_urb(dev->tx_urb); - usb_free_urb(dev->intr_urb); - return 0; - } - - return 1; -} - -static void free_all_urbs(rtl8150_t * dev) -{ - usb_free_urb(dev->rx_urb); - usb_free_urb(dev->tx_urb); - usb_free_urb(dev->intr_urb); - usb_free_urb(dev->ctrl_urb); -} - -static void unlink_all_urbs(rtl8150_t * dev) -{ - usb_kill_urb(dev->rx_urb); - usb_kill_urb(dev->tx_urb); - usb_kill_urb(dev->intr_urb); - usb_kill_urb(dev->ctrl_urb); -} - -static inline struct sk_buff *pull_skb(rtl8150_t *dev) -{ - struct sk_buff *skb; - int i; - - for (i = 0; i < RX_SKB_POOL_SIZE; i++) { - if (dev->rx_skb_pool[i]) { - skb = dev->rx_skb_pool[i]; - dev->rx_skb_pool[i] = NULL; - return skb; - } - } - return NULL; -} - -static void read_bulk_callback(struct urb *urb, struct pt_regs *regs) -{ - rtl8150_t *dev; - unsigned pkt_len, res; - struct sk_buff *skb; - struct net_device *netdev; - u16 rx_stat; - - dev = urb->context; - if (!dev) - return; - if (test_bit(RTL8150_UNPLUG, &dev->flags)) - return; - netdev = dev->netdev; - if (!netif_device_present(netdev)) - return; - - switch (urb->status) { - case 0: - break; - case -ENOENT: - return; /* the urb is in unlink state */ - case -ETIMEDOUT: - warn("may be reset is needed?.."); - goto goon; - default: - warn("Rx status %d", urb->status); - goto goon; - } - - if (!dev->rx_skb) - goto resched; - /* protect against short packets (tell me why we got some?!?) */ - if (urb->actual_length < 4) - goto goon; - - res = urb->actual_length; - rx_stat = le16_to_cpu(*(__le16 *)(urb->transfer_buffer + res - 4)); - pkt_len = res - 4; - - skb_put(dev->rx_skb, pkt_len); - dev->rx_skb->protocol = eth_type_trans(dev->rx_skb, netdev); - netif_rx(dev->rx_skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; - - spin_lock(&dev->rx_pool_lock); - skb = pull_skb(dev); - spin_unlock(&dev->rx_pool_lock); - if (!skb) - goto resched; - - dev->rx_skb = skb; -goon: - usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), - dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { - set_bit(RX_URB_FAIL, &dev->flags); - goto resched; - } else { - clear_bit(RX_URB_FAIL, &dev->flags); - } - - return; -resched: - tasklet_schedule(&dev->tl); -} - -static void rx_fixup(unsigned long data) -{ - rtl8150_t *dev; - struct sk_buff *skb; - - dev = (rtl8150_t *)data; - - spin_lock_irq(&dev->rx_pool_lock); - fill_skb_pool(dev); - spin_unlock_irq(&dev->rx_pool_lock); - if (test_bit(RX_URB_FAIL, &dev->flags)) - if (dev->rx_skb) - goto try_again; - spin_lock_irq(&dev->rx_pool_lock); - skb = pull_skb(dev); - spin_unlock_irq(&dev->rx_pool_lock); - if (skb == NULL) - goto tlsched; - dev->rx_skb = skb; - usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), - dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); -try_again: - if (usb_submit_urb(dev->rx_urb, GFP_ATOMIC)) { - set_bit(RX_URB_FAIL, &dev->flags); - goto tlsched; - } else { - clear_bit(RX_URB_FAIL, &dev->flags); - } - - return; -tlsched: - tasklet_schedule(&dev->tl); -} - -static void write_bulk_callback(struct urb *urb, struct pt_regs *regs) -{ - rtl8150_t *dev; - - dev = urb->context; - if (!dev) - return; - dev_kfree_skb_irq(dev->tx_skb); - if (!netif_device_present(dev->netdev)) - return; - if (urb->status) - info("%s: Tx status %d", dev->netdev->name, urb->status); - dev->netdev->trans_start = jiffies; - netif_wake_queue(dev->netdev); -} - -static void intr_callback(struct urb *urb, struct pt_regs *regs) -{ - rtl8150_t *dev; - __u8 *d; - int status; - - dev = urb->context; - if (!dev) - return; - switch (urb->status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: - info("%s: intr status %d", dev->netdev->name, urb->status); - goto resubmit; - } - - d = urb->transfer_buffer; - if (d[0] & TSR_ERRORS) { - dev->stats.tx_errors++; - if (d[INT_TSR] & (TSR_ECOL | TSR_JBR)) - dev->stats.tx_aborted_errors++; - if (d[INT_TSR] & TSR_LCOL) - dev->stats.tx_window_errors++; - if (d[INT_TSR] & TSR_LOSS_CRS) - dev->stats.tx_carrier_errors++; - } - /* Report link status changes to the network stack */ - if ((d[INT_MSR] & MSR_LINK) == 0) { - if (netif_carrier_ok(dev->netdev)) { - netif_carrier_off(dev->netdev); - dbg("%s: LINK LOST\n", __func__); - } - } else { - if (!netif_carrier_ok(dev->netdev)) { - netif_carrier_on(dev->netdev); - dbg("%s: LINK CAME BACK\n", __func__); - } - } - -resubmit: - status = usb_submit_urb (urb, SLAB_ATOMIC); - if (status) - err ("can't resubmit intr, %s-%s/input0, status %d", - dev->udev->bus->bus_name, - dev->udev->devpath, status); -} - - -/* -** -** network related part of the code -** -*/ - -static void fill_skb_pool(rtl8150_t *dev) -{ - struct sk_buff *skb; - int i; - - for (i = 0; i < RX_SKB_POOL_SIZE; i++) { - if (dev->rx_skb_pool[i]) - continue; - skb = dev_alloc_skb(RTL8150_MTU + 2); - if (!skb) { - return; - } - skb->dev = dev->netdev; - skb_reserve(skb, 2); - dev->rx_skb_pool[i] = skb; - } -} - -static void free_skb_pool(rtl8150_t *dev) -{ - int i; - - for (i = 0; i < RX_SKB_POOL_SIZE; i++) - if (dev->rx_skb_pool[i]) - dev_kfree_skb(dev->rx_skb_pool[i]); -} - -static int enable_net_traffic(rtl8150_t * dev) -{ - u8 cr, tcr, rcr, msr; - - if (!rtl8150_reset(dev)) { - warn("%s - device reset failed", __FUNCTION__); - } - /* RCR bit7=1 attach Rx info at the end; =0 HW CRC (which is broken) */ - rcr = 0x9e; - dev->rx_creg = cpu_to_le16(rcr); - tcr = 0xd8; - cr = 0x0c; - if (!(rcr & 0x80)) - set_bit(RTL8150_HW_CRC, &dev->flags); - set_registers(dev, RCR, 1, &rcr); - set_registers(dev, TCR, 1, &tcr); - set_registers(dev, CR, 1, &cr); - get_registers(dev, MSR, 1, &msr); - - return 0; -} - -static void disable_net_traffic(rtl8150_t * dev) -{ - u8 cr; - - get_registers(dev, CR, 1, &cr); - cr &= 0xf3; - set_registers(dev, CR, 1, &cr); -} - -static struct net_device_stats *rtl8150_netdev_stats(struct net_device *dev) -{ - return &((rtl8150_t *)netdev_priv(dev))->stats; -} - -static void rtl8150_tx_timeout(struct net_device *netdev) -{ - rtl8150_t *dev = netdev_priv(netdev); - warn("%s: Tx timeout.", netdev->name); - usb_unlink_urb(dev->tx_urb); - dev->stats.tx_errors++; -} - -static void rtl8150_set_multicast(struct net_device *netdev) -{ - rtl8150_t *dev = netdev_priv(netdev); - netif_stop_queue(netdev); - if (netdev->flags & IFF_PROMISC) { - dev->rx_creg |= cpu_to_le16(0x0001); - info("%s: promiscuous mode", netdev->name); - } else if (netdev->mc_count || - (netdev->flags & IFF_ALLMULTI)) { - dev->rx_creg &= cpu_to_le16(0xfffe); - dev->rx_creg |= cpu_to_le16(0x0002); - info("%s: allmulti set", netdev->name); - } else { - /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ - dev->rx_creg &= cpu_to_le16(0x00fc); - } - async_set_registers(dev, RCR, 2); - netif_wake_queue(netdev); -} - -static int rtl8150_start_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - rtl8150_t *dev = netdev_priv(netdev); - int count, res; - - netif_stop_queue(netdev); - count = (skb->len < 60) ? 60 : skb->len; - count = (count & 0x3f) ? count : count + 1; - dev->tx_skb = skb; - usb_fill_bulk_urb(dev->tx_urb, dev->udev, usb_sndbulkpipe(dev->udev, 2), - skb->data, count, write_bulk_callback, dev); - if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) { - warn("failed tx_urb %d\n", res); - dev->stats.tx_errors++; - netif_start_queue(netdev); - } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - netdev->trans_start = jiffies; - } - - return 0; -} - - -static void set_carrier(struct net_device *netdev) -{ - rtl8150_t *dev = netdev_priv(netdev); - short tmp; - - get_registers(dev, CSCR, 2, &tmp); - if (tmp & CSCR_LINK_STATUS) - netif_carrier_on(netdev); - else - netif_carrier_off(netdev); -} - -static int rtl8150_open(struct net_device *netdev) -{ - rtl8150_t *dev = netdev_priv(netdev); - int res; - - if (dev->rx_skb == NULL) - dev->rx_skb = pull_skb(dev); - if (!dev->rx_skb) - return -ENOMEM; - - set_registers(dev, IDR, 6, netdev->dev_addr); - - usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1), - dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev); - if ((res = usb_submit_urb(dev->rx_urb, GFP_KERNEL))) - warn("%s: rx_urb submit failed: %d", __FUNCTION__, res); - usb_fill_int_urb(dev->intr_urb, dev->udev, usb_rcvintpipe(dev->udev, 3), - dev->intr_buff, INTBUFSIZE, intr_callback, - dev, dev->intr_interval); - if ((res = usb_submit_urb(dev->intr_urb, GFP_KERNEL))) - warn("%s: intr_urb submit failed: %d", __FUNCTION__, res); - netif_start_queue(netdev); - enable_net_traffic(dev); - set_carrier(netdev); - - return res; -} - -static int rtl8150_close(struct net_device *netdev) -{ - rtl8150_t *dev = netdev_priv(netdev); - int res = 0; - - netif_stop_queue(netdev); - if (!test_bit(RTL8150_UNPLUG, &dev->flags)) - disable_net_traffic(dev); - unlink_all_urbs(dev); - - return res; -} - -static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) -{ - rtl8150_t *dev = netdev_priv(netdev); - - strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN); - strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN); - usb_make_path(dev->udev, info->bus_info, sizeof info->bus_info); -} - -static int rtl8150_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -{ - rtl8150_t *dev = netdev_priv(netdev); - short lpa, bmcr; - - 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 = dev->phy; - get_registers(dev, BMCR, 2, &bmcr); - get_registers(dev, ANLP, 2, &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; - } - return 0; -} - -static struct ethtool_ops ops = { - .get_drvinfo = rtl8150_get_drvinfo, - .get_settings = rtl8150_get_settings, - .get_link = ethtool_op_get_link -}; - -static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) -{ - rtl8150_t *dev = netdev_priv(netdev); - u16 *data = (u16 *) & rq->ifr_ifru; - int res = 0; - - switch (cmd) { - case SIOCDEVPRIVATE: - data[0] = dev->phy; - case SIOCDEVPRIVATE + 1: - read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]); - break; - case SIOCDEVPRIVATE + 2: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - write_mii_word(dev, dev->phy, (data[1] & 0x1f), data[2]); - break; - default: - res = -EOPNOTSUPP; - } - - return res; -} - -static int rtl8150_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - rtl8150_t *dev; - struct net_device *netdev; - - netdev = alloc_etherdev(sizeof(rtl8150_t)); - if (!netdev) { - err("Out of memory"); - return -ENOMEM; - } - - dev = netdev_priv(netdev); - memset(dev, 0, sizeof(rtl8150_t)); - - dev->intr_buff = kmalloc(INTBUFSIZE, GFP_KERNEL); - if (!dev->intr_buff) { - free_netdev(netdev); - return -ENOMEM; - } - - tasklet_init(&dev->tl, rx_fixup, (unsigned long)dev); - spin_lock_init(&dev->rx_pool_lock); - - dev->udev = udev; - dev->netdev = netdev; - SET_MODULE_OWNER(netdev); - netdev->open = rtl8150_open; - netdev->stop = rtl8150_close; - netdev->do_ioctl = rtl8150_ioctl; - netdev->watchdog_timeo = RTL8150_TX_TIMEOUT; - netdev->tx_timeout = rtl8150_tx_timeout; - netdev->hard_start_xmit = rtl8150_start_xmit; - netdev->set_multicast_list = rtl8150_set_multicast; - netdev->set_mac_address = rtl8150_set_mac_address; - netdev->get_stats = rtl8150_netdev_stats; - netdev->mtu = RTL8150_MTU; - SET_ETHTOOL_OPS(netdev, &ops); - dev->intr_interval = 100; /* 100ms */ - - if (!alloc_all_urbs(dev)) { - err("out of memory"); - goto out; - } - if (!rtl8150_reset(dev)) { - err("couldn't reset the device"); - goto out1; - } - fill_skb_pool(dev); - set_ethernet_addr(dev); - info("%s: rtl8150 is detected", netdev->name); - - usb_set_intfdata(intf, dev); - SET_NETDEV_DEV(netdev, &intf->dev); - if (register_netdev(netdev) != 0) { - err("couldn't register the device"); - goto out2; - } - return 0; - -out2: - usb_set_intfdata(intf, NULL); - free_skb_pool(dev); -out1: - free_all_urbs(dev); -out: - kfree(dev->intr_buff); - free_netdev(netdev); - return -EIO; -} - -static void rtl8150_disconnect(struct usb_interface *intf) -{ - rtl8150_t *dev = usb_get_intfdata(intf); - - usb_set_intfdata(intf, NULL); - if (dev) { - set_bit(RTL8150_UNPLUG, &dev->flags); - tasklet_disable(&dev->tl); - unregister_netdev(dev->netdev); - unlink_all_urbs(dev); - free_all_urbs(dev); - free_skb_pool(dev); - if (dev->rx_skb) - dev_kfree_skb(dev->rx_skb); - kfree(dev->intr_buff); - free_netdev(dev->netdev); - } -} - -static int __init usb_rtl8150_init(void) -{ - info(DRIVER_DESC " " DRIVER_VERSION); - return usb_register(&rtl8150_driver); -} - -static void __exit usb_rtl8150_exit(void) -{ - usb_deregister(&rtl8150_driver); -} - -module_init(usb_rtl8150_init); -module_exit(usb_rtl8150_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c deleted file mode 100644 index 74f05c9c84d..00000000000 --- a/drivers/usb/net/usbnet.c +++ /dev/null @@ -1,1223 +0,0 @@ -/* - * USB Network driver infrastructure - * Copyright (C) 2000-2005 by David Brownell - * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com> - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * This is a generic "USB networking" framework that works with several - * kinds of full and high speed networking devices: host-to-host cables, - * smart usb peripherals, and actual Ethernet adapters. - * - * These devices usually differ in terms of control protocols (if they - * even have one!) and sometimes they define new framing to wrap or batch - * Ethernet packets. Otherwise, they talk to USB pretty much the same, - * so interface (un)binding, endpoint I/O queues, fault handling, and other - * issues can usefully be addressed by this framework. - */ - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include <linux/config.h> -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#endif -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/ethtool.h> -#include <linux/workqueue.h> -#include <linux/mii.h> -#include <linux/usb.h> - -#include "usbnet.h" - -#define DRIVER_VERSION "22-Aug-2005" - - -/*-------------------------------------------------------------------------*/ - -/* - * Nineteen USB 1.1 max size bulk transactions per frame (ms), max. - * Several dozen bytes of IPv4 data can fit in two such transactions. - * One maximum size Ethernet packet takes twenty four of them. - * For high speed, each frame comfortably fits almost 36 max size - * Ethernet packets (so queues should be bigger). - * - * REVISIT qlens should be members of 'struct usbnet'; the goal is to - * let the USB host controller be busy for 5msec or more before an irq - * is required, under load. Jumbograms change the equation. - */ -#define RX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4) -#define TX_QLEN(dev) (((dev)->udev->speed == USB_SPEED_HIGH) ? 60 : 4) - -// reawaken network queue this soon after stopping; else watchdog barks -#define TX_TIMEOUT_JIFFIES (5*HZ) - -// throttle rx/tx briefly after some faults, so khubd might disconnect() -// us (it polls at HZ/4 usually) before we report too many false errors. -#define THROTTLE_JIFFIES (HZ/8) - -// between wakeups -#define UNLINK_TIMEOUT_MS 3 - -/*-------------------------------------------------------------------------*/ - -// randomly generated ethernet address -static u8 node_id [ETH_ALEN]; - -static const char driver_name [] = "usbnet"; - -/* use ethtool to change the level for any given device */ -static int msg_level = -1; -module_param (msg_level, int, 0); -MODULE_PARM_DESC (msg_level, "Override default message level"); - -/*-------------------------------------------------------------------------*/ - -/* handles CDC Ethernet and many other network "bulk data" interfaces */ -int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) -{ - int tmp; - struct usb_host_interface *alt = NULL; - struct usb_host_endpoint *in = NULL, *out = NULL; - struct usb_host_endpoint *status = NULL; - - for (tmp = 0; tmp < intf->num_altsetting; tmp++) { - unsigned ep; - - in = out = status = NULL; - alt = intf->altsetting + tmp; - - /* take the first altsetting with in-bulk + out-bulk; - * remember any status endpoint, just in case; - * ignore other endpoints and altsetttings. - */ - for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { - struct usb_host_endpoint *e; - int intr = 0; - - e = alt->endpoint + ep; - switch (e->desc.bmAttributes) { - case USB_ENDPOINT_XFER_INT: - if (!(e->desc.bEndpointAddress & USB_DIR_IN)) - continue; - intr = 1; - /* FALLTHROUGH */ - case USB_ENDPOINT_XFER_BULK: - break; - default: - continue; - } - if (e->desc.bEndpointAddress & USB_DIR_IN) { - if (!intr && !in) - in = e; - else if (intr && !status) - status = e; - } else { - if (!out) - out = e; - } - } - if (in && out) - break; - } - if (!alt || !in || !out) - return -EINVAL; - - if (alt->desc.bAlternateSetting != 0 - || !(dev->driver_info->flags & FLAG_NO_SETINT)) { - tmp = usb_set_interface (dev->udev, alt->desc.bInterfaceNumber, - alt->desc.bAlternateSetting); - if (tmp < 0) - return tmp; - } - - dev->in = usb_rcvbulkpipe (dev->udev, - in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - dev->out = usb_sndbulkpipe (dev->udev, - out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - dev->status = status; - return 0; -} -EXPORT_SYMBOL_GPL(usbnet_get_endpoints); - -static void intr_complete (struct urb *urb, struct pt_regs *regs); - -static int init_status (struct usbnet *dev, struct usb_interface *intf) -{ - char *buf = NULL; - unsigned pipe = 0; - unsigned maxp; - unsigned period; - - if (!dev->driver_info->status) - return 0; - - pipe = usb_rcvintpipe (dev->udev, - dev->status->desc.bEndpointAddress - & USB_ENDPOINT_NUMBER_MASK); - maxp = usb_maxpacket (dev->udev, pipe, 0); - - /* avoid 1 msec chatter: min 8 msec poll rate */ - period = max ((int) dev->status->desc.bInterval, - (dev->udev->speed == USB_SPEED_HIGH) ? 7 : 3); - - buf = kmalloc (maxp, SLAB_KERNEL); - if (buf) { - dev->interrupt = usb_alloc_urb (0, SLAB_KERNEL); - if (!dev->interrupt) { - kfree (buf); - return -ENOMEM; - } else { - usb_fill_int_urb(dev->interrupt, dev->udev, pipe, - buf, maxp, intr_complete, dev, period); - dev_dbg(&intf->dev, - "status ep%din, %d bytes period %d\n", - usb_pipeendpoint(pipe), maxp, period); - } - } - return 0; -} - -/* Passes this packet up the stack, updating its accounting. - * Some link protocols batch packets, so their rx_fixup paths - * can return clones as well as just modify the original skb. - */ -void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb) -{ - int status; - - skb->dev = dev->net; - skb->protocol = eth_type_trans (skb, dev->net); - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - - if (netif_msg_rx_status (dev)) - devdbg (dev, "< rx, len %zu, type 0x%x", - skb->len + sizeof (struct ethhdr), skb->protocol); - memset (skb->cb, 0, sizeof (struct skb_data)); - status = netif_rx (skb); - if (status != NET_RX_SUCCESS && netif_msg_rx_err (dev)) - devdbg (dev, "netif_rx status %d", status); -} -EXPORT_SYMBOL_GPL(usbnet_skb_return); - - -/*------------------------------------------------------------------------- - * - * Network Device Driver (peer link to "Host Device", from USB host) - * - *-------------------------------------------------------------------------*/ - -static int usbnet_change_mtu (struct net_device *net, int new_mtu) -{ - struct usbnet *dev = netdev_priv(net); - int ll_mtu = new_mtu + net->hard_header_len; - - if (new_mtu <= 0 || ll_mtu > dev->hard_mtu) - return -EINVAL; - // no second zero-length packet read wanted after mtu-sized packets - if ((ll_mtu % dev->maxpacket) == 0) - return -EDOM; - net->mtu = new_mtu; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static struct net_device_stats *usbnet_get_stats (struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - return &dev->stats; -} - -/*-------------------------------------------------------------------------*/ - -/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from - * completion callbacks. 2.5 should have fixed those bugs... - */ - -static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list) -{ - unsigned long flags; - - spin_lock_irqsave(&list->lock, flags); - __skb_unlink(skb, list); - spin_unlock(&list->lock); - spin_lock(&dev->done.lock); - __skb_queue_tail(&dev->done, skb); - if (dev->done.qlen == 1) - tasklet_schedule(&dev->bh); - spin_unlock_irqrestore(&dev->done.lock, flags); -} - -/* some work can't be done in tasklets, so we use keventd - * - * NOTE: annoying asymmetry: if it's active, schedule_work() fails, - * but tasklet_schedule() doesn't. hope the failure is rare. - */ -void usbnet_defer_kevent (struct usbnet *dev, int work) -{ - set_bit (work, &dev->flags); - if (!schedule_work (&dev->kevent)) - deverr (dev, "kevent %d may have been dropped", work); - else - devdbg (dev, "kevent %d scheduled", work); -} -EXPORT_SYMBOL_GPL(usbnet_defer_kevent); - -/*-------------------------------------------------------------------------*/ - -static void rx_complete (struct urb *urb, struct pt_regs *regs); - -static void rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) -{ - struct sk_buff *skb; - struct skb_data *entry; - int retval = 0; - unsigned long lockflags; - size_t size = dev->rx_urb_size; - - if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) { - if (netif_msg_rx_err (dev)) - devdbg (dev, "no rx skb"); - usbnet_defer_kevent (dev, EVENT_RX_MEMORY); - usb_free_urb (urb); - return; - } - skb_reserve (skb, NET_IP_ALIGN); - - entry = (struct skb_data *) skb->cb; - entry->urb = urb; - entry->dev = dev; - entry->state = rx_start; - entry->length = 0; - - usb_fill_bulk_urb (urb, dev->udev, dev->in, - skb->data, size, rx_complete, skb); - - spin_lock_irqsave (&dev->rxq.lock, lockflags); - - if (netif_running (dev->net) - && netif_device_present (dev->net) - && !test_bit (EVENT_RX_HALT, &dev->flags)) { - switch (retval = usb_submit_urb (urb, GFP_ATOMIC)){ - case -EPIPE: - usbnet_defer_kevent (dev, EVENT_RX_HALT); - break; - case -ENOMEM: - usbnet_defer_kevent (dev, EVENT_RX_MEMORY); - break; - case -ENODEV: - if (netif_msg_ifdown (dev)) - devdbg (dev, "device gone"); - netif_device_detach (dev->net); - break; - default: - if (netif_msg_rx_err (dev)) - devdbg (dev, "rx submit, %d", retval); - tasklet_schedule (&dev->bh); - break; - case 0: - __skb_queue_tail (&dev->rxq, skb); - } - } else { - if (netif_msg_ifdown (dev)) - devdbg (dev, "rx: stopped"); - retval = -ENOLINK; - } - spin_unlock_irqrestore (&dev->rxq.lock, lockflags); - if (retval) { - dev_kfree_skb_any (skb); - usb_free_urb (urb); - } -} - - -/*-------------------------------------------------------------------------*/ - -static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) -{ - if (dev->driver_info->rx_fixup - && !dev->driver_info->rx_fixup (dev, skb)) - goto error; - // else network stack removes extra byte if we forced a short packet - - if (skb->len) - usbnet_skb_return (dev, skb); - else { - if (netif_msg_rx_err (dev)) - devdbg (dev, "drop"); -error: - dev->stats.rx_errors++; - skb_queue_tail (&dev->done, skb); - } -} - -/*-------------------------------------------------------------------------*/ - -static void rx_complete (struct urb *urb, struct pt_regs *regs) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct skb_data *entry = (struct skb_data *) skb->cb; - struct usbnet *dev = entry->dev; - int urb_status = urb->status; - - skb_put (skb, urb->actual_length); - entry->state = rx_done; - entry->urb = NULL; - - switch (urb_status) { - // success - case 0: - if (skb->len < dev->net->hard_header_len) { - entry->state = rx_cleanup; - dev->stats.rx_errors++; - dev->stats.rx_length_errors++; - if (netif_msg_rx_err (dev)) - devdbg (dev, "rx length %d", skb->len); - } - break; - - // stalls need manual reset. this is rare ... except that - // when going through USB 2.0 TTs, unplug appears this way. - // we avoid the highspeed version of the ETIMEOUT/EILSEQ - // storm, recovering as needed. - case -EPIPE: - dev->stats.rx_errors++; - usbnet_defer_kevent (dev, EVENT_RX_HALT); - // FALLTHROUGH - - // software-driven interface shutdown - case -ECONNRESET: // async unlink - case -ESHUTDOWN: // hardware gone - if (netif_msg_ifdown (dev)) - devdbg (dev, "rx shutdown, code %d", urb_status); - goto block; - - // we get controller i/o faults during khubd disconnect() delays. - // throttle down resubmits, to avoid log floods; just temporarily, - // so we still recover when the fault isn't a khubd delay. - case -EPROTO: // ehci - case -ETIMEDOUT: // ohci - case -EILSEQ: // uhci - dev->stats.rx_errors++; - if (!timer_pending (&dev->delay)) { - mod_timer (&dev->delay, jiffies + THROTTLE_JIFFIES); - if (netif_msg_link (dev)) - devdbg (dev, "rx throttle %d", urb_status); - } -block: - entry->state = rx_cleanup; - entry->urb = urb; - urb = NULL; - break; - - // data overrun ... flush fifo? - case -EOVERFLOW: - dev->stats.rx_over_errors++; - // FALLTHROUGH - - default: - entry->state = rx_cleanup; - dev->stats.rx_errors++; - if (netif_msg_rx_err (dev)) - devdbg (dev, "rx status %d", urb_status); - break; - } - - defer_bh(dev, skb, &dev->rxq); - - if (urb) { - if (netif_running (dev->net) - && !test_bit (EVENT_RX_HALT, &dev->flags)) { - rx_submit (dev, urb, GFP_ATOMIC); - return; - } - usb_free_urb (urb); - } - if (netif_msg_rx_err (dev)) - devdbg (dev, "no read resubmitted"); -} - -static void intr_complete (struct urb *urb, struct pt_regs *regs) -{ - struct usbnet *dev = urb->context; - int status = urb->status; - - switch (status) { - /* success */ - case 0: - dev->driver_info->status(dev, urb); - break; - - /* software-driven interface shutdown */ - case -ENOENT: // urb killed - case -ESHUTDOWN: // hardware gone - if (netif_msg_ifdown (dev)) - devdbg (dev, "intr shutdown, code %d", status); - return; - - /* NOTE: not throttling like RX/TX, since this endpoint - * already polls infrequently - */ - default: - devdbg (dev, "intr status %d", status); - break; - } - - if (!netif_running (dev->net)) - return; - - memset(urb->transfer_buffer, 0, urb->transfer_buffer_length); - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status != 0 && netif_msg_timer (dev)) - deverr(dev, "intr resubmit --> %d", status); -} - -/*-------------------------------------------------------------------------*/ - -// unlink pending rx/tx; completion handlers do all other cleanup - -static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) -{ - unsigned long flags; - struct sk_buff *skb, *skbnext; - int count = 0; - - spin_lock_irqsave (&q->lock, flags); - for (skb = q->next; skb != (struct sk_buff *) q; skb = skbnext) { - struct skb_data *entry; - struct urb *urb; - int retval; - - entry = (struct skb_data *) skb->cb; - urb = entry->urb; - skbnext = skb->next; - - // during some PM-driven resume scenarios, - // these (async) unlinks complete immediately - retval = usb_unlink_urb (urb); - if (retval != -EINPROGRESS && retval != 0) - devdbg (dev, "unlink urb err, %d", retval); - else - count++; - } - spin_unlock_irqrestore (&q->lock, flags); - return count; -} - - -/*-------------------------------------------------------------------------*/ - -// precondition: never called in_interrupt - -static int usbnet_stop (struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - int temp; - DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); - DECLARE_WAITQUEUE (wait, current); - - netif_stop_queue (net); - - if (netif_msg_ifdown (dev)) - devinfo (dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld", - dev->stats.rx_packets, dev->stats.tx_packets, - dev->stats.rx_errors, dev->stats.tx_errors - ); - - // ensure there are no more active urbs - add_wait_queue (&unlink_wakeup, &wait); - dev->wait = &unlink_wakeup; - temp = unlink_urbs (dev, &dev->txq) + unlink_urbs (dev, &dev->rxq); - - // maybe wait for deletions to finish. - while (!skb_queue_empty(&dev->rxq) && - !skb_queue_empty(&dev->txq) && - !skb_queue_empty(&dev->done)) { - msleep(UNLINK_TIMEOUT_MS); - if (netif_msg_ifdown (dev)) - devdbg (dev, "waited for %d urb completions", temp); - } - dev->wait = NULL; - remove_wait_queue (&unlink_wakeup, &wait); - - usb_kill_urb(dev->interrupt); - - /* deferred work (task, timer, softirq) must also stop. - * can't flush_scheduled_work() until we drop rtnl (later), - * else workers could deadlock; so make workers a NOP. - */ - dev->flags = 0; - del_timer_sync (&dev->delay); - tasklet_kill (&dev->bh); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -// posts reads, and enables write queuing - -// precondition: never called in_interrupt - -static int usbnet_open (struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - int retval = 0; - struct driver_info *info = dev->driver_info; - - // put into "known safe" state - if (info->reset && (retval = info->reset (dev)) < 0) { - if (netif_msg_ifup (dev)) - devinfo (dev, - "open reset fail (%d) usbnet usb-%s-%s, %s", - retval, - dev->udev->bus->bus_name, dev->udev->devpath, - info->description); - goto done; - } - - // insist peer be connected - if (info->check_connect && (retval = info->check_connect (dev)) < 0) { - if (netif_msg_ifup (dev)) - devdbg (dev, "can't open; %d", retval); - goto done; - } - - /* start any status interrupt transfer */ - if (dev->interrupt) { - retval = usb_submit_urb (dev->interrupt, GFP_KERNEL); - if (retval < 0) { - if (netif_msg_ifup (dev)) - deverr (dev, "intr submit %d", retval); - goto done; - } - } - - netif_start_queue (net); - if (netif_msg_ifup (dev)) { - char *framing; - - if (dev->driver_info->flags & FLAG_FRAMING_NC) - framing = "NetChip"; - else if (dev->driver_info->flags & FLAG_FRAMING_GL) - framing = "GeneSys"; - else if (dev->driver_info->flags & FLAG_FRAMING_Z) - framing = "Zaurus"; - else if (dev->driver_info->flags & FLAG_FRAMING_RN) - framing = "RNDIS"; - else if (dev->driver_info->flags & FLAG_FRAMING_AX) - framing = "ASIX"; - else - framing = "simple"; - - devinfo (dev, "open: enable queueing " - "(rx %d, tx %d) mtu %d %s framing", - RX_QLEN (dev), TX_QLEN (dev), dev->net->mtu, - framing); - } - - // delay posting reads until we're fully open - tasklet_schedule (&dev->bh); -done: - return retval; -} - -/*-------------------------------------------------------------------------*/ - -/* ethtool methods; minidrivers may need to add some more, but - * they'll probably want to use this base set. - */ - -void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) -{ - struct usbnet *dev = netdev_priv(net); - - /* REVISIT don't always return "usbnet" */ - strncpy (info->driver, driver_name, sizeof info->driver); - strncpy (info->version, DRIVER_VERSION, sizeof info->version); - strncpy (info->fw_version, dev->driver_info->description, - sizeof info->fw_version); - usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info); -} -EXPORT_SYMBOL_GPL(usbnet_get_drvinfo); - -static u32 usbnet_get_link (struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - - /* If a check_connect is defined, return its result */ - if (dev->driver_info->check_connect) - return dev->driver_info->check_connect (dev) == 0; - - /* Otherwise, say we're up (to avoid breaking scripts) */ - return 1; -} - -u32 usbnet_get_msglevel (struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - - return dev->msg_enable; -} -EXPORT_SYMBOL_GPL(usbnet_get_msglevel); - -void usbnet_set_msglevel (struct net_device *net, u32 level) -{ - struct usbnet *dev = netdev_priv(net); - - dev->msg_enable = level; -} -EXPORT_SYMBOL_GPL(usbnet_set_msglevel); - -/* drivers may override default ethtool_ops in their bind() routine */ -static struct ethtool_ops usbnet_ethtool_ops = { - .get_drvinfo = usbnet_get_drvinfo, - .get_link = usbnet_get_link, - .get_msglevel = usbnet_get_msglevel, - .set_msglevel = usbnet_set_msglevel, -}; - -/*-------------------------------------------------------------------------*/ - -/* work that cannot be done in interrupt context uses keventd. - * - * NOTE: with 2.5 we could do more of this using completion callbacks, - * especially now that control transfers can be queued. - */ -static void -kevent (void *data) -{ - struct usbnet *dev = data; - int status; - - /* usb_clear_halt() needs a thread context */ - if (test_bit (EVENT_TX_HALT, &dev->flags)) { - unlink_urbs (dev, &dev->txq); - status = usb_clear_halt (dev->udev, dev->out); - if (status < 0 - && status != -EPIPE - && status != -ESHUTDOWN) { - if (netif_msg_tx_err (dev)) - deverr (dev, "can't clear tx halt, status %d", - status); - } else { - clear_bit (EVENT_TX_HALT, &dev->flags); - if (status != -ESHUTDOWN) - netif_wake_queue (dev->net); - } - } - if (test_bit (EVENT_RX_HALT, &dev->flags)) { - unlink_urbs (dev, &dev->rxq); - status = usb_clear_halt (dev->udev, dev->in); - if (status < 0 - && status != -EPIPE - && status != -ESHUTDOWN) { - if (netif_msg_rx_err (dev)) - deverr (dev, "can't clear rx halt, status %d", - status); - } else { - clear_bit (EVENT_RX_HALT, &dev->flags); - tasklet_schedule (&dev->bh); - } - } - - /* tasklet could resubmit itself forever if memory is tight */ - if (test_bit (EVENT_RX_MEMORY, &dev->flags)) { - struct urb *urb = NULL; - - if (netif_running (dev->net)) - urb = usb_alloc_urb (0, GFP_KERNEL); - else - clear_bit (EVENT_RX_MEMORY, &dev->flags); - if (urb != NULL) { - clear_bit (EVENT_RX_MEMORY, &dev->flags); - rx_submit (dev, urb, GFP_KERNEL); - tasklet_schedule (&dev->bh); - } - } - - if (test_bit (EVENT_LINK_RESET, &dev->flags)) { - struct driver_info *info = dev->driver_info; - int retval = 0; - - clear_bit (EVENT_LINK_RESET, &dev->flags); - if(info->link_reset && (retval = info->link_reset(dev)) < 0) { - devinfo(dev, "link reset failed (%d) usbnet usb-%s-%s, %s", - retval, - dev->udev->bus->bus_name, dev->udev->devpath, - info->description); - } - } - - if (dev->flags) - devdbg (dev, "kevent done, flags = 0x%lx", - dev->flags); -} - -/*-------------------------------------------------------------------------*/ - -static void tx_complete (struct urb *urb, struct pt_regs *regs) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct skb_data *entry = (struct skb_data *) skb->cb; - struct usbnet *dev = entry->dev; - - if (urb->status == 0) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += entry->length; - } else { - dev->stats.tx_errors++; - - switch (urb->status) { - case -EPIPE: - usbnet_defer_kevent (dev, EVENT_TX_HALT); - break; - - /* software-driven interface shutdown */ - case -ECONNRESET: // async unlink - case -ESHUTDOWN: // hardware gone - break; - - // like rx, tx gets controller i/o faults during khubd delays - // and so it uses the same throttling mechanism. - case -EPROTO: // ehci - case -ETIMEDOUT: // ohci - case -EILSEQ: // uhci - if (!timer_pending (&dev->delay)) { - mod_timer (&dev->delay, - jiffies + THROTTLE_JIFFIES); - if (netif_msg_link (dev)) - devdbg (dev, "tx throttle %d", - urb->status); - } - netif_stop_queue (dev->net); - break; - default: - if (netif_msg_tx_err (dev)) - devdbg (dev, "tx err %d", entry->urb->status); - break; - } - } - - urb->dev = NULL; - entry->state = tx_done; - defer_bh(dev, skb, &dev->txq); -} - -/*-------------------------------------------------------------------------*/ - -static void usbnet_tx_timeout (struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - - unlink_urbs (dev, &dev->txq); - tasklet_schedule (&dev->bh); - - // FIXME: device recovery -- reset? -} - -/*-------------------------------------------------------------------------*/ - -static int usbnet_start_xmit (struct sk_buff *skb, struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - int length; - int retval = NET_XMIT_SUCCESS; - struct urb *urb = NULL; - struct skb_data *entry; - struct driver_info *info = dev->driver_info; - unsigned long flags; - - // some devices want funky USB-level framing, for - // win32 driver (usually) and/or hardware quirks - if (info->tx_fixup) { - skb = info->tx_fixup (dev, skb, GFP_ATOMIC); - if (!skb) { - if (netif_msg_tx_err (dev)) - devdbg (dev, "can't tx_fixup skb"); - goto drop; - } - } - length = skb->len; - - if (!(urb = usb_alloc_urb (0, GFP_ATOMIC))) { - if (netif_msg_tx_err (dev)) - devdbg (dev, "no urb"); - goto drop; - } - - entry = (struct skb_data *) skb->cb; - entry->urb = urb; - entry->dev = dev; - entry->state = tx_start; - entry->length = length; - - usb_fill_bulk_urb (urb, dev->udev, dev->out, - skb->data, skb->len, tx_complete, skb); - - /* don't assume the hardware handles USB_ZERO_PACKET - * NOTE: strictly conforming cdc-ether devices should expect - * the ZLP here, but ignore the one-byte packet. - * - * FIXME zero that byte, if it doesn't require a new skb. - */ - if ((length % dev->maxpacket) == 0) - urb->transfer_buffer_length++; - - spin_lock_irqsave (&dev->txq.lock, flags); - - switch ((retval = usb_submit_urb (urb, GFP_ATOMIC))) { - case -EPIPE: - netif_stop_queue (net); - usbnet_defer_kevent (dev, EVENT_TX_HALT); - break; - default: - if (netif_msg_tx_err (dev)) - devdbg (dev, "tx: submit urb err %d", retval); - break; - case 0: - net->trans_start = jiffies; - __skb_queue_tail (&dev->txq, skb); - if (dev->txq.qlen >= TX_QLEN (dev)) - netif_stop_queue (net); - } - spin_unlock_irqrestore (&dev->txq.lock, flags); - - if (retval) { - if (netif_msg_tx_err (dev)) - devdbg (dev, "drop, code %d", retval); -drop: - retval = NET_XMIT_SUCCESS; - dev->stats.tx_dropped++; - if (skb) - dev_kfree_skb_any (skb); - usb_free_urb (urb); - } else if (netif_msg_tx_queued (dev)) { - devdbg (dev, "> tx, len %d, type 0x%x", - length, skb->protocol); - } - return retval; -} - - -/*-------------------------------------------------------------------------*/ - -// tasklet (work deferred from completions, in_irq) or timer - -static void usbnet_bh (unsigned long param) -{ - struct usbnet *dev = (struct usbnet *) param; - struct sk_buff *skb; - struct skb_data *entry; - - while ((skb = skb_dequeue (&dev->done))) { - entry = (struct skb_data *) skb->cb; - switch (entry->state) { - case rx_done: - entry->state = rx_cleanup; - rx_process (dev, skb); - continue; - case tx_done: - case rx_cleanup: - usb_free_urb (entry->urb); - dev_kfree_skb (skb); - continue; - default: - devdbg (dev, "bogus skb state %d", entry->state); - } - } - - // waiting for all pending urbs to complete? - if (dev->wait) { - if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { - wake_up (dev->wait); - } - - // or are we maybe short a few urbs? - } else if (netif_running (dev->net) - && netif_device_present (dev->net) - && !timer_pending (&dev->delay) - && !test_bit (EVENT_RX_HALT, &dev->flags)) { - int temp = dev->rxq.qlen; - int qlen = RX_QLEN (dev); - - if (temp < qlen) { - struct urb *urb; - int i; - - // don't refill the queue all at once - for (i = 0; i < 10 && dev->rxq.qlen < qlen; i++) { - urb = usb_alloc_urb (0, GFP_ATOMIC); - if (urb != NULL) - rx_submit (dev, urb, GFP_ATOMIC); - } - if (temp != dev->rxq.qlen && netif_msg_link (dev)) - devdbg (dev, "rxqlen %d --> %d", - temp, dev->rxq.qlen); - if (dev->rxq.qlen < qlen) - tasklet_schedule (&dev->bh); - } - if (dev->txq.qlen < TX_QLEN (dev)) - netif_wake_queue (dev->net); - } -} - - - -/*------------------------------------------------------------------------- - * - * USB Device Driver support - * - *-------------------------------------------------------------------------*/ - -// precondition: never called in_interrupt - -void usbnet_disconnect (struct usb_interface *intf) -{ - struct usbnet *dev; - struct usb_device *xdev; - struct net_device *net; - - dev = usb_get_intfdata(intf); - usb_set_intfdata(intf, NULL); - if (!dev) - return; - - xdev = interface_to_usbdev (intf); - - if (netif_msg_probe (dev)) - devinfo (dev, "unregister '%s' usb-%s-%s, %s", - intf->dev.driver->name, - xdev->bus->bus_name, xdev->devpath, - dev->driver_info->description); - - net = dev->net; - unregister_netdev (net); - - /* we don't hold rtnl here ... */ - flush_scheduled_work (); - - if (dev->driver_info->unbind) - dev->driver_info->unbind (dev, intf); - - free_netdev(net); - usb_put_dev (xdev); -} -EXPORT_SYMBOL_GPL(usbnet_disconnect); - - -/*-------------------------------------------------------------------------*/ - -// precondition: never called in_interrupt - -int -usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) -{ - struct usbnet *dev; - struct net_device *net; - struct usb_host_interface *interface; - struct driver_info *info; - struct usb_device *xdev; - int status; - - info = (struct driver_info *) prod->driver_info; - if (!info) { - dev_dbg (&udev->dev, "blacklisted by %s\n", driver_name); - return -ENODEV; - } - xdev = interface_to_usbdev (udev); - interface = udev->cur_altsetting; - - usb_get_dev (xdev); - - status = -ENOMEM; - - // set up our own records - net = alloc_etherdev(sizeof(*dev)); - if (!net) { - dbg ("can't kmalloc dev"); - goto out; - } - - dev = netdev_priv(net); - dev->udev = xdev; - dev->driver_info = info; - dev->msg_enable = netif_msg_init (msg_level, NETIF_MSG_DRV - | NETIF_MSG_PROBE | NETIF_MSG_LINK); - skb_queue_head_init (&dev->rxq); - skb_queue_head_init (&dev->txq); - skb_queue_head_init (&dev->done); - dev->bh.func = usbnet_bh; - dev->bh.data = (unsigned long) dev; - INIT_WORK (&dev->kevent, kevent, dev); - dev->delay.function = usbnet_bh; - dev->delay.data = (unsigned long) dev; - init_timer (&dev->delay); - - SET_MODULE_OWNER (net); - dev->net = net; - strcpy (net->name, "usb%d"); - memcpy (net->dev_addr, node_id, sizeof node_id); - - /* rx and tx sides can use different message sizes; - * bind() should set rx_urb_size in that case. - */ - dev->hard_mtu = net->mtu + net->hard_header_len; -#if 0 -// dma_supported() is deeply broken on almost all architectures - // possible with some EHCI controllers - if (dma_supported (&udev->dev, DMA_64BIT_MASK)) - net->features |= NETIF_F_HIGHDMA; -#endif - - net->change_mtu = usbnet_change_mtu; - net->get_stats = usbnet_get_stats; - net->hard_start_xmit = usbnet_start_xmit; - net->open = usbnet_open; - net->stop = usbnet_stop; - net->watchdog_timeo = TX_TIMEOUT_JIFFIES; - net->tx_timeout = usbnet_tx_timeout; - net->ethtool_ops = &usbnet_ethtool_ops; - - // allow device-specific bind/init procedures - // NOTE net->name still not usable ... - if (info->bind) { - status = info->bind (dev, udev); - // heuristic: "usb%d" for links we know are two-host, - // else "eth%d" when there's reasonable doubt. userspace - // can rename the link if it knows better. - if ((dev->driver_info->flags & FLAG_ETHER) != 0 - && (net->dev_addr [0] & 0x02) == 0) - strcpy (net->name, "eth%d"); - - /* maybe the remote can't receive an Ethernet MTU */ - if (net->mtu > (dev->hard_mtu - net->hard_header_len)) - net->mtu = dev->hard_mtu - net->hard_header_len; - } else if (!info->in || !info->out) - status = usbnet_get_endpoints (dev, udev); - else { - dev->in = usb_rcvbulkpipe (xdev, info->in); - dev->out = usb_sndbulkpipe (xdev, info->out); - if (!(info->flags & FLAG_NO_SETINT)) - status = usb_set_interface (xdev, - interface->desc.bInterfaceNumber, - interface->desc.bAlternateSetting); - else - status = 0; - - } - if (status == 0 && dev->status) - status = init_status (dev, udev); - if (status < 0) - goto out1; - - if (!dev->rx_urb_size) - dev->rx_urb_size = dev->hard_mtu; - dev->maxpacket = usb_maxpacket (dev->udev, dev->out, 1); - - SET_NETDEV_DEV(net, &udev->dev); - status = register_netdev (net); - if (status) - goto out3; - if (netif_msg_probe (dev)) - devinfo (dev, "register '%s' at usb-%s-%s, %s, " - "%02x:%02x:%02x:%02x:%02x:%02x", - udev->dev.driver->name, - xdev->bus->bus_name, xdev->devpath, - dev->driver_info->description, - net->dev_addr [0], net->dev_addr [1], - net->dev_addr [2], net->dev_addr [3], - net->dev_addr [4], net->dev_addr [5]); - - // ok, it's ready to go. - usb_set_intfdata (udev, dev); - - // start as if the link is up - netif_device_attach (net); - - return 0; - -out3: - if (info->unbind) - info->unbind (dev, udev); -out1: - free_netdev(net); -out: - usb_put_dev(xdev); - return status; -} -EXPORT_SYMBOL_GPL(usbnet_probe); - -/*-------------------------------------------------------------------------*/ - -/* FIXME these suspend/resume methods assume non-CDC style - * devices, with only one interface. - */ - -int usbnet_suspend (struct usb_interface *intf, pm_message_t message) -{ - struct usbnet *dev = usb_get_intfdata(intf); - - /* accelerate emptying of the rx and queues, to avoid - * having everything error out. - */ - netif_device_detach (dev->net); - (void) unlink_urbs (dev, &dev->rxq); - (void) unlink_urbs (dev, &dev->txq); - return 0; -} -EXPORT_SYMBOL_GPL(usbnet_suspend); - -int usbnet_resume (struct usb_interface *intf) -{ - struct usbnet *dev = usb_get_intfdata(intf); - - netif_device_attach (dev->net); - tasklet_schedule (&dev->bh); - return 0; -} -EXPORT_SYMBOL_GPL(usbnet_resume); - - -/*-------------------------------------------------------------------------*/ - -static int __init usbnet_init(void) -{ - /* compiler should optimize this out */ - BUG_ON (sizeof (((struct sk_buff *)0)->cb) - < sizeof (struct skb_data)); - - random_ether_addr(node_id); - return 0; -} -module_init(usbnet_init); - -static void __exit usbnet_exit(void) -{ -} -module_exit(usbnet_exit); - -MODULE_AUTHOR("David Brownell"); -MODULE_DESCRIPTION("USB network driver framework"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h deleted file mode 100644 index 89fc4958eec..00000000000 --- a/drivers/usb/net/usbnet.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * USB Networking Link Interface - * - * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net> - * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com> - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#ifndef __USBNET_H -#define __USBNET_H - - -/* interface from usbnet core to each USB networking link we handle */ -struct usbnet { - /* housekeeping */ - struct usb_device *udev; - struct driver_info *driver_info; - wait_queue_head_t *wait; - - /* i/o info: pipes etc */ - unsigned in, out; - struct usb_host_endpoint *status; - unsigned maxpacket; - struct timer_list delay; - - /* protocol/interface state */ - struct net_device *net; - struct net_device_stats stats; - int msg_enable; - unsigned long data [5]; - u32 xid; - u32 hard_mtu; /* count any extra framing */ - size_t rx_urb_size; /* size for rx urbs */ - struct mii_if_info mii; - - /* various kinds of pending driver work */ - struct sk_buff_head rxq; - struct sk_buff_head txq; - struct sk_buff_head done; - struct urb *interrupt; - struct tasklet_struct bh; - - struct work_struct kevent; - unsigned long flags; -# define EVENT_TX_HALT 0 -# define EVENT_RX_HALT 1 -# define EVENT_RX_MEMORY 2 -# define EVENT_STS_SPLIT 3 -# define EVENT_LINK_RESET 4 -}; - -static inline struct usb_driver *driver_of(struct usb_interface *intf) -{ - return to_usb_driver(intf->dev.driver); -} - -/* interface from the device/framing level "minidriver" to core */ -struct driver_info { - char *description; - - int flags; -/* framing is CDC Ethernet, not writing ZLPs (hw issues), or optionally: */ -#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */ -#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */ -#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */ -#define FLAG_FRAMING_RN 0x0008 /* RNDIS batches, plus huge header */ - -#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */ -#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */ - -#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ - - /* init device ... can sleep, or cause probe() failure */ - int (*bind)(struct usbnet *, struct usb_interface *); - - /* cleanup device ... can sleep, but can't fail */ - void (*unbind)(struct usbnet *, struct usb_interface *); - - /* reset device ... can sleep */ - int (*reset)(struct usbnet *); - - /* see if peer is connected ... can sleep */ - int (*check_connect)(struct usbnet *); - - /* for status polling */ - void (*status)(struct usbnet *, struct urb *); - - /* link reset handling, called from defer_kevent */ - int (*link_reset)(struct usbnet *); - - /* fixup rx packet (strip framing) */ - int (*rx_fixup)(struct usbnet *dev, struct sk_buff *skb); - - /* fixup tx packet (add framing) */ - struct sk_buff *(*tx_fixup)(struct usbnet *dev, - struct sk_buff *skb, gfp_t flags); - - /* for new devices, use the descriptor-reading code instead */ - int in; /* rx endpoint */ - int out; /* tx endpoint */ - - unsigned long data; /* Misc driver specific data */ -}; - -/* Minidrivers are just drivers using the "usbnet" core as a powerful - * network-specific subroutine library ... that happens to do pretty - * much everything except custom framing and chip-specific stuff. - */ -extern int usbnet_probe(struct usb_interface *, const struct usb_device_id *); -extern int usbnet_suspend (struct usb_interface *, pm_message_t ); -extern int usbnet_resume (struct usb_interface *); -extern void usbnet_disconnect(struct usb_interface *); - - -/* Drivers that reuse some of the standard USB CDC infrastructure - * (notably, using multiple interfaces according to the the CDC - * union descriptor) get some helper code. - */ -struct cdc_state { - struct usb_cdc_header_desc *header; - struct usb_cdc_union_desc *u; - struct usb_cdc_ether_desc *ether; - struct usb_interface *control; - struct usb_interface *data; -}; - -extern int usbnet_generic_cdc_bind (struct usbnet *, struct usb_interface *); -extern void usbnet_cdc_unbind (struct usbnet *, struct usb_interface *); - -/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */ -#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ - |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ - |USB_CDC_PACKET_TYPE_PROMISCUOUS \ - |USB_CDC_PACKET_TYPE_DIRECTED) - - -/* we record the state for each of our queued skbs */ -enum skb_state { - illegal = 0, - tx_start, tx_done, - rx_start, rx_done, rx_cleanup -}; - -struct skb_data { /* skb->cb is one of these */ - struct urb *urb; - struct usbnet *dev; - enum skb_state state; - size_t length; -}; - - -extern int usbnet_get_endpoints(struct usbnet *, struct usb_interface *); -extern void usbnet_defer_kevent (struct usbnet *, int); -extern void usbnet_skb_return (struct usbnet *, struct sk_buff *); - -extern u32 usbnet_get_msglevel (struct net_device *); -extern void usbnet_set_msglevel (struct net_device *, u32); -extern void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *); - -/* messaging support includes the interface name, so it must not be - * used before it has one ... notably, in minidriver bind() calls. - */ -#ifdef DEBUG -#define devdbg(usbnet, fmt, arg...) \ - printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , ## arg) -#else -#define devdbg(usbnet, fmt, arg...) do {} while(0) -#endif - -#define deverr(usbnet, fmt, arg...) \ - printk(KERN_ERR "%s: " fmt "\n" , (usbnet)->net->name , ## arg) -#define devwarn(usbnet, fmt, arg...) \ - printk(KERN_WARNING "%s: " fmt "\n" , (usbnet)->net->name , ## arg) - -#define devinfo(usbnet, fmt, arg...) \ - printk(KERN_INFO "%s: " fmt "\n" , (usbnet)->net->name , ## arg); \ - - -#endif /* __USBNET_H */ diff --git a/drivers/usb/net/zaurus.c b/drivers/usb/net/zaurus.c deleted file mode 100644 index 5d4b7d55b09..00000000000 --- a/drivers/usb/net/zaurus.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz> - * Copyright (C) 2002-2005 by David Brownell - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include <linux/config.h> -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#endif -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/ethtool.h> -#include <linux/workqueue.h> -#include <linux/mii.h> -#include <linux/crc32.h> -#include <linux/usb.h> -#include <linux/usb_cdc.h> - -#include "usbnet.h" - - -/* - * All known Zaurii lie about their standards conformance. At least - * the earliest SA-1100 models lie by saying they support CDC Ethernet. - * Some later models (especially PXA-25x and PXA-27x based ones) lie - * and say they support CDC MDLM (for access to cell phone modems). - * - * There are non-Zaurus products that use these same protocols too. - * - * The annoying thing is that at the same time Sharp was developing - * that annoying standards-breaking software, the Linux community had - * a simple "CDC Subset" working reliably on the same SA-1100 hardware. - * That is, the same functionality but not violating standards. - * - * The CDC Ethernet nonconformance points are troublesome to hosts - * with a true CDC Ethernet implementation: - * - Framing appends a CRC, which the spec says drivers "must not" do; - * - Transfers data in altsetting zero, instead of altsetting 1; - * - All these peripherals use the same ethernet address. - * - * The CDC MDLM nonconformance is less immediately troublesome, since all - * MDLM implementations are quasi-proprietary anyway. - */ - -static struct sk_buff * -zaurus_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) -{ - int padlen; - struct sk_buff *skb2; - - padlen = 2; - if (!skb_cloned(skb)) { - int tailroom = skb_tailroom(skb); - if ((padlen + 4) <= tailroom) - goto done; - } - skb2 = skb_copy_expand(skb, 0, 4 + padlen, flags); - dev_kfree_skb_any(skb); - skb = skb2; - if (skb) { - u32 fcs; -done: - fcs = crc32_le(~0, skb->data, skb->len); - fcs = ~fcs; - - *skb_put (skb, 1) = fcs & 0xff; - *skb_put (skb, 1) = (fcs>> 8) & 0xff; - *skb_put (skb, 1) = (fcs>>16) & 0xff; - *skb_put (skb, 1) = (fcs>>24) & 0xff; - } - return skb; -} - -static int zaurus_bind(struct usbnet *dev, struct usb_interface *intf) -{ - /* Belcarra's funky framing has other options; mostly - * TRAILERS (!) with 4 bytes CRC, and maybe 2 pad bytes. - */ - dev->net->hard_header_len += 6; - dev->rx_urb_size = dev->net->hard_header_len + dev->net->mtu; - return usbnet_generic_cdc_bind(dev, intf); -} - -/* PDA style devices are always connected if present */ -static int always_connected (struct usbnet *dev) -{ - return 0; -} - -static const struct driver_info zaurus_sl5x00_info = { - .description = "Sharp Zaurus SL-5x00", - .flags = FLAG_FRAMING_Z, - .check_connect = always_connected, - .bind = zaurus_bind, - .unbind = usbnet_cdc_unbind, - .tx_fixup = zaurus_tx_fixup, -}; -#define ZAURUS_STRONGARM_INFO ((unsigned long)&zaurus_sl5x00_info) - -static const struct driver_info zaurus_pxa_info = { - .description = "Sharp Zaurus, PXA-2xx based", - .flags = FLAG_FRAMING_Z, - .check_connect = always_connected, - .bind = zaurus_bind, - .unbind = usbnet_cdc_unbind, - .tx_fixup = zaurus_tx_fixup, -}; -#define ZAURUS_PXA_INFO ((unsigned long)&zaurus_pxa_info) - -static const struct driver_info olympus_mxl_info = { - .description = "Olympus R1000", - .flags = FLAG_FRAMING_Z, - .check_connect = always_connected, - .bind = zaurus_bind, - .unbind = usbnet_cdc_unbind, - .tx_fixup = zaurus_tx_fixup, -}; -#define OLYMPUS_MXL_INFO ((unsigned long)&olympus_mxl_info) - - -/* Some more recent products using Lineo/Belcarra code will wrongly claim - * CDC MDLM conformance. They aren't conformant: data endpoints live - * in the control interface, there's no data interface, and it's not used - * to talk to a cell phone radio. But at least we can detect these two - * pseudo-classes, rather than growing this product list with entries for - * each new nonconformant product (sigh). - */ -static const u8 safe_guid[16] = { - 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, - 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, -}; -static const u8 blan_guid[16] = { - 0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70, - 0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37, -}; - -static int blan_mdlm_bind(struct usbnet *dev, struct usb_interface *intf) -{ - u8 *buf = intf->cur_altsetting->extra; - int len = intf->cur_altsetting->extralen; - struct usb_cdc_mdlm_desc *desc = NULL; - struct usb_cdc_mdlm_detail_desc *detail = NULL; - - while (len > 3) { - if (buf [1] != USB_DT_CS_INTERFACE) - goto next_desc; - - /* use bDescriptorSubType, and just verify that we get a - * "BLAN" (or "SAFE") descriptor. - */ - switch (buf [2]) { - case USB_CDC_MDLM_TYPE: - if (desc) { - dev_dbg(&intf->dev, "extra MDLM\n"); - goto bad_desc; - } - desc = (void *) buf; - if (desc->bLength != sizeof *desc) { - dev_dbg(&intf->dev, "MDLM len %u\n", - desc->bLength); - goto bad_desc; - } - /* expect bcdVersion 1.0, ignore */ - if (memcmp(&desc->bGUID, blan_guid, 16) - && memcmp(&desc->bGUID, safe_guid, 16) ) { - /* hey, this one might _really_ be MDLM! */ - dev_dbg(&intf->dev, "MDLM guid\n"); - goto bad_desc; - } - break; - case USB_CDC_MDLM_DETAIL_TYPE: - if (detail) { - dev_dbg(&intf->dev, "extra MDLM detail\n"); - goto bad_desc; - } - detail = (void *) buf; - switch (detail->bGuidDescriptorType) { - case 0: /* "SAFE" */ - if (detail->bLength != (sizeof *detail + 2)) - goto bad_detail; - break; - case 1: /* "BLAN" */ - if (detail->bLength != (sizeof *detail + 3)) - goto bad_detail; - break; - default: - goto bad_detail; - } - - /* assuming we either noticed BLAN already, or will - * find it soon, there are some data bytes here: - * - bmNetworkCapabilities (unused) - * - bmDataCapabilities (bits, see below) - * - bPad (ignored, for PADAFTER -- BLAN-only) - * bits are: - * - 0x01 -- Zaurus framing (add CRC) - * - 0x02 -- PADBEFORE (CRC includes some padding) - * - 0x04 -- PADAFTER (some padding after CRC) - * - 0x08 -- "fermat" packet mangling (for hw bugs) - * the PADBEFORE appears not to matter; we interop - * with devices that use it and those that don't. - */ - if ((detail->bDetailData[1] & ~0x02) != 0x01) { - /* bmDataCapabilites == 0 would be fine too, - * but framing is minidriver-coupled for now. - */ -bad_detail: - dev_dbg(&intf->dev, - "bad MDLM detail, %d %d %d\n", - detail->bLength, - detail->bDetailData[0], - detail->bDetailData[2]); - goto bad_desc; - } - break; - } -next_desc: - len -= buf [0]; /* bLength */ - buf += buf [0]; - } - - if (!desc || !detail) { - dev_dbg(&intf->dev, "missing cdc mdlm %s%sdescriptor\n", - desc ? "" : "func ", - detail ? "" : "detail "); - goto bad_desc; - } - - /* There's probably a CDC Ethernet descriptor there, but we can't - * rely on the Ethernet address it provides since not all vendors - * bother to make it unique. Likewise there's no point in tracking - * of the CDC event notifications. - */ - return usbnet_get_endpoints(dev, intf); - -bad_desc: - dev_info(&dev->udev->dev, "unsupported MDLM descriptors\n"); - return -ENODEV; -} - -static const struct driver_info bogus_mdlm_info = { - .description = "pseudo-MDLM (BLAN) device", - .flags = FLAG_FRAMING_Z, - .check_connect = always_connected, - .tx_fixup = zaurus_tx_fixup, - .bind = blan_mdlm_bind, -}; - -static const struct usb_device_id products [] = { -#define ZAURUS_MASTER_INTERFACE \ - .bInterfaceClass = USB_CLASS_COMM, \ - .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, \ - .bInterfaceProtocol = USB_CDC_PROTO_NONE - -/* SA-1100 based Sharp Zaurus ("collie"), or compatible. */ -{ - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x8004, - ZAURUS_MASTER_INTERFACE, - .driver_info = ZAURUS_STRONGARM_INFO, -}, - -/* PXA-2xx based models are also lying-about-cdc. If you add any - * more devices that claim to be CDC Ethernet, make sure they get - * added to the blacklist in cdc_ether too. - * - * NOTE: OpenZaurus versions with 2.6 kernels won't use these entries, - * unlike the older ones with 2.4 "embedix" kernels. - */ -{ - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x8005, /* A-300 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = ZAURUS_PXA_INFO, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x8006, /* B-500/SL-5600 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = ZAURUS_PXA_INFO, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x8007, /* C-700 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = ZAURUS_PXA_INFO, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x9031, /* C-750 C-760 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = ZAURUS_PXA_INFO, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - .idProduct = 0x9032, /* SL-6000 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = ZAURUS_PXA_INFO, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x04DD, - /* reported with some C860 units */ - .idProduct = 0x9050, /* C-860 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = ZAURUS_PXA_INFO, -}, - - -/* At least some of the newest PXA units have very different lies about - * their standards support: they claim to be cell phones offering - * direct access to their radios! (No, they don't conform to CDC MDLM.) - */ -{ - USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM, - USB_CDC_PROTO_NONE), - .driver_info = (unsigned long) &bogus_mdlm_info, -}, - -/* Olympus has some models with a Zaurus-compatible option. - * R-1000 uses a FreeScale i.MXL cpu (ARMv4T) - */ -{ - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x07B4, - .idProduct = 0x0F02, /* R-1000 */ - ZAURUS_MASTER_INTERFACE, - .driver_info = OLYMPUS_MXL_INFO, -}, - { }, // END -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver zaurus_driver = { - .owner = THIS_MODULE, - .name = "zaurus", - .id_table = products, - .probe = usbnet_probe, - .disconnect = usbnet_disconnect, - .suspend = usbnet_suspend, - .resume = usbnet_resume, -}; - -static int __init zaurus_init(void) -{ - return usb_register(&zaurus_driver); -} -module_init(zaurus_init); - -static void __exit zaurus_exit(void) -{ - usb_deregister(&zaurus_driver); -} -module_exit(zaurus_exit); - -MODULE_AUTHOR("Pavel Machek, David Brownell"); -MODULE_DESCRIPTION("Sharp Zaurus PDA, and compatible products"); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c deleted file mode 100644 index 2f52261c7cc..00000000000 --- a/drivers/usb/net/zd1201.c +++ /dev/null @@ -1,1946 +0,0 @@ -/* - * Driver for ZyDAS zd1201 based wireless USB devices. - * - * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Parts of this driver have been derived from a wlan-ng version - * modified by ZyDAS. They also made documentation available, thanks! - * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - */ - -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/wireless.h> -#include <net/iw_handler.h> -#include <linux/string.h> -#include <linux/if_arp.h> -#include <linux/firmware.h> -#include <net/ieee80211.h> -#include "zd1201.h" - -static struct usb_device_id zd1201_table[] = { - {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */ - {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ - {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ - {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ - {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ - {} -}; - -static int ap = 0; /* Are we an AP or a normal station? */ - -#define ZD1201_VERSION "0.15" - -MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>"); -MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters"); -MODULE_VERSION(ZD1201_VERSION); -MODULE_LICENSE("GPL"); -module_param(ap, int, 0); -MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded"); -MODULE_DEVICE_TABLE(usb, zd1201_table); - - -static int zd1201_fw_upload(struct usb_device *dev, int apfw) -{ - const struct firmware *fw_entry; - char* data; - unsigned long len; - int err; - unsigned char ret; - char *buf; - char *fwfile; - - if (apfw) - fwfile = "zd1201-ap.fw"; - else - fwfile = "zd1201.fw"; - - err = request_firmware(&fw_entry, fwfile, &dev->dev); - if (err) { - dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile); - dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n"); - dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info\n"); - return err; - } - - data = fw_entry->data; - len = fw_entry->size; - - buf = kmalloc(1024, GFP_ATOMIC); - if (!buf) - goto exit; - - while (len > 0) { - int translen = (len > 1024) ? 1024 : len; - memcpy(buf, data, translen); - - err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, - USB_DIR_OUT | 0x40, 0, 0, buf, translen, - ZD1201_FW_TIMEOUT); - if (err < 0) - goto exit; - - len -= translen; - data += translen; - } - - err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2, - USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT); - if (err < 0) - goto exit; - - err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4, - USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT); - if (err < 0) - goto exit; - - if (ret & 0x80) { - err = -EIO; - goto exit; - } - - err = 0; -exit: - kfree(buf); - release_firmware(fw_entry); - return err; -} - -static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs) -{ - struct zd1201 *zd = urb->context; - - switch(urb->status) { - case -EILSEQ: - case -ENODEV: - case -ETIMEDOUT: - case -ENOENT: - case -EPIPE: - case -EOVERFLOW: - case -ESHUTDOWN: - dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", - zd->dev->name, urb->status); - } - - kfree(urb->transfer_buffer); - usb_free_urb(urb); - return; -} - -/* cmdreq message: - u32 type - u16 cmd - u16 parm0 - u16 parm1 - u16 parm2 - u8 pad[4] - - total: 4 + 2 + 2 + 2 + 2 + 4 = 16 -*/ -static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, - int parm1, int parm2) -{ - unsigned char *command; - int ret; - struct urb *urb; - - command = kmalloc(16, GFP_ATOMIC); - if (!command) - return -ENOMEM; - - *((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ); - *((__le16*)&command[4]) = cpu_to_le16(cmd); - *((__le16*)&command[6]) = cpu_to_le16(parm0); - *((__le16*)&command[8]) = cpu_to_le16(parm1); - *((__le16*)&command[10])= cpu_to_le16(parm2); - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - kfree(command); - return -ENOMEM; - } - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), - command, 16, zd1201_usbfree, zd); - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - kfree(command); - usb_free_urb(urb); - } - - return ret; -} - -/* Callback after sending out a packet */ -static void zd1201_usbtx(struct urb *urb, struct pt_regs *regs) -{ - struct zd1201 *zd = urb->context; - netif_wake_queue(zd->dev); - return; -} - -/* Incoming data */ -static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs) -{ - struct zd1201 *zd = urb->context; - int free = 0; - unsigned char *data = urb->transfer_buffer; - struct sk_buff *skb; - unsigned char type; - - if (!zd) { - free = 1; - goto exit; - } - - switch(urb->status) { - case -EILSEQ: - case -ENODEV: - case -ETIMEDOUT: - case -ENOENT: - case -EPIPE: - case -EOVERFLOW: - case -ESHUTDOWN: - dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n", - zd->dev->name, urb->status); - free = 1; - goto exit; - } - - if (urb->status != 0 || urb->actual_length == 0) - goto resubmit; - - type = data[0]; - if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) { - memcpy(zd->rxdata, data, urb->actual_length); - zd->rxlen = urb->actual_length; - zd->rxdatas = 1; - wake_up(&zd->rxdataq); - } - /* Info frame */ - if (type == ZD1201_PACKET_INQUIRE) { - int i = 0; - unsigned short infotype, framelen, copylen; - framelen = le16_to_cpu(*(__le16*)&data[4]); - infotype = le16_to_cpu(*(__le16*)&data[6]); - - if (infotype == ZD1201_INF_LINKSTATUS) { - short linkstatus; - - linkstatus = le16_to_cpu(*(__le16*)&data[8]); - switch(linkstatus) { - case 1: - netif_carrier_on(zd->dev); - break; - case 2: - netif_carrier_off(zd->dev); - break; - case 3: - netif_carrier_off(zd->dev); - break; - case 4: - netif_carrier_on(zd->dev); - break; - default: - netif_carrier_off(zd->dev); - } - goto resubmit; - } - if (infotype == ZD1201_INF_ASSOCSTATUS) { - short status = le16_to_cpu(*(__le16*)(data+8)); - int event; - union iwreq_data wrqu; - - switch (status) { - case ZD1201_ASSOCSTATUS_STAASSOC: - case ZD1201_ASSOCSTATUS_REASSOC: - event = IWEVREGISTERED; - break; - case ZD1201_ASSOCSTATUS_DISASSOC: - case ZD1201_ASSOCSTATUS_ASSOCFAIL: - case ZD1201_ASSOCSTATUS_AUTHFAIL: - default: - event = IWEVEXPIRED; - } - memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - - /* Send event to user space */ - wireless_send_event(zd->dev, event, &wrqu, NULL); - - goto resubmit; - } - if (infotype == ZD1201_INF_AUTHREQ) { - union iwreq_data wrqu; - - memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - /* There isn't a event that trully fits this request. - We assume that userspace will be smart enough to - see a new station being expired and sends back a - authstation ioctl to authorize it. */ - wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL); - goto resubmit; - } - /* Other infotypes are handled outside this handler */ - zd->rxlen = 0; - while (i < urb->actual_length) { - copylen = le16_to_cpu(*(__le16*)&data[i+2]); - /* Sanity check, sometimes we get junk */ - if (copylen+zd->rxlen > sizeof(zd->rxdata)) - break; - memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen); - zd->rxlen += copylen; - i += 64; - } - if (i >= urb->actual_length) { - zd->rxdatas = 1; - wake_up(&zd->rxdataq); - } - goto resubmit; - } - /* Actual data */ - if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) { - int datalen = urb->actual_length-1; - unsigned short len, fc, seq; - struct hlist_node *node; - - len = ntohs(*(__be16 *)&data[datalen-2]); - if (len>datalen) - len=datalen; - fc = le16_to_cpu(*(__le16 *)&data[datalen-16]); - seq = le16_to_cpu(*(__le16 *)&data[datalen-24]); - - if(zd->monitor) { - if (datalen < 24) - goto resubmit; - if (!(skb = dev_alloc_skb(datalen+24))) - goto resubmit; - - memcpy(skb_put(skb, 2), &data[datalen-16], 2); - memcpy(skb_put(skb, 2), &data[datalen-2], 2); - memcpy(skb_put(skb, 6), &data[datalen-14], 6); - memcpy(skb_put(skb, 6), &data[datalen-22], 6); - memcpy(skb_put(skb, 6), &data[datalen-8], 6); - memcpy(skb_put(skb, 2), &data[datalen-24], 2); - memcpy(skb_put(skb, len), data, len); - skb->dev = zd->dev; - skb->dev->last_rx = jiffies; - skb->protocol = eth_type_trans(skb, zd->dev); - zd->stats.rx_packets++; - zd->stats.rx_bytes += skb->len; - netif_rx(skb); - goto resubmit; - } - - if ((seq & IEEE80211_SCTL_FRAG) || - (fc & IEEE80211_FCTL_MOREFRAGS)) { - struct zd1201_frag *frag = NULL; - char *ptr; - - if (datalen<14) - goto resubmit; - if ((seq & IEEE80211_SCTL_FRAG) == 0) { - frag = kmalloc(sizeof(*frag), GFP_ATOMIC); - if (!frag) - goto resubmit; - skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2); - if (!skb) { - kfree(frag); - goto resubmit; - } - frag->skb = skb; - frag->seq = seq & IEEE80211_SCTL_SEQ; - skb_reserve(skb, 2); - memcpy(skb_put(skb, 12), &data[datalen-14], 12); - memcpy(skb_put(skb, 2), &data[6], 2); - memcpy(skb_put(skb, len), data+8, len); - hlist_add_head(&frag->fnode, &zd->fraglist); - goto resubmit; - } - hlist_for_each_entry(frag, node, &zd->fraglist, fnode) - if(frag->seq == (seq&IEEE80211_SCTL_SEQ)) - break; - if (!frag) - goto resubmit; - skb = frag->skb; - ptr = skb_put(skb, len); - if (ptr) - memcpy(ptr, data+8, len); - if (fc & IEEE80211_FCTL_MOREFRAGS) - goto resubmit; - hlist_del_init(&frag->fnode); - kfree(frag); - /* Fallthrough */ - } else { - if (datalen<14) - goto resubmit; - skb = dev_alloc_skb(len + 14 + 2); - if (!skb) - goto resubmit; - skb_reserve(skb, 2); - memcpy(skb_put(skb, 12), &data[datalen-14], 12); - memcpy(skb_put(skb, 2), &data[6], 2); - memcpy(skb_put(skb, len), data+8, len); - } - skb->dev = zd->dev; - skb->dev->last_rx = jiffies; - skb->protocol = eth_type_trans(skb, zd->dev); - zd->stats.rx_packets++; - zd->stats.rx_bytes += skb->len; - netif_rx(skb); - } -resubmit: - memset(data, 0, ZD1201_RXSIZE); - - urb->status = 0; - urb->dev = zd->usb; - if(usb_submit_urb(urb, GFP_ATOMIC)) - free = 1; - -exit: - if (free) { - zd->rxlen = 0; - zd->rxdatas = 1; - wake_up(&zd->rxdataq); - kfree(urb->transfer_buffer); - } - return; -} - -static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, - unsigned int riddatalen) -{ - int err; - int i = 0; - int code; - int rid_fid; - int length; - unsigned char *pdata; - - zd->rxdatas = 0; - err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0); - if (err) - return err; - - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen) - return -EIO; - - code = le16_to_cpu(*(__le16*)(&zd->rxdata[4])); - rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6])); - length = le16_to_cpu(*(__le16*)(&zd->rxdata[8])); - if (length > zd->rxlen) - length = zd->rxlen-6; - - /* If access bit is not on, then error */ - if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid ) - return -EINVAL; - - /* Not enough buffer for allocating data */ - if (riddatalen != (length - 4)) { - dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n", - riddatalen, zd->rxlen, length, rid, rid_fid); - return -ENODATA; - } - - zd->rxdatas = 0; - /* Issue SetRxRid commnd */ - err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length); - if (err) - return err; - - /* Receive RID record from resource packets */ - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen) - return -EIO; - - if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) { - dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n", - zd->rxdata[zd->rxlen-1]); - return -EINVAL; - } - - /* Set the data pointer and received data length */ - pdata = zd->rxdata; - length = zd->rxlen; - - do { - int actual_length; - - actual_length = (length > 64) ? 64 : length; - - if(pdata[0] != 0x3) { - dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n", - pdata[0]); - return -EINVAL; - } - - if (actual_length != 64) { - /* Trim the last packet type byte */ - actual_length--; - } - - /* Skip the 4 bytes header (RID length and RID) */ - if(i == 0) { - pdata += 8; - actual_length -= 8; - } - else { - pdata += 4; - actual_length -= 4; - } - - memcpy(riddata, pdata, actual_length); - riddata += actual_length; - pdata += actual_length; - length -= 64; - i++; - } while (length > 0); - - return 0; -} - -/* - * resreq: - * byte type - * byte sequence - * u16 reserved - * byte data[12] - * total: 16 - */ -static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait) -{ - int err; - unsigned char *request; - int reqlen; - char seq=0; - struct urb *urb; - gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; - - len += 4; /* first 4 are for header */ - - zd->rxdatas = 0; - zd->rxlen = 0; - for (seq=0; len > 0; seq++) { - request = kmalloc(16, gfp_mask); - if (!request) - return -ENOMEM; - urb = usb_alloc_urb(0, gfp_mask); - if (!urb) { - kfree(request); - return -ENOMEM; - } - memset(request, 0, 16); - reqlen = len>12 ? 12 : len; - request[0] = ZD1201_USB_RESREQ; - request[1] = seq; - request[2] = 0; - request[3] = 0; - if (request[1] == 0) { - /* add header */ - *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2); - *(__le16*)&request[6] = cpu_to_le16(rid); - memcpy(request+8, buf, reqlen-4); - buf += reqlen-4; - } else { - memcpy(request+4, buf, reqlen); - buf += reqlen; - } - - len -= reqlen; - - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, - zd->endp_out2), request, 16, zd1201_usbfree, zd); - err = usb_submit_urb(urb, gfp_mask); - if (err) - goto err; - } - - request = kmalloc(16, gfp_mask); - if (!request) - return -ENOMEM; - urb = usb_alloc_urb(0, gfp_mask); - if (!urb) { - kfree(request); - return -ENOMEM; - } - *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ); - *((__le16*)&request[4]) = - cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT); - *((__le16*)&request[6]) = cpu_to_le16(rid); - *((__le16*)&request[8]) = cpu_to_le16(0); - *((__le16*)&request[10]) = cpu_to_le16(0); - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), - request, 16, zd1201_usbfree, zd); - err = usb_submit_urb(urb, gfp_mask); - if (err) - goto err; - - if (wait) { - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) { - dev_dbg(&zd->usb->dev, "wrong or no RID received\n"); - } - } - - return 0; -err: - kfree(request); - usb_free_urb(urb); - return err; -} - -static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val) -{ - int err; - __le16 zdval; - - err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16)); - if (err) - return err; - *val = le16_to_cpu(zdval); - return 0; -} - -static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val) -{ - __le16 zdval = cpu_to_le16(val); - return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1)); -} - -static int zd1201_drvr_start(struct zd1201 *zd) -{ - int err, i; - short max; - __le16 zdmax; - unsigned char *buffer; - - buffer = kmalloc(ZD1201_RXSIZE, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - memset(buffer, 0, ZD1201_RXSIZE); - - usb_fill_bulk_urb(zd->rx_urb, zd->usb, - usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, - zd1201_usbrx, zd); - - err = usb_submit_urb(zd->rx_urb, GFP_KERNEL); - if (err) - goto err_buffer; - - err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); - if (err) - goto err_urb; - - err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax, - sizeof(__le16)); - if (err) - goto err_urb; - - max = le16_to_cpu(zdmax); - for (i=0; i<max; i++) { - err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0); - if (err) - goto err_urb; - } - - return 0; - -err_urb: - usb_kill_urb(zd->rx_urb); - return err; -err_buffer: - kfree(buffer); - return err; -} - -/* Magic alert: The firmware doesn't seem to like the MAC state being - * toggled in promisc (aka monitor) mode. - * (It works a number of times, but will halt eventually) - * So we turn it of before disabling and on after enabling if needed. - */ -static int zd1201_enable(struct zd1201 *zd) -{ - int err; - - if (zd->mac_enabled) - return 0; - - err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0); - if (!err) - zd->mac_enabled = 1; - - if (zd->monitor) - err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1); - - return err; -} - -static int zd1201_disable(struct zd1201 *zd) -{ - int err; - - if (!zd->mac_enabled) - return 0; - if (zd->monitor) { - err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); - if (err) - return err; - } - - err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0); - if (!err) - zd->mac_enabled = 0; - return err; -} - -static int zd1201_mac_reset(struct zd1201 *zd) -{ - if (!zd->mac_enabled) - return 0; - zd1201_disable(zd); - return zd1201_enable(zd); -} - -static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen) -{ - int err, val; - char buf[IW_ESSID_MAX_SIZE+2]; - - err = zd1201_disable(zd); - if (err) - return err; - - val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; - val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val); - if (err) - return err; - - *(__le16 *)buf = cpu_to_le16(essidlen); - memcpy(buf+2, essid, essidlen); - if (!zd->ap) { /* Normal station */ - err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, - IW_ESSID_MAX_SIZE+2, 1); - if (err) - return err; - } else { /* AP */ - err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf, - IW_ESSID_MAX_SIZE+2, 1); - if (err) - return err; - } - - err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, - zd->dev->dev_addr, zd->dev->addr_len, 1); - if (err) - return err; - - err = zd1201_enable(zd); - if (err) - return err; - - msleep(100); - return 0; -} - -static int zd1201_net_open(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - /* Start MAC with wildcard if no essid set */ - if (!zd->mac_enabled) - zd1201_join(zd, zd->essid, zd->essidlen); - netif_start_queue(dev); - - return 0; -} - -static int zd1201_net_stop(struct net_device *dev) -{ - netif_stop_queue(dev); - - return 0; -} - -/* - RFC 1042 encapsulates Ethernet frames in 802.11 frames - by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0 - (0x00, 0x00, 0x00). Zd requires an additional padding, copy - of ethernet addresses, length of the standard RFC 1042 packet - and a command byte (which is nul for tx). - - tx frame (from Wlan NG): - RFC 1042: - llc 0xAA 0xAA 0x03 (802.2 LLC) - snap 0x00 0x00 0x00 (Ethernet encapsulated) - type 2 bytes, Ethernet type field - payload (minus eth header) - Zydas specific: - padding 1B if (skb->len+8+1)%64==0 - Eth MAC addr 12 bytes, Ethernet MAC addresses - length 2 bytes, RFC 1042 packet length - (llc+snap+type+payload) - zd 1 null byte, zd1201 packet type - */ -static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - unsigned char *txbuf = zd->txdata; - int txbuflen, pad = 0, err; - struct urb *urb = zd->tx_urb; - - if (!zd->mac_enabled || zd->monitor) { - zd->stats.tx_dropped++; - kfree_skb(skb); - return 0; - } - netif_stop_queue(dev); - - txbuflen = skb->len + 8 + 1; - if (txbuflen%64 == 0) { - pad = 1; - txbuflen++; - } - txbuf[0] = 0xAA; - txbuf[1] = 0xAA; - txbuf[2] = 0x03; - txbuf[3] = 0x00; /* rfc1042 */ - txbuf[4] = 0x00; - txbuf[5] = 0x00; - - memcpy(txbuf+6, skb->data+12, skb->len-12); - if (pad) - txbuf[skb->len-12+6]=0; - memcpy(txbuf+skb->len-12+6+pad, skb->data, 12); - *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6); - txbuf[txbuflen-1] = 0; - - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out), - txbuf, txbuflen, zd1201_usbtx, zd); - - err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC); - if (err) { - zd->stats.tx_errors++; - netif_start_queue(dev); - return err; - } - zd->stats.tx_packets++; - zd->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; - kfree_skb(skb); - - return 0; -} - -static void zd1201_tx_timeout(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - if (!zd) - return; - dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n", - dev->name); - usb_unlink_urb(zd->tx_urb); - zd->stats.tx_errors++; - /* Restart the timeout to quiet the watchdog: */ - dev->trans_start = jiffies; -} - -static int zd1201_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - - if (!zd) - return -ENODEV; - - err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, - addr->sa_data, dev->addr_len, 1); - if (err) - return err; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - return zd1201_mac_reset(zd); -} - -static struct net_device_stats *zd1201_get_stats(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - return &zd->stats; -} - -static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - return &zd->iwstats; -} - -static void zd1201_set_multicast(struct net_device *dev) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - struct dev_mc_list *mc = dev->mc_list; - unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; - int i; - - if (dev->mc_count > ZD1201_MAXMULTI) - return; - - for (i=0; i<dev->mc_count; i++) { - memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN); - mc = mc->next; - } - zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, - dev->mc_count*ETH_ALEN, 0); - -} - -static int zd1201_config_commit(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - return zd1201_mac_reset(zd); -} - -static int zd1201_get_name(struct net_device *dev, - struct iw_request_info *info, char *name, char *extra) -{ - strcpy(name, "IEEE 802.11b"); - - return 0; -} - -static int zd1201_set_freq(struct net_device *dev, - struct iw_request_info *info, struct iw_freq *freq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short channel = 0; - int err; - - if (freq->e == 0) - channel = freq->m; - else { - if (freq->m >= 2482) - channel = 14; - if (freq->m >= 2407) - channel = (freq->m-2407)/5; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); - if (err) - return err; - - zd1201_mac_reset(zd); - - return 0; -} - -static int zd1201_get_freq(struct net_device *dev, - struct iw_request_info *info, struct iw_freq *freq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short channel; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel); - if (err) - return err; - freq->e = 0; - freq->m = channel; - - return 0; -} - -static int zd1201_set_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *mode, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short porttype, monitor = 0; - unsigned char buffer[IW_ESSID_MAX_SIZE+2]; - int err; - - if (zd->ap) { - if (*mode != IW_MODE_MASTER) - return -EINVAL; - return 0; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); - if (err) - return err; - zd->dev->type = ARPHRD_ETHER; - switch(*mode) { - case IW_MODE_MONITOR: - monitor = 1; - zd->dev->type = ARPHRD_IEEE80211; - /* Make sure we are no longer associated with by - setting an 'impossible' essid. - (otherwise we mess up firmware) - */ - zd1201_join(zd, "\0-*#\0", 5); - /* Put port in pIBSS */ - case 8: /* No pseudo-IBSS in wireless extensions (yet) */ - porttype = ZD1201_PORTTYPE_PSEUDOIBSS; - break; - case IW_MODE_ADHOC: - porttype = ZD1201_PORTTYPE_IBSS; - break; - case IW_MODE_INFRA: - porttype = ZD1201_PORTTYPE_BSS; - break; - default: - return -EINVAL; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); - if (err) - return err; - if (zd->monitor && !monitor) { - zd1201_disable(zd); - *(__le16 *)buffer = cpu_to_le16(zd->essidlen); - memcpy(buffer+2, zd->essid, zd->essidlen); - err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, - buffer, IW_ESSID_MAX_SIZE+2, 1); - if (err) - return err; - } - zd->monitor=monitor; - /* If monitor mode is set we don't actually turn it on here since it - * is done during mac reset anyway (see zd1201_mac_enable). - */ - - zd1201_mac_reset(zd); - - return 0; -} - -static int zd1201_get_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *mode, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short porttype; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype); - if (err) - return err; - switch(porttype) { - case ZD1201_PORTTYPE_IBSS: - *mode = IW_MODE_ADHOC; - break; - case ZD1201_PORTTYPE_BSS: - *mode = IW_MODE_INFRA; - break; - case ZD1201_PORTTYPE_WDS: - *mode = IW_MODE_REPEAT; - break; - case ZD1201_PORTTYPE_PSEUDOIBSS: - *mode = 8;/* No Pseudo-IBSS... */ - break; - case ZD1201_PORTTYPE_AP: - *mode = IW_MODE_MASTER; - break; - default: - dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n", - porttype); - *mode = IW_MODE_AUTO; - } - if (zd->monitor) - *mode = IW_MODE_MONITOR; - - return 0; -} - -static int zd1201_get_range(struct net_device *dev, - struct iw_request_info *info, struct iw_point *wrq, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - - wrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = WIRELESS_EXT; - - range->max_qual.qual = 128; - range->max_qual.level = 128; - range->max_qual.noise = 128; - range->max_qual.updated = 7; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = ZD1201_NUMKEYS; - - range->num_bitrates = 4; - range->bitrate[0] = 1000000; - range->bitrate[1] = 2000000; - range->bitrate[2] = 5500000; - range->bitrate[3] = 11000000; - - range->min_rts = 0; - range->min_frag = ZD1201_FRAGMIN; - range->max_rts = ZD1201_RTSMAX; - range->min_frag = ZD1201_FRAGMAX; - - return 0; -} - -/* Little bit of magic here: we only get the quality if we poll - * for it, and we never get an actual request to trigger such - * a poll. Therefore we 'assume' that the user will soon ask for - * the stats after asking the bssid. - */ -static int zd1201_get_wap(struct net_device *dev, - struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - unsigned char buffer[6]; - - if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { - /* Unfortunately the quality and noise reported is useless. - they seem to be accumulators that increase until you - read them, unless we poll on a fixed interval we can't - use them - */ - /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/ - zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]); - /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/ - zd->iwstats.qual.updated = 2; - } - - return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6); -} - -static int zd1201_set_scan(struct net_device *dev, - struct iw_request_info *info, struct iw_point *srq, char *extra) -{ - /* We do everything in get_scan */ - return 0; -} - -static int zd1201_get_scan(struct net_device *dev, - struct iw_request_info *info, struct iw_point *srq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err, i, j, enabled_save; - struct iw_event iwe; - char *cev = extra; - char *end_buf = extra + IW_SCAN_MAX_DATA; - - /* No scanning in AP mode */ - if (zd->ap) - return -EOPNOTSUPP; - - /* Scan doesn't seem to work if disabled */ - enabled_save = zd->mac_enabled; - zd1201_enable(zd); - - zd->rxdatas = 0; - err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, - ZD1201_INQ_SCANRESULTS, 0, 0); - if (err) - return err; - - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen) - return -EIO; - - if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS) - return -EIO; - - for(i=8; i<zd->rxlen; i+=62) { - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); - cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); - - iwe.cmd = SIOCGIWESSID; - iwe.u.data.length = zd->rxdata[i+16]; - iwe.u.data.flags = 1; - cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18); - - iwe.cmd = SIOCGIWMODE; - if (zd->rxdata[i+14]&0x01) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); - - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = zd->rxdata[i+0]; - iwe.u.freq.e = 0; - cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); - - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.fixed = 0; - iwe.u.bitrate.disabled = 0; - for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { - iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; - cev=iwe_stream_add_event(cev, end_buf, &iwe, - IW_EV_PARAM_LEN); - } - - iwe.cmd = SIOCGIWENCODE; - iwe.u.data.length = 0; - if (zd->rxdata[i+14]&0x10) - iwe.u.data.flags = IW_ENCODE_ENABLED; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); - - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = zd->rxdata[i+4]; - iwe.u.qual.noise= zd->rxdata[i+2]/10-100; - iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; - iwe.u.qual.updated = 7; - cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); - } - - if (!enabled_save) - zd1201_disable(zd); - - srq->length = cev - extra; - srq->flags = 0; - - return 0; -} - -static int zd1201_set_essid(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - if (data->length > IW_ESSID_MAX_SIZE) - return -EINVAL; - if (data->length < 1) - data->length = 1; - zd->essidlen = data->length-1; - memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1); - memcpy(zd->essid, essid, data->length); - return zd1201_join(zd, zd->essid, zd->essidlen); -} - -static int zd1201_get_essid(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - - memcpy(essid, zd->essid, zd->essidlen); - data->flags = 1; - data->length = zd->essidlen; - - return 0; -} - -static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *nick) -{ - strcpy(nick, "zd1201"); - data->flags = 1; - data->length = strlen(nick); - return 0; -} - -static int zd1201_set_rate(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short rate; - int err; - - switch (rrq->value) { - case 1000000: - rate = ZD1201_RATEB1; - break; - case 2000000: - rate = ZD1201_RATEB2; - break; - case 5500000: - rate = ZD1201_RATEB5; - break; - case 11000000: - default: - rate = ZD1201_RATEB11; - break; - } - if (!rrq->fixed) { /* Also enable all lower bitrates */ - rate |= rate-1; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate); - if (err) - return err; - - return zd1201_mac_reset(zd); -} - -static int zd1201_get_rate(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short rate; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate); - if (err) - return err; - - switch(rate) { - case 1: - rrq->value = 1000000; - break; - case 2: - rrq->value = 2000000; - break; - case 5: - rrq->value = 5500000; - break; - case 11: - rrq->value = 11000000; - break; - default: - rrq->value = 0; - } - rrq->fixed = 0; - rrq->disabled = 0; - - return 0; -} - -static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - short val = rts->value; - - if (rts->disabled || !rts->fixed) - val = ZD1201_RTSMAX; - if (val > ZD1201_RTSMAX) - return -EINVAL; - if (val < 0) - return -EINVAL; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val); - if (err) - return err; - return zd1201_mac_reset(zd); -} - -static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short rtst; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst); - if (err) - return err; - rts->value = rtst; - rts->disabled = (rts->value == ZD1201_RTSMAX); - rts->fixed = 1; - - return 0; -} - -static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - short val = frag->value; - - if (frag->disabled || !frag->fixed) - val = ZD1201_FRAGMAX; - if (val > ZD1201_FRAGMAX) - return -EINVAL; - if (val < ZD1201_FRAGMIN) - return -EINVAL; - if (val & 1) - return -EINVAL; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val); - if (err) - return err; - return zd1201_mac_reset(zd); -} - -static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short fragt; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt); - if (err) - return err; - frag->value = fragt; - frag->disabled = (frag->value == ZD1201_FRAGMAX); - frag->fixed = 1; - - return 0; -} - -static int zd1201_set_retry(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - return 0; -} - -static int zd1201_get_retry(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - return 0; -} - -static int zd1201_set_encode(struct net_device *dev, - struct iw_request_info *info, struct iw_point *erq, char *key) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short i; - int err, rid; - - if (erq->length > ZD1201_MAXKEYLEN) - return -EINVAL; - - i = (erq->flags & IW_ENCODE_INDEX)-1; - if (i == -1) { - err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i); - if (err) - return err; - } else { - err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i); - if (err) - return err; - } - - if (i < 0 || i >= ZD1201_NUMKEYS) - return -EINVAL; - - rid = ZD1201_RID_CNFDEFAULTKEY0 + i; - err = zd1201_setconfig(zd, rid, key, erq->length, 1); - if (err) - return err; - zd->encode_keylen[i] = erq->length; - memcpy(zd->encode_keys[i], key, erq->length); - - i=0; - if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) { - i |= 0x01; - zd->encode_enabled = 1; - } else - zd->encode_enabled = 0; - if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) { - i |= 0x02; - zd->encode_restricted = 1; - } else - zd->encode_restricted = 0; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i); - if (err) - return err; - - if (zd->encode_enabled) - i = ZD1201_CNFAUTHENTICATION_SHAREDKEY; - else - i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i); - if (err) - return err; - - return zd1201_mac_reset(zd); -} - -static int zd1201_get_encode(struct net_device *dev, - struct iw_request_info *info, struct iw_point *erq, char *key) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short i; - int err; - - if (zd->encode_enabled) - erq->flags = IW_ENCODE_ENABLED; - else - erq->flags = IW_ENCODE_DISABLED; - if (zd->encode_restricted) - erq->flags |= IW_ENCODE_RESTRICTED; - else - erq->flags |= IW_ENCODE_OPEN; - - i = (erq->flags & IW_ENCODE_INDEX) -1; - if (i == -1) { - err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i); - if (err) - return err; - } - if (i<0 || i>= ZD1201_NUMKEYS) - return -EINVAL; - - erq->flags |= i+1; - - erq->length = zd->encode_keylen[i]; - memcpy(key, zd->encode_keys[i], erq->length); - - return 0; -} - -static int zd1201_set_power(struct net_device *dev, - struct iw_request_info *info, struct iw_param *vwrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short enabled, duration, level; - int err; - - enabled = vwrq->disabled ? 0 : 1; - if (enabled) { - if (vwrq->flags & IW_POWER_PERIOD) { - duration = vwrq->value; - err = zd1201_setconfig16(zd, - ZD1201_RID_CNFMAXSLEEPDURATION, duration); - if (err) - return err; - goto out; - } - if (vwrq->flags & IW_POWER_TIMEOUT) { - err = zd1201_getconfig16(zd, - ZD1201_RID_CNFMAXSLEEPDURATION, &duration); - if (err) - return err; - level = vwrq->value * 4 / duration; - if (level > 4) - level = 4; - if (level < 0) - level = 0; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS, - level); - if (err) - return err; - goto out; - } - return -EINVAL; - } -out: - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled); - if (err) - return err; - - return 0; -} - -static int zd1201_get_power(struct net_device *dev, - struct iw_request_info *info, struct iw_param *vwrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short enabled, level, duration; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled); - if (err) - return err; - err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level); - if (err) - return err; - err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration); - if (err) - return err; - vwrq->disabled = enabled ? 0 : 1; - if (vwrq->flags & IW_POWER_TYPE) { - if (vwrq->flags & IW_POWER_PERIOD) { - vwrq->value = duration; - vwrq->flags = IW_POWER_PERIOD; - } else { - vwrq->value = duration * level / 4; - vwrq->flags = IW_POWER_TIMEOUT; - } - } - if (vwrq->flags & IW_POWER_MODE) { - if (enabled && level) - vwrq->flags = IW_POWER_UNICAST_R; - else - vwrq->flags = IW_POWER_ALL_R; - } - - return 0; -} - - -static const iw_handler zd1201_iw_handler[] = -{ - (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */ - (iw_handler) zd1201_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */ - (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */ - (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */ - (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */ - (iw_handler) zd1201_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */ - (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */ - (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */ - (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */ - (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */ - (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */ - (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */ - (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */ - (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) NULL, /* SIOCGIWTXPOW */ - (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */ - (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */ - (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */ - (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */ - (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */ - (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */ -}; - -static int zd1201_set_hostauth(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value); - if (err) - return err; - return 0; -} - -static int zd1201_get_hostauth(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short hostauth; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth); - if (err) - return err; - rrq->value = hostauth; - rrq->fixed = 1; - - return 0; -} - -static int zd1201_auth_sta(struct net_device *dev, - struct iw_request_info *info, struct sockaddr *sta, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - unsigned char buffer[10]; - - if (!zd->ap) - return -EOPNOTSUPP; - - memcpy(buffer, sta->sa_data, ETH_ALEN); - *(short*)(buffer+6) = 0; /* 0==success, 1==failure */ - *(short*)(buffer+8) = 0; - - return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1); -} - -static int zd1201_set_maxassoc(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value); - if (err) - return err; - return 0; -} - -static int zd1201_get_maxassoc(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = (struct zd1201 *)dev->priv; - short maxassoc; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc); - if (err) - return err; - rrq->value = maxassoc; - rrq->fixed = 1; - - return 0; -} - -static const iw_handler zd1201_private_handler[] = { - (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ - (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ - (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ - (iw_handler) NULL, /* nothing to get */ - (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ - (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */ -}; - -static const struct iw_priv_args zd1201_private_args[] = { - { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "sethostauth" }, - { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" }, - { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "authstation" }, - { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "setmaxassoc" }, - { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" }, -}; - -static const struct iw_handler_def zd1201_iw_handlers = { - .num_standard = sizeof(zd1201_iw_handler)/sizeof(iw_handler), - .num_private = sizeof(zd1201_private_handler)/sizeof(iw_handler), - .num_private_args = sizeof(zd1201_private_args)/sizeof(struct iw_priv_args), - .standard = (iw_handler *)zd1201_iw_handler, - .private = (iw_handler *)zd1201_private_handler, - .private_args = (struct iw_priv_args *) zd1201_private_args, -}; - -static int zd1201_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct zd1201 *zd; - struct usb_device *usb; - int i, err; - short porttype; - char buf[IW_ESSID_MAX_SIZE+2]; - - usb = interface_to_usbdev(interface); - - zd = kmalloc(sizeof(struct zd1201), GFP_KERNEL); - if (!zd) { - return -ENOMEM; - } - memset(zd, 0, sizeof(struct zd1201)); - zd->ap = ap; - zd->usb = usb; - zd->removed = 0; - init_waitqueue_head(&zd->rxdataq); - INIT_HLIST_HEAD(&zd->fraglist); - - err = zd1201_fw_upload(usb, zd->ap); - if (err) { - dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err); - goto err_zd; - } - - zd->endp_in = 1; - zd->endp_out = 1; - zd->endp_out2 = 2; - zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!zd->rx_urb || !zd->tx_urb) - goto err_zd; - - for(i = 0; i<100; i++) - udelay(1000); - - err = zd1201_drvr_start(zd); - if (err) - goto err_zd; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312); - if (err) - goto err_start; - - err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, - ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11); - if (err) - goto err_start; - - zd->dev = alloc_etherdev(0); - if (!zd->dev) - goto err_start; - - zd->dev->priv = zd; - zd->dev->open = zd1201_net_open; - zd->dev->stop = zd1201_net_stop; - zd->dev->get_stats = zd1201_get_stats; - zd->dev->get_wireless_stats = zd1201_get_wireless_stats; - zd->dev->wireless_handlers = - (struct iw_handler_def *)&zd1201_iw_handlers; - zd->dev->hard_start_xmit = zd1201_hard_start_xmit; - zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT; - zd->dev->tx_timeout = zd1201_tx_timeout; - zd->dev->set_multicast_list = zd1201_set_multicast; - zd->dev->set_mac_address = zd1201_set_mac_address; - strcpy(zd->dev->name, "wlan%d"); - - err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, - zd->dev->dev_addr, zd->dev->addr_len); - if (err) - goto err_net; - - /* Set wildcard essid to match zd->essid */ - *(__le16 *)buf = cpu_to_le16(0); - err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, - IW_ESSID_MAX_SIZE+2, 1); - if (err) - goto err_net; - - if (zd->ap) - porttype = ZD1201_PORTTYPE_AP; - else - porttype = ZD1201_PORTTYPE_BSS; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); - if (err) - goto err_net; - - err = register_netdev(zd->dev); - if (err) - goto err_net; - dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", - zd->dev->name); - - usb_set_intfdata(interface, zd); - return 0; - -err_net: - free_netdev(zd->dev); -err_start: - /* Leave the device in reset state */ - zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); -err_zd: - if (zd->tx_urb) - usb_free_urb(zd->tx_urb); - if (zd->rx_urb) - usb_free_urb(zd->rx_urb); - kfree(zd); - return err; -} - -static void zd1201_disconnect(struct usb_interface *interface) -{ - struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); - struct hlist_node *node, *node2; - struct zd1201_frag *frag; - - if (!zd) - return; - usb_set_intfdata(interface, NULL); - if (zd->dev) { - unregister_netdev(zd->dev); - free_netdev(zd->dev); - } - - hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) { - hlist_del_init(&frag->fnode); - kfree_skb(frag->skb); - kfree(frag); - } - - if (zd->tx_urb) { - usb_kill_urb(zd->tx_urb); - usb_free_urb(zd->tx_urb); - } - if (zd->rx_urb) { - usb_kill_urb(zd->rx_urb); - usb_free_urb(zd->rx_urb); - } - kfree(zd); -} - -#ifdef CONFIG_PM - -static int zd1201_suspend(struct usb_interface *interface, - pm_message_t message) -{ - struct zd1201 *zd = usb_get_intfdata(interface); - - netif_device_detach(zd->dev); - - zd->was_enabled = zd->mac_enabled; - - if (zd->was_enabled) - return zd1201_disable(zd); - else - return 0; -} - -static int zd1201_resume(struct usb_interface *interface) -{ - struct zd1201 *zd = usb_get_intfdata(interface); - - if (!zd || !zd->dev) - return -ENODEV; - - netif_device_attach(zd->dev); - - if (zd->was_enabled) - return zd1201_enable(zd); - else - return 0; -} - -#else - -#define zd1201_suspend NULL -#define zd1201_resume NULL - -#endif - -static struct usb_driver zd1201_usb = { - .owner = THIS_MODULE, - .name = "zd1201", - .probe = zd1201_probe, - .disconnect = zd1201_disconnect, - .id_table = zd1201_table, - .suspend = zd1201_suspend, - .resume = zd1201_resume, -}; - -static int __init zd1201_init(void) -{ - return usb_register(&zd1201_usb); -} - -static void __exit zd1201_cleanup(void) -{ - usb_deregister(&zd1201_usb); -} - -module_init(zd1201_init); -module_exit(zd1201_cleanup); diff --git a/drivers/usb/net/zd1201.h b/drivers/usb/net/zd1201.h deleted file mode 100644 index 235f0ee34b2..00000000000 --- a/drivers/usb/net/zd1201.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Parts of this driver have been derived from a wlan-ng version - * modified by ZyDAS. - * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - */ - -#ifndef _INCLUDE_ZD1201_H_ -#define _INCLUDE_ZD1201_H_ - -#define ZD1201_NUMKEYS 4 -#define ZD1201_MAXKEYLEN 13 -#define ZD1201_MAXMULTI 16 -#define ZD1201_FRAGMAX 2500 -#define ZD1201_FRAGMIN 256 -#define ZD1201_RTSMAX 2500 - -#define ZD1201_RXSIZE 3000 - -struct zd1201 { - struct usb_device *usb; - int removed; - struct net_device *dev; - struct net_device_stats stats; - struct iw_statistics iwstats; - - int endp_in; - int endp_out; - int endp_out2; - struct urb *rx_urb; - struct urb *tx_urb; - - unsigned char rxdata[ZD1201_RXSIZE]; - int rxlen; - wait_queue_head_t rxdataq; - int rxdatas; - struct hlist_head fraglist; - unsigned char txdata[ZD1201_RXSIZE]; - - int ap; - char essid[IW_ESSID_MAX_SIZE+1]; - int essidlen; - int mac_enabled; - int was_enabled; - int monitor; - int encode_enabled; - int encode_restricted; - unsigned char encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN]; - int encode_keylen[ZD1201_NUMKEYS]; -}; - -struct zd1201_frag { - struct hlist_node fnode; - int seq; - struct sk_buff *skb; -}; - -#define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV -#define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1 -#define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2 -#define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4 -#define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1 - -#define ZD1201_FW_TIMEOUT (1000) - -#define ZD1201_TX_TIMEOUT (2000) - -#define ZD1201_USB_CMDREQ 0 -#define ZD1201_USB_RESREQ 1 - -#define ZD1201_CMDCODE_INIT 0x00 -#define ZD1201_CMDCODE_ENABLE 0x01 -#define ZD1201_CMDCODE_DISABLE 0x02 -#define ZD1201_CMDCODE_ALLOC 0x0a -#define ZD1201_CMDCODE_INQUIRE 0x11 -#define ZD1201_CMDCODE_SETRXRID 0x17 -#define ZD1201_CMDCODE_ACCESS 0x21 - -#define ZD1201_PACKET_EVENTSTAT 0x0 -#define ZD1201_PACKET_RXDATA 0x1 -#define ZD1201_PACKET_INQUIRE 0x2 -#define ZD1201_PACKET_RESOURCE 0x3 - -#define ZD1201_ACCESSBIT 0x0100 - -#define ZD1201_RID_CNFPORTTYPE 0xfc00 -#define ZD1201_RID_CNFOWNMACADDR 0xfc01 -#define ZD1201_RID_CNFDESIREDSSID 0xfc02 -#define ZD1201_RID_CNFOWNCHANNEL 0xfc03 -#define ZD1201_RID_CNFOWNSSID 0xfc04 -#define ZD1201_RID_CNFMAXDATALEN 0xfc07 -#define ZD1201_RID_CNFPMENABLED 0xfc09 -#define ZD1201_RID_CNFPMEPS 0xfc0a -#define ZD1201_RID_CNFMAXSLEEPDURATION 0xfc0c -#define ZD1201_RID_CNFDEFAULTKEYID 0xfc23 -#define ZD1201_RID_CNFDEFAULTKEY0 0xfc24 -#define ZD1201_RID_CNFDEFAULTKEY1 0xfc25 -#define ZD1201_RID_CNFDEFAULTKEY2 0xfc26 -#define ZD1201_RID_CNFDEFAULTKEY3 0xfc27 -#define ZD1201_RID_CNFWEBFLAGS 0xfc28 -#define ZD1201_RID_CNFAUTHENTICATION 0xfc2a -#define ZD1201_RID_CNFMAXASSOCSTATIONS 0xfc2b -#define ZD1201_RID_CNFHOSTAUTH 0xfc2e -#define ZD1201_RID_CNFGROUPADDRESS 0xfc80 -#define ZD1201_RID_CNFFRAGTHRESHOLD 0xfc82 -#define ZD1201_RID_CNFRTSTHRESHOLD 0xfc83 -#define ZD1201_RID_TXRATECNTL 0xfc84 -#define ZD1201_RID_PROMISCUOUSMODE 0xfc85 -#define ZD1201_RID_CNFBASICRATES 0xfcb3 -#define ZD1201_RID_AUTHENTICATESTA 0xfce3 -#define ZD1201_RID_CURRENTBSSID 0xfd42 -#define ZD1201_RID_COMMSQUALITY 0xfd43 -#define ZD1201_RID_CURRENTTXRATE 0xfd44 -#define ZD1201_RID_CNFMAXTXBUFFERNUMBER 0xfda0 -#define ZD1201_RID_CURRENTCHANNEL 0xfdc1 - -#define ZD1201_INQ_SCANRESULTS 0xf101 - -#define ZD1201_INF_LINKSTATUS 0xf200 -#define ZD1201_INF_ASSOCSTATUS 0xf201 -#define ZD1201_INF_AUTHREQ 0xf202 - -#define ZD1201_ASSOCSTATUS_STAASSOC 0x1 -#define ZD1201_ASSOCSTATUS_REASSOC 0x2 -#define ZD1201_ASSOCSTATUS_DISASSOC 0x3 -#define ZD1201_ASSOCSTATUS_ASSOCFAIL 0x4 -#define ZD1201_ASSOCSTATUS_AUTHFAIL 0x5 - -#define ZD1201_PORTTYPE_IBSS 0 -#define ZD1201_PORTTYPE_BSS 1 -#define ZD1201_PORTTYPE_WDS 2 -#define ZD1201_PORTTYPE_PSEUDOIBSS 3 -#define ZD1201_PORTTYPE_AP 6 - -#define ZD1201_RATEB1 1 -#define ZD1201_RATEB2 2 -#define ZD1201_RATEB5 4 /* 5.5 really, but 5 is shorter :) */ -#define ZD1201_RATEB11 8 - -#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0x0001 -#define ZD1201_CNFAUTHENTICATION_SHAREDKEY 0x0002 - -#endif /* _INCLUDE_ZD1201_H_ */ |
