aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.davemloft.net>2005-01-10 05:04:15 -0800
committerDavid S. Miller <davem@nuts.davemloft.net>2005-01-10 05:04:15 -0800
commit240cdcf7cc2bdc55bc13a065dc737efc5e3d54ba (patch)
tree005fab276d9c68b5081377a2dd25601a3e2d585d /drivers
parent0526ab7788b28c58352e0deae17568dc7b071435 (diff)
parent73ef2d644741787f8054e69c4c52d471bd68617f (diff)
downloadhistory-240cdcf7cc2bdc55bc13a065dc737efc5e3d54ba.tar.gz
Merge nuts.davemloft.net:/disk1/BK/network-2.6
into nuts.davemloft.net:/disk1/BK/net-2.6
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/base/Kconfig2
-rw-r--r--drivers/base/bus.c2
-rw-r--r--drivers/base/class.c18
-rw-r--r--drivers/base/platform.c52
-rw-r--r--drivers/block/Kconfig8
-rw-r--r--drivers/block/aoe/Makefile6
-rw-r--r--drivers/block/aoe/aoe.h162
-rw-r--r--drivers/block/aoe/aoeblk.c251
-rw-r--r--drivers/block/aoe/aoechr.c279
-rw-r--r--drivers/block/aoe/aoecmd.c627
-rw-r--r--drivers/block/aoe/aoedev.c194
-rw-r--r--drivers/block/aoe/aoemain.c93
-rw-r--r--drivers/block/aoe/aoenet.c175
-rw-r--r--drivers/bluetooth/bfusb.c2
-rw-r--r--drivers/bluetooth/hci_usb.c10
-rw-r--r--drivers/char/drm/drmP.h1
-rw-r--r--drivers/char/misc.c14
-rw-r--r--drivers/char/watchdog/pcwd_usb.c8
-rw-r--r--drivers/eisa/Makefile3
-rw-r--r--drivers/i2c/algos/Kconfig13
-rw-r--r--drivers/i2c/algos/Makefile2
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-sgi.c189
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c231
-rw-r--r--drivers/i2c/busses/Kconfig16
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c7
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c15
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c7
-rw-r--r--drivers/i2c/busses/i2c-amd756.c15
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c2
-rw-r--r--drivers/i2c/busses/i2c-hydra.c7
-rw-r--r--drivers/i2c/busses/i2c-i801.c56
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c547
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.h103
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c11
-rw-r--r--drivers/i2c/busses/i2c-piix4.c54
-rw-r--r--drivers/i2c/busses/i2c-prosavage.c7
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c71
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c12
-rw-r--r--drivers/i2c/busses/i2c-stub.c22
-rw-r--r--drivers/i2c/busses/i2c-viapro.c72
-rw-r--r--drivers/i2c/chips/Kconfig12
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/chips/asb100.c3
-rw-r--r--drivers/i2c/chips/eeprom.c19
-rw-r--r--drivers/i2c/chips/fscher.c11
-rw-r--r--drivers/i2c/chips/isp1301_omap.c9
-rw-r--r--drivers/i2c/chips/it87.c2
-rw-r--r--drivers/i2c/chips/lm78.c2
-rw-r--r--drivers/i2c/chips/lm90.c28
-rw-r--r--drivers/i2c/chips/pc87360.c3
-rw-r--r--drivers/i2c/chips/smsc47b397.c353
-rw-r--r--drivers/i2c/chips/smsc47m1.c2
-rw-r--r--drivers/i2c/chips/via686a.c2
-rw-r--r--drivers/i2c/chips/w83627hf.c45
-rw-r--r--drivers/i2c/chips/w83781d.c3
-rw-r--r--drivers/i2c/i2c-sensor-vid.c5
-rw-r--r--drivers/isdn/hisax/hfc_usb.c15
-rw-r--r--drivers/isdn/hisax/st5481_b.c2
-rw-r--r--drivers/isdn/hisax/st5481_d.c2
-rw-r--r--drivers/isdn/hisax/st5481_init.c3
-rw-r--r--drivers/isdn/hisax/st5481_usb.c4
-rw-r--r--drivers/media/dvb/b2c2/b2c2-usb-core.c2
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb.c12
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c6
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c8
-rw-r--r--drivers/media/video/bttv-driver.c4
-rw-r--r--drivers/media/video/bttv.h1
-rw-r--r--drivers/net/3c59x.c8
-rw-r--r--drivers/net/8139cp.c6
-rw-r--r--drivers/net/8139too.c4
-rwxr-xr-xdrivers/net/amd8111e.c16
-rw-r--r--drivers/net/e100.c4
-rw-r--r--drivers/net/eepro100.c8
-rw-r--r--drivers/net/irda/irda-usb.c6
-rw-r--r--drivers/net/irda/stir4200.c4
-rw-r--r--drivers/net/pci-skeleton.c4
-rw-r--r--drivers/net/pcmcia/Kconfig2
-rw-r--r--drivers/net/sis900.c4
-rw-r--r--drivers/net/starfire.c2
-rw-r--r--drivers/net/tokenring/Kconfig2
-rw-r--r--drivers/net/typhoon.c6
-rw-r--r--drivers/net/via-rhine.c2
-rw-r--r--drivers/net/via-velocity.c32
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/parport/Kconfig2
-rw-r--r--drivers/pci/hotplug/Kconfig2
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c2
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c2
-rw-r--r--drivers/pci/hotplug/cpcihp_generic.c2
-rw-r--r--drivers/pci/hotplug/cpqphp_pci.c30
-rw-r--r--drivers/pci/hotplug/fakephp.c2
-rw-r--r--drivers/pci/hotplug/ibmphp.h2
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c804
-rw-r--r--drivers/pci/hotplug/ibmphp_pci.c56
-rw-r--r--drivers/pci/hotplug/pciehp_core.c1
-rw-r--r--drivers/pci/hotplug/shpchp.h2
-rw-r--r--drivers/pci/hotplug/shpchp_core.c1
-rw-r--r--drivers/pci/pci-sysfs.c163
-rw-r--r--drivers/pci/pci.c67
-rw-r--r--drivers/pci/probe.c139
-rw-r--r--drivers/pci/quirks.c7
-rw-r--r--drivers/pci/setup-bus.c9
-rw-r--r--drivers/pci/setup-irq.c3
-rw-r--r--drivers/pcmcia/Kconfig2
-rw-r--r--drivers/serial/mcfserial.c61
-rw-r--r--drivers/usb/Makefile4
-rw-r--r--drivers/usb/README33
-rw-r--r--drivers/usb/atm/speedtch.c31
-rw-r--r--drivers/usb/atm/usb_atm.c17
-rw-r--r--drivers/usb/atm/usb_atm.h19
-rw-r--r--drivers/usb/class/audio.c7
-rw-r--r--drivers/usb/class/bluetty.c6
-rw-r--r--drivers/usb/class/cdc-acm.c23
-rw-r--r--drivers/usb/class/cdc-acm.h3
-rw-r--r--drivers/usb/class/usb-midi.c30
-rw-r--r--drivers/usb/class/usb-midi.h4
-rw-r--r--drivers/usb/class/usblp.c19
-rw-r--r--drivers/usb/core/config.c4
-rw-r--r--drivers/usb/core/devices.c14
-rw-r--r--drivers/usb/core/devio.c52
-rw-r--r--drivers/usb/core/hcd-pci.c23
-rw-r--r--drivers/usb/core/hcd.c232
-rw-r--r--drivers/usb/core/hcd.h47
-rw-r--r--drivers/usb/core/hub.c560
-rw-r--r--drivers/usb/core/hub.h2
-rw-r--r--drivers/usb/core/inode.c2
-rw-r--r--drivers/usb/core/message.c50
-rw-r--r--drivers/usb/core/otg_whitelist.h16
-rw-r--r--drivers/usb/core/sysfs.c26
-rw-r--r--drivers/usb/core/urb.c2
-rw-r--r--drivers/usb/core/usb.c84
-rw-r--r--drivers/usb/core/usb.h2
-rw-r--r--drivers/usb/gadget/Kconfig35
-rw-r--r--drivers/usb/gadget/dummy_hcd.c132
-rw-r--r--drivers/usb/gadget/epautoconf.c3
-rw-r--r--drivers/usb/gadget/file_storage.c2
-rw-r--r--drivers/usb/gadget/omap_udc.c2
-rw-r--r--drivers/usb/gadget/serial.c2
-rw-r--r--drivers/usb/host/ehci-dbg.c30
-rw-r--r--drivers/usb/host/ehci-hcd.c130
-rw-r--r--drivers/usb/host/ehci-hub.c12
-rw-r--r--drivers/usb/host/ehci-mem.c31
-rw-r--r--drivers/usb/host/ehci-q.c68
-rw-r--r--drivers/usb/host/ehci-sched.c420
-rw-r--r--drivers/usb/host/ehci.h50
-rw-r--r--drivers/usb/host/hc_crisv10.c32
-rw-r--r--drivers/usb/host/ohci-dbg.c22
-rw-r--r--drivers/usb/host/ohci-hcd.c73
-rw-r--r--drivers/usb/host/ohci-hub.c27
-rw-r--r--drivers/usb/host/ohci-lh7a404.c45
-rw-r--r--drivers/usb/host/ohci-mem.c25
-rw-r--r--drivers/usb/host/ohci-omap.c61
-rw-r--r--drivers/usb/host/ohci-pci.c8
-rw-r--r--drivers/usb/host/ohci-pxa27x.c43
-rw-r--r--drivers/usb/host/ohci-q.c78
-rw-r--r--drivers/usb/host/ohci-sa1111.c30
-rw-r--r--drivers/usb/host/ohci.h25
-rw-r--r--drivers/usb/host/sl811-hcd.c345
-rw-r--r--drivers/usb/host/sl811.h18
-rw-r--r--drivers/usb/host/uhci-debug.c36
-rw-r--r--drivers/usb/host/uhci-hcd.c122
-rw-r--r--drivers/usb/host/uhci-hcd.h22
-rw-r--r--drivers/usb/image/mdc800.c45
-rw-r--r--drivers/usb/image/microtek.c4
-rw-r--r--drivers/usb/input/aiptek.c6
-rw-r--r--drivers/usb/input/ati_remote.c19
-rw-r--r--drivers/usb/input/hid-core.c8
-rw-r--r--drivers/usb/input/hid-ff.c4
-rw-r--r--drivers/usb/input/hid-input.c6
-rw-r--r--drivers/usb/input/hid-lgff.c4
-rw-r--r--drivers/usb/input/hiddev.c6
-rw-r--r--drivers/usb/input/kbtab.c6
-rw-r--r--drivers/usb/input/mtouchusb.c6
-rw-r--r--drivers/usb/input/powermate.c13
-rw-r--r--drivers/usb/input/touchkitusb.c6
-rw-r--r--drivers/usb/input/usbkbd.c6
-rw-r--r--drivers/usb/input/usbmouse.c6
-rw-r--r--drivers/usb/input/wacom.c6
-rw-r--r--drivers/usb/input/xpad.c10
-rw-r--r--drivers/usb/media/Makefile2
-rw-r--r--drivers/usb/media/dabusb.c9
-rw-r--r--drivers/usb/media/ibmcam.c25
-rw-r--r--drivers/usb/media/konicawc.c18
-rw-r--r--drivers/usb/media/ov511.c20
-rw-r--r--drivers/usb/media/se401.c22
-rw-r--r--drivers/usb/media/sn9c102.h13
-rw-r--r--drivers/usb/media/sn9c102_core.c119
-rw-r--r--drivers/usb/media/sn9c102_hv7131d.c271
-rw-r--r--drivers/usb/media/sn9c102_mi0343.c363
-rw-r--r--drivers/usb/media/sn9c102_pas106b.c45
-rw-r--r--drivers/usb/media/sn9c102_pas202bcb.c49
-rw-r--r--drivers/usb/media/sn9c102_sensor.h62
-rw-r--r--drivers/usb/media/sn9c102_tas5110c1b.c28
-rw-r--r--drivers/usb/media/sn9c102_tas5130d1b.c26
-rw-r--r--drivers/usb/media/stv680.c3
-rw-r--r--drivers/usb/media/ultracam.c16
-rw-r--r--drivers/usb/media/vicam.c6
-rw-r--r--drivers/usb/media/w9968cf.c8
-rw-r--r--drivers/usb/misc/Kconfig20
-rw-r--r--drivers/usb/misc/Makefile1
-rw-r--r--drivers/usb/misc/auerswald.c19
-rw-r--r--drivers/usb/misc/emi26.c8
-rw-r--r--drivers/usb/misc/emi62.c6
-rw-r--r--drivers/usb/misc/legousbtower.c11
-rw-r--r--drivers/usb/misc/tiglusb.c592
-rw-r--r--drivers/usb/misc/tiglusb.h43
-rw-r--r--drivers/usb/misc/usblcd.c15
-rw-r--r--drivers/usb/misc/usbtest.c25
-rw-r--r--drivers/usb/misc/uss720.c3
-rw-r--r--drivers/usb/net/catc.c5
-rw-r--r--drivers/usb/net/kaweth.c9
-rw-r--r--drivers/usb/serial/Kconfig23
-rw-r--r--drivers/usb/serial/Makefile2
-rw-r--r--drivers/usb/serial/belkin_sa.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.c135
-rw-r--r--drivers/usb/serial/ftdi_sio.h51
-rw-r--r--drivers/usb/serial/garmin_gps.c1541
-rw-r--r--drivers/usb/serial/io_edgeport.c4
-rw-r--r--drivers/usb/serial/io_ti.c4
-rw-r--r--drivers/usb/serial/keyspan.c12
-rw-r--r--drivers/usb/serial/keyspan_pda.c6
-rw-r--r--drivers/usb/serial/kobil_sct.c2
-rw-r--r--drivers/usb/serial/mct_u232.c157
-rw-r--r--drivers/usb/serial/ti_fw_3410.h885
-rw-r--r--drivers/usb/serial/ti_fw_5052.h885
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c1842
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h224
-rw-r--r--drivers/usb/serial/usb-serial.c29
-rw-r--r--drivers/usb/serial/usb-serial.h4
-rw-r--r--drivers/usb/serial/visor.c8
-rw-r--r--drivers/usb/serial/visor.h6
-rw-r--r--drivers/usb/storage/scsiglue.c2
-rw-r--r--drivers/usb/storage/transport.c16
-rw-r--r--drivers/usb/storage/unusual_devs.h112
-rw-r--r--drivers/usb/storage/usb.c20
-rw-r--r--drivers/usb/storage/usb.h1
-rw-r--r--drivers/usb/usb-skeleton.c2
-rw-r--r--drivers/w1/dscore.c2
243 files changed, 12590 insertions, 4063 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index 3010e5a54108ab..04fba9e5009b4f 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_DIO) += dio/
obj-$(CONFIG_SBUS) += sbus/
obj-$(CONFIG_ZORRO) += zorro/
obj-$(CONFIG_MAC) += macintosh/
+obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/
obj-$(CONFIG_PARIDE) += block/paride/
obj-$(CONFIG_TC) += tc/
obj-$(CONFIG_USB) += usb/
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 20f597eff8a4bd..934149c1512b1e 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -20,7 +20,7 @@ config PREVENT_FIRMWARE_BUILD
config FW_LOADER
tristate "Hotplug firmware loading support"
- depends on HOTPLUG
+ select HOTPLUG
---help---
This option is provided for the case where no in-kernel-tree modules
require hotplug firmware loading support, but a module built outside
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index be36edd42275a2..3da24059bdf1f8 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -326,7 +326,7 @@ int device_attach(struct device * dev)
if (!error)
/* success, driver matched */
return 1;
- if (error != -ENODEV)
+ if (error != -ENODEV && error != -ENXIO)
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 54b20126c9f796..e22fa1fdf74a69 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -179,6 +179,22 @@ void class_device_remove_file(struct class_device * class_dev,
sysfs_remove_file(&class_dev->kobj, &attr->attr);
}
+int class_device_create_bin_file(struct class_device *class_dev,
+ struct bin_attribute *attr)
+{
+ int error = -EINVAL;
+ if (class_dev)
+ error = sysfs_create_bin_file(&class_dev->kobj, attr);
+ return error;
+}
+
+void class_device_remove_bin_file(struct class_device *class_dev,
+ struct bin_attribute *attr)
+{
+ if (class_dev)
+ sysfs_remove_bin_file(&class_dev->kobj, attr);
+}
+
static int class_device_dev_link(struct class_device * class_dev)
{
if (class_dev->dev)
@@ -576,6 +592,8 @@ EXPORT_SYMBOL_GPL(class_device_get);
EXPORT_SYMBOL_GPL(class_device_put);
EXPORT_SYMBOL_GPL(class_device_create_file);
EXPORT_SYMBOL_GPL(class_device_remove_file);
+EXPORT_SYMBOL_GPL(class_device_create_bin_file);
+EXPORT_SYMBOL_GPL(class_device_remove_bin_file);
EXPORT_SYMBOL_GPL(class_interface_register);
EXPORT_SYMBOL_GPL(class_interface_unregister);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 04451da003a6bb..81251fde251657 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -58,6 +58,41 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
}
/**
+ * platform_get_resource_byname - get a resource for a device by name
+ * @dev: platform device
+ * @type: resource type
+ * @name: resource name
+ */
+struct resource *
+platform_get_resource_byname(struct platform_device *dev, unsigned int type,
+ char *name)
+{
+ int i;
+
+ for (i = 0; i < dev->num_resources; i++) {
+ struct resource *r = &dev->resource[i];
+
+ if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
+ IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
+ if (!strcmp(r->name, name))
+ return r;
+ }
+ return NULL;
+}
+
+/**
+ * platform_get_irq - get an IRQ for a device
+ * @dev: platform device
+ * @name: IRQ name
+ */
+int platform_get_irq_byname(struct platform_device *dev, char *name)
+{
+ struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
+
+ return r ? r->start : 0;
+}
+
+/**
* platform_add_devices - add a numbers of platform devices
* @devs: array of platform devices to add
* @num: number of platform devices in array
@@ -103,13 +138,16 @@ int platform_device_register(struct platform_device * pdev)
for (i = 0; i < pdev->num_resources; i++) {
struct resource *p, *r = &pdev->resource[i];
- r->name = pdev->dev.bus_id;
+ if (r->name == NULL)
+ r->name = pdev->dev.bus_id;
- p = NULL;
- if (r->flags & IORESOURCE_MEM)
- p = &iomem_resource;
- else if (r->flags & IORESOURCE_IO)
- p = &ioport_resource;
+ p = r->parent;
+ if (!p) {
+ if (r->flags & IORESOURCE_MEM)
+ p = &iomem_resource;
+ else if (r->flags & IORESOURCE_IO)
+ p = &ioport_resource;
+ }
if (p && request_resource(p, r)) {
printk(KERN_ERR
@@ -308,3 +346,5 @@ EXPORT_SYMBOL_GPL(platform_device_register_simple);
EXPORT_SYMBOL_GPL(platform_device_unregister);
EXPORT_SYMBOL_GPL(platform_get_irq);
EXPORT_SYMBOL_GPL(platform_get_resource);
+EXPORT_SYMBOL_GPL(platform_get_irq_byname);
+EXPORT_SYMBOL_GPL(platform_get_resource_byname);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 8e1c8535effd01..ce71d5dec3dbc5 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -446,4 +446,12 @@ source "drivers/s390/block/Kconfig"
source "drivers/block/Kconfig.iosched"
+config ATA_OVER_ETH
+ tristate "ATA over Ethernet support"
+ depends on NET
+ default m
+ help
+ This driver provides Support for ATA over Ethernet block
+ devices like the Coraid EtherDrive (R) Storage Blade.
+
endmenu
diff --git a/drivers/block/aoe/Makefile b/drivers/block/aoe/Makefile
new file mode 100644
index 00000000000000..e76d997183c69e
--- /dev/null
+++ b/drivers/block/aoe/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for ATA over Ethernet
+#
+
+obj-$(CONFIG_ATA_OVER_ETH) += aoe.o
+aoe-objs := aoeblk.o aoechr.o aoecmd.o aoedev.o aoemain.o aoenet.o
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
new file mode 100644
index 00000000000000..ef6bcdf19b2f86
--- /dev/null
+++ b/drivers/block/aoe/aoe.h
@@ -0,0 +1,162 @@
+/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+#define VERSION "4"
+#define AOE_MAJOR 152
+#define DEVICE_NAME "aoe"
+#define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * 10 + (aoeminor))
+#define AOEMAJOR(sysminor) ((sysminor) / 10)
+#define AOEMINOR(sysminor) ((sysminor) % 10)
+#define WHITESPACE " \t\v\f\n"
+
+enum {
+ AOECMD_ATA,
+ AOECMD_CFG,
+
+ AOEFL_RSP = (1<<3),
+ AOEFL_ERR = (1<<2),
+
+ AOEAFL_EXT = (1<<6),
+ AOEAFL_DEV = (1<<4),
+ AOEAFL_ASYNC = (1<<1),
+ AOEAFL_WRITE = (1<<0),
+
+ AOECCMD_READ = 0,
+ AOECCMD_TEST,
+ AOECCMD_PTEST,
+ AOECCMD_SET,
+ AOECCMD_FSET,
+
+ AOE_HVER = 0x10,
+};
+
+struct aoe_hdr {
+ unsigned char dst[6];
+ unsigned char src[6];
+ unsigned char type[2];
+ unsigned char verfl;
+ unsigned char err;
+ unsigned char major[2];
+ unsigned char minor;
+ unsigned char cmd;
+ unsigned char tag[4];
+};
+
+struct aoe_atahdr {
+ unsigned char aflags;
+ unsigned char errfeat;
+ unsigned char scnt;
+ unsigned char cmdstat;
+ unsigned char lba0;
+ unsigned char lba1;
+ unsigned char lba2;
+ unsigned char lba3;
+ unsigned char lba4;
+ unsigned char lba5;
+ unsigned char res[2];
+};
+
+struct aoe_cfghdr {
+ unsigned char bufcnt[2];
+ unsigned char fwver[2];
+ unsigned char res;
+ unsigned char aoeccmd;
+ unsigned char cslen[2];
+};
+
+enum {
+ DEVFL_UP = 1, /* device is installed in system and ready for AoE->ATA commands */
+ DEVFL_TKILL = (1<<1), /* flag for timer to know when to kill self */
+ DEVFL_EXT = (1<<2), /* device accepts lba48 commands */
+ DEVFL_CLOSEWAIT = (1<<3), /* device is waiting for all closes to revalidate */
+ DEVFL_WC_UPDATE = (1<<4), /* this device needs to update write cache status */
+ DEVFL_WORKON = (1<<4),
+
+ BUFFL_FAIL = 1,
+};
+
+enum {
+ MAXATADATA = 1024,
+ NPERSHELF = 10,
+ FREETAG = -1,
+ MIN_BUFS = 8,
+};
+
+struct buf {
+ struct list_head bufs;
+ ulong flags;
+ ulong nframesout;
+ char *bufaddr;
+ ulong resid;
+ ulong bv_resid;
+ sector_t sector;
+ struct bio *bio;
+ struct bio_vec *bv;
+};
+
+struct frame {
+ int tag;
+ ulong waited;
+ struct buf *buf;
+ char *bufaddr;
+ int writedatalen;
+ int ndata;
+
+ /* largest possible */
+ char data[sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr)];
+};
+
+struct aoedev {
+ struct aoedev *next;
+ unsigned char addr[6]; /* remote mac addr */
+ ushort flags;
+ ulong sysminor;
+ ulong aoemajor;
+ ulong aoeminor;
+ ulong rttavg; /* round trip average of requests/responses */
+ u16 fw_ver; /* version of blade's firmware */
+ struct work_struct work;/* disk create work struct */
+ struct gendisk *gd;
+ request_queue_t blkq;
+ struct hd_geometry geo;
+ sector_t ssize;
+ struct timer_list timer;
+ spinlock_t lock;
+ struct net_device *ifp; /* interface ed is attached to */
+ struct sk_buff *skblist;/* packets needing to be sent */
+ mempool_t *bufpool; /* for deadlock-free Buf allocation */
+ struct list_head bufq; /* queue of bios to work on */
+ struct buf *inprocess; /* the one we're currently working on */
+ ulong lasttag; /* last tag sent */
+ ulong nframes; /* number of frames below */
+ struct frame *frames;
+};
+
+
+int aoeblk_init(void);
+void aoeblk_exit(void);
+void aoeblk_gdalloc(void *);
+void aoedisk_rm_sysfs(struct aoedev *d);
+
+int aoechr_init(void);
+void aoechr_exit(void);
+void aoechr_error(char *);
+void aoechr_hdump(char *, int len);
+
+void aoecmd_work(struct aoedev *d);
+void aoecmd_cfg(ushort, unsigned char);
+void aoecmd_ata_rsp(struct sk_buff *);
+void aoecmd_cfg_rsp(struct sk_buff *);
+
+int aoedev_init(void);
+void aoedev_exit(void);
+struct aoedev *aoedev_bymac(unsigned char *);
+void aoedev_downdev(struct aoedev *d);
+struct aoedev *aoedev_set(ulong, unsigned char *, struct net_device *, ulong);
+int aoedev_busy(void);
+
+int aoenet_init(void);
+void aoenet_exit(void);
+void aoenet_xmit(struct sk_buff *);
+int is_aoe_netif(struct net_device *ifp);
+int set_aoe_iflist(const char __user *str, size_t size);
+
+u64 mac_addr(char addr[6]);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
new file mode 100644
index 00000000000000..33c19b35fb6729
--- /dev/null
+++ b/drivers/block/aoe/aoeblk.c
@@ -0,0 +1,251 @@
+/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/*
+ * aoeblk.c
+ * block device routines
+ */
+
+#include <linux/hdreg.h>
+#include <linux/blkdev.h>
+#include <linux/fs.h>
+#include <linux/ioctl.h>
+#include <linux/genhd.h>
+#include <linux/netdevice.h>
+#include "aoe.h"
+
+/* add attributes for our block devices in sysfs
+ * (see drivers/block/genhd.c:disk_attr_show, etc.)
+ */
+struct disk_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct gendisk *, char *);
+};
+
+static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
+{
+ struct aoedev *d = disk->private_data;
+
+ return snprintf(page, PAGE_SIZE,
+ "%s%s\n",
+ (d->flags & DEVFL_UP) ? "up" : "down",
+ (d->flags & DEVFL_CLOSEWAIT) ? ",closewait" : "");
+}
+static ssize_t aoedisk_show_mac(struct gendisk * disk, char *page)
+{
+ struct aoedev *d = disk->private_data;
+
+ return snprintf(page, PAGE_SIZE, "%012llx\n", mac_addr(d->addr));
+}
+static ssize_t aoedisk_show_netif(struct gendisk * disk, char *page)
+{
+ struct aoedev *d = disk->private_data;
+
+ return snprintf(page, PAGE_SIZE, "%s\n", d->ifp->name);
+}
+
+static struct disk_attribute disk_attr_state = {
+ .attr = {.name = "state", .mode = S_IRUGO },
+ .show = aoedisk_show_state
+};
+static struct disk_attribute disk_attr_mac = {
+ .attr = {.name = "mac", .mode = S_IRUGO },
+ .show = aoedisk_show_mac
+};
+static struct disk_attribute disk_attr_netif = {
+ .attr = {.name = "netif", .mode = S_IRUGO },
+ .show = aoedisk_show_netif
+};
+
+static void
+aoedisk_add_sysfs(struct aoedev *d)
+{
+ sysfs_create_file(&d->gd->kobj, &disk_attr_state.attr);
+ sysfs_create_file(&d->gd->kobj, &disk_attr_mac.attr);
+ sysfs_create_file(&d->gd->kobj, &disk_attr_netif.attr);
+}
+void
+aoedisk_rm_sysfs(struct aoedev *d)
+{
+ sysfs_remove_link(&d->gd->kobj, "state");
+ sysfs_remove_link(&d->gd->kobj, "mac");
+ sysfs_remove_link(&d->gd->kobj, "netif");
+}
+
+static int
+aoeblk_open(struct inode *inode, struct file *filp)
+{
+ struct aoedev *d;
+
+ d = inode->i_bdev->bd_disk->private_data;
+ return (d->flags & DEVFL_UP) ? 0 : -ENODEV;
+}
+
+static int
+aoeblk_release(struct inode *inode, struct file *filp)
+{
+ struct aoedev *d;
+ ulong flags;
+
+ d = inode->i_bdev->bd_disk->private_data;
+
+ spin_lock_irqsave(&d->lock, flags);
+
+ if (inode->i_bdev->bd_openers == 0 && (d->flags & DEVFL_CLOSEWAIT)) {
+ d->flags &= ~DEVFL_CLOSEWAIT;
+ spin_unlock_irqrestore(&d->lock, flags);
+ aoecmd_cfg(d->aoemajor, d->aoeminor);
+ return 0;
+ }
+ spin_unlock_irqrestore(&d->lock, flags);
+
+ return 0;
+}
+
+static int
+aoeblk_make_request(request_queue_t *q, struct bio *bio)
+{
+ struct aoedev *d;
+ struct buf *buf;
+ struct sk_buff *sl;
+ ulong flags;
+
+ blk_queue_bounce(q, &bio);
+
+ d = bio->bi_bdev->bd_disk->private_data;
+ buf = mempool_alloc(d->bufpool, GFP_NOIO);
+ if (buf == NULL) {
+ printk(KERN_INFO "aoe: aoeblk_make_request: buf allocation "
+ "failure\n");
+ bio_endio(bio, bio->bi_size, -ENOMEM);
+ return 0;
+ }
+ memset(buf, 0, sizeof(*buf));
+ INIT_LIST_HEAD(&buf->bufs);
+ buf->bio = bio;
+ buf->resid = bio->bi_size;
+ buf->sector = bio->bi_sector;
+ buf->bv = buf->bio->bi_io_vec;
+ buf->bv_resid = buf->bv->bv_len;
+ buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset;
+
+ spin_lock_irqsave(&d->lock, flags);
+
+ if ((d->flags & DEVFL_UP) == 0) {
+ printk(KERN_INFO "aoe: aoeblk_make_request: device %ld.%ld is not up\n",
+ d->aoemajor, d->aoeminor);
+ spin_unlock_irqrestore(&d->lock, flags);
+ mempool_free(buf, d->bufpool);
+ bio_endio(bio, bio->bi_size, -ENXIO);
+ return 0;
+ }
+
+ list_add_tail(&buf->bufs, &d->bufq);
+ aoecmd_work(d);
+
+ sl = d->skblist;
+ d->skblist = NULL;
+
+ spin_unlock_irqrestore(&d->lock, flags);
+
+ aoenet_xmit(sl);
+ return 0;
+}
+
+/* This ioctl implementation expects userland to have the device node
+ * permissions set so that only priviledged users can open an aoe
+ * block device directly.
+ */
+static int
+aoeblk_ioctl(struct inode *inode, struct file *filp, uint cmd, ulong arg)
+{
+ struct aoedev *d;
+
+ if (!arg)
+ return -EINVAL;
+
+ d = inode->i_bdev->bd_disk->private_data;
+ if ((d->flags & DEVFL_UP) == 0) {
+ printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n");
+ return -ENODEV;
+ }
+
+ if (cmd == HDIO_GETGEO) {
+ d->geo.start = get_start_sect(inode->i_bdev);
+ if (!copy_to_user((void __user *) arg, &d->geo, sizeof d->geo))
+ return 0;
+ return -EFAULT;
+ }
+ printk(KERN_INFO "aoe: aoeblk_ioctl: unknown ioctl %d\n", cmd);
+ return -EINVAL;
+}
+
+static struct block_device_operations aoe_bdops = {
+ .open = aoeblk_open,
+ .release = aoeblk_release,
+ .ioctl = aoeblk_ioctl,
+ .owner = THIS_MODULE,
+};
+
+/* alloc_disk and add_disk can sleep */
+void
+aoeblk_gdalloc(void *vp)
+{
+ struct aoedev *d = vp;
+ struct gendisk *gd;
+ ulong flags;
+ enum { NPARTITIONS = 16 };
+
+ gd = alloc_disk(NPARTITIONS);
+
+ spin_lock_irqsave(&d->lock, flags);
+
+ if (gd == NULL) {
+ printk(KERN_CRIT "aoe: aoeblk_gdalloc: cannot allocate disk "
+ "structure for %ld.%ld\n", d->aoemajor, d->aoeminor);
+ d->flags &= ~DEVFL_WORKON;
+ spin_unlock_irqrestore(&d->lock, flags);
+ return;
+ }
+
+ blk_queue_make_request(&d->blkq, aoeblk_make_request);
+ gd->major = AOE_MAJOR;
+ gd->first_minor = d->sysminor * NPARTITIONS;
+ gd->fops = &aoe_bdops;
+ gd->private_data = d;
+ gd->capacity = d->ssize;
+ snprintf(gd->disk_name, sizeof gd->disk_name, "etherd/e%ld.%ld",
+ d->aoemajor, d->aoeminor);
+
+ gd->queue = &d->blkq;
+ d->gd = gd;
+ d->flags &= ~DEVFL_WORKON;
+ d->flags |= DEVFL_UP;
+
+ spin_unlock_irqrestore(&d->lock, flags);
+
+ add_disk(gd);
+ aoedisk_add_sysfs(d);
+
+ printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu "
+ "sectors\n", mac_addr(d->addr), d->aoemajor, d->aoeminor,
+ d->fw_ver, (long long)d->ssize);
+}
+
+void __exit
+aoeblk_exit(void)
+{
+ unregister_blkdev(AOE_MAJOR, DEVICE_NAME);
+}
+
+int __init
+aoeblk_init(void)
+{
+ int n;
+
+ n = register_blkdev(AOE_MAJOR, DEVICE_NAME);
+ if (n < 0) {
+ printk(KERN_ERR "aoe: aoeblk_init: can't register major\n");
+ return n;
+ }
+ return 0;
+}
+
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
new file mode 100644
index 00000000000000..3823d1b8fcf831
--- /dev/null
+++ b/drivers/block/aoe/aoechr.c
@@ -0,0 +1,279 @@
+/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/*
+ * aoechr.c
+ * AoE character device driver
+ */
+
+#include <linux/hdreg.h>
+#include <linux/blkdev.h>
+#include "aoe.h"
+
+enum {
+ //MINOR_STAT = 1, (moved to sysfs)
+ MINOR_ERR = 2,
+ MINOR_DISCOVER,
+ MINOR_INTERFACES,
+ MSGSZ = 2048,
+ NARGS = 10,
+ NMSG = 100, /* message backlog to retain */
+};
+
+struct aoe_chardev {
+ ulong minor;
+ char name[32];
+};
+
+enum { EMFL_VALID = 1 };
+
+struct ErrMsg {
+ short flags;
+ short len;
+ char *msg;
+};
+
+static struct ErrMsg emsgs[NMSG];
+static int emsgs_head_idx, emsgs_tail_idx;
+static struct semaphore emsgs_sema;
+static spinlock_t emsgs_lock;
+static int nblocked_emsgs_readers;
+static struct class_simple *aoe_class;
+static struct aoe_chardev chardevs[] = {
+ { MINOR_ERR, "err" },
+ { MINOR_DISCOVER, "discover" },
+ { MINOR_INTERFACES, "interfaces" },
+};
+
+static int
+discover(void)
+{
+ aoecmd_cfg(0xffff, 0xff);
+ return 0;
+}
+
+static int
+interfaces(const char __user *str, size_t size)
+{
+ if (set_aoe_iflist(str, size)) {
+ printk(KERN_CRIT
+ "%s: could not set interface list: %s\n",
+ __FUNCTION__, "too many interfaces");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void
+aoechr_error(char *msg)
+{
+ struct ErrMsg *em;
+ char *mp;
+ ulong flags, n;
+
+ n = strlen(msg);
+
+ spin_lock_irqsave(&emsgs_lock, flags);
+
+ em = emsgs + emsgs_tail_idx;
+ if ((em->flags & EMFL_VALID)) {
+bail: spin_unlock_irqrestore(&emsgs_lock, flags);
+ return;
+ }
+
+ mp = kmalloc(n, GFP_ATOMIC);
+ if (mp == NULL) {
+ printk(KERN_CRIT "aoe: aoechr_error: allocation failure, len=%ld\n", n);
+ goto bail;
+ }
+
+ memcpy(mp, msg, n);
+ em->msg = mp;
+ em->flags |= EMFL_VALID;
+ em->len = n;
+
+ emsgs_tail_idx++;
+ emsgs_tail_idx %= ARRAY_SIZE(emsgs);
+
+ spin_unlock_irqrestore(&emsgs_lock, flags);
+
+ if (nblocked_emsgs_readers)
+ up(&emsgs_sema);
+}
+
+#define PERLINE 16
+void
+aoechr_hdump(char *buf, int n)
+{
+ int bufsiz;
+ char *fbuf;
+ int linelen;
+ char *p, *e, *fp;
+
+ bufsiz = n * 3; /* 2 hex digits and a space */
+ bufsiz += n / PERLINE + 1; /* the newline characters */
+ bufsiz += 1; /* the final '\0' */
+
+ fbuf = kmalloc(bufsiz, GFP_ATOMIC);
+ if (!fbuf) {
+ printk(KERN_INFO
+ "%s: cannot allocate memory\n",
+ __FUNCTION__);
+ return;
+ }
+
+ for (p = buf; n <= 0;) {
+ linelen = n > PERLINE ? PERLINE : n;
+ n -= linelen;
+
+ fp = fbuf;
+ for (e=p+linelen; p<e; p++)
+ fp += sprintf(fp, "%2.2X ", *p & 255);
+ sprintf(fp, "\n");
+ aoechr_error(fbuf);
+ }
+
+ kfree(fbuf);
+}
+
+static ssize_t
+aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp)
+{
+ int ret = -EINVAL;
+
+ switch ((unsigned long) filp->private_data) {
+ default:
+ printk(KERN_INFO "aoe: aoechr_write: can't write to that file.\n");
+ break;
+ case MINOR_DISCOVER:
+ ret = discover();
+ break;
+ case MINOR_INTERFACES:
+ ret = interfaces(buf, cnt);
+ break;
+ }
+ if (ret == 0)
+ ret = cnt;
+ return ret;
+}
+
+static int
+aoechr_open(struct inode *inode, struct file *filp)
+{
+ int n, i;
+
+ n = MINOR(inode->i_rdev);
+ filp->private_data = (void *) (unsigned long) n;
+
+ for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
+ if (chardevs[i].minor == n)
+ return 0;
+ return -EINVAL;
+}
+
+static int
+aoechr_rel(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static ssize_t
+aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
+{
+ int n;
+ char *mp;
+ struct ErrMsg *em;
+ ssize_t len;
+ ulong flags;
+
+ n = (int) filp->private_data;
+ switch (n) {
+ case MINOR_ERR:
+ spin_lock_irqsave(&emsgs_lock, flags);
+loop:
+ em = emsgs + emsgs_head_idx;
+ if ((em->flags & EMFL_VALID) == 0) {
+ if (filp->f_flags & O_NDELAY) {
+ spin_unlock_irqrestore(&emsgs_lock, flags);
+ return -EAGAIN;
+ }
+ nblocked_emsgs_readers++;
+
+ spin_unlock_irqrestore(&emsgs_lock, flags);
+
+ n = down_interruptible(&emsgs_sema);
+
+ spin_lock_irqsave(&emsgs_lock, flags);
+
+ nblocked_emsgs_readers--;
+
+ if (n) {
+ spin_unlock_irqrestore(&emsgs_lock, flags);
+ return -ERESTARTSYS;
+ }
+ goto loop;
+ }
+ if (em->len > cnt) {
+ spin_unlock_irqrestore(&emsgs_lock, flags);
+ return -EAGAIN;
+ }
+ mp = em->msg;
+ len = em->len;
+ em->msg = NULL;
+ em->flags &= ~EMFL_VALID;
+
+ emsgs_head_idx++;
+ emsgs_head_idx %= ARRAY_SIZE(emsgs);
+
+ spin_unlock_irqrestore(&emsgs_lock, flags);
+
+ n = copy_to_user(buf, mp, len);
+ kfree(mp);
+ return n == 0 ? len : -EFAULT;
+ default:
+ return -EFAULT;
+ }
+}
+
+struct file_operations aoe_fops = {
+ .write = aoechr_write,
+ .read = aoechr_read,
+ .open = aoechr_open,
+ .release = aoechr_rel,
+ .owner = THIS_MODULE,
+};
+
+int __init
+aoechr_init(void)
+{
+ int n, i;
+
+ n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops);
+ if (n < 0) {
+ printk(KERN_ERR "aoe: aoechr_init: can't register char device\n");
+ return n;
+ }
+ sema_init(&emsgs_sema, 0);
+ spin_lock_init(&emsgs_lock);
+ aoe_class = class_simple_create(THIS_MODULE, "aoe");
+ if (IS_ERR(aoe_class)) {
+ unregister_chrdev(AOE_MAJOR, "aoechr");
+ return PTR_ERR(aoe_class);
+ }
+ for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
+ class_simple_device_add(aoe_class,
+ MKDEV(AOE_MAJOR, chardevs[i].minor),
+ NULL, chardevs[i].name);
+
+ return 0;
+}
+
+void __exit
+aoechr_exit(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
+ class_simple_device_remove(MKDEV(AOE_MAJOR, chardevs[i].minor));
+ class_simple_destroy(aoe_class);
+ unregister_chrdev(AOE_MAJOR, "aoechr");
+}
+
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
new file mode 100644
index 00000000000000..9ac1a58e783322
--- /dev/null
+++ b/drivers/block/aoe/aoecmd.c
@@ -0,0 +1,627 @@
+/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/*
+ * aoecmd.c
+ * Filesystem request handling methods
+ */
+
+#include <linux/hdreg.h>
+#include <linux/blkdev.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include "aoe.h"
+
+#define TIMERTICK (HZ / 10)
+#define MINTIMER (2 * TIMERTICK)
+#define MAXTIMER (HZ << 1)
+#define MAXWAIT (60 * 3) /* After MAXWAIT seconds, give up and fail dev */
+
+static struct sk_buff *
+new_skb(struct net_device *if_dev, ulong len)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (skb) {
+ skb->nh.raw = skb->mac.raw = skb->data;
+ skb->dev = if_dev;
+ skb->protocol = __constant_htons(ETH_P_AOE);
+ skb->priority = 0;
+ skb_put(skb, len);
+ skb->next = skb->prev = NULL;
+
+ /* tell the network layer not to perform IP checksums
+ * or to get the NIC to do it
+ */
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+ return skb;
+}
+
+static struct sk_buff *
+skb_prepare(struct aoedev *d, struct frame *f)
+{
+ struct sk_buff *skb;
+ char *p;
+
+ skb = new_skb(d->ifp, f->ndata + f->writedatalen);
+ if (!skb) {
+ printk(KERN_INFO "aoe: skb_prepare: failure to allocate skb\n");
+ return NULL;
+ }
+
+ p = skb->mac.raw;
+ memcpy(p, f->data, f->ndata);
+
+ if (f->writedatalen) {
+ p += sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr);
+ memcpy(p, f->bufaddr, f->writedatalen);
+ }
+
+ return skb;
+}
+
+static struct frame *
+getframe(struct aoedev *d, int tag)
+{
+ struct frame *f, *e;
+
+ f = d->frames;
+ e = f + d->nframes;
+ for (; f<e; f++)
+ if (f->tag == tag)
+ return f;
+ return NULL;
+}
+
+/*
+ * Leave the top bit clear so we have tagspace for userland.
+ * The bottom 16 bits are the xmit tick for rexmit/rttavg processing.
+ * This driver reserves tag -1 to mean "unused frame."
+ */
+static int
+newtag(struct aoedev *d)
+{
+ register ulong n;
+
+ n = jiffies & 0xffff;
+ return n |= (++d->lasttag & 0x7fff) << 16;
+}
+
+static int
+aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h)
+{
+ u16 type = __constant_cpu_to_be16(ETH_P_AOE);
+ u16 aoemajor = __cpu_to_be16(d->aoemajor);
+ u32 host_tag = newtag(d);
+ u32 tag = __cpu_to_be32(host_tag);
+
+ memcpy(h->src, d->ifp->dev_addr, sizeof h->src);
+ memcpy(h->dst, d->addr, sizeof h->dst);
+ memcpy(h->type, &type, sizeof type);
+ h->verfl = AOE_HVER;
+ memcpy(h->major, &aoemajor, sizeof aoemajor);
+ h->minor = d->aoeminor;
+ h->cmd = AOECMD_ATA;
+ memcpy(h->tag, &tag, sizeof tag);
+
+ return host_tag;
+}
+
+static void
+aoecmd_ata_rw(struct aoedev *d, struct frame *f)
+{
+ struct aoe_hdr *h;
+ struct aoe_atahdr *ah;
+ struct buf *buf;
+ struct sk_buff *skb;
+ ulong bcnt;
+ register sector_t sector;
+ char writebit, extbit;
+
+ writebit = 0x10;
+ extbit = 0x4;
+
+ buf = d->inprocess;
+
+ sector = buf->sector;
+ bcnt = buf->bv_resid;
+ if (bcnt > MAXATADATA)
+ bcnt = MAXATADATA;
+
+ /* initialize the headers & frame */
+ h = (struct aoe_hdr *) f->data;
+ ah = (struct aoe_atahdr *) (h+1);
+ f->ndata = sizeof *h + sizeof *ah;
+ memset(h, 0, f->ndata);
+ f->tag = aoehdr_atainit(d, h);
+ f->waited = 0;
+ f->buf = buf;
+ f->bufaddr = buf->bufaddr;
+
+ /* set up ata header */
+ ah->scnt = bcnt >> 9;
+ ah->lba0 = sector;
+ ah->lba1 = sector >>= 8;
+ ah->lba2 = sector >>= 8;
+ ah->lba3 = sector >>= 8;
+ if (d->flags & DEVFL_EXT) {
+ ah->aflags |= AOEAFL_EXT;
+ ah->lba4 = sector >>= 8;
+ ah->lba5 = sector >>= 8;
+ } else {
+ extbit = 0;
+ ah->lba3 &= 0x0f;
+ ah->lba3 |= 0xe0; /* LBA bit + obsolete 0xa0 */
+ }
+
+ if (bio_data_dir(buf->bio) == WRITE) {
+ ah->aflags |= AOEAFL_WRITE;
+ f->writedatalen = bcnt;
+ } else {
+ writebit = 0;
+ f->writedatalen = 0;
+ }
+
+ ah->cmdstat = WIN_READ | writebit | extbit;
+
+ /* mark all tracking fields and load out */
+ buf->nframesout += 1;
+ buf->bufaddr += bcnt;
+ buf->bv_resid -= bcnt;
+/* printk(KERN_INFO "aoe: bv_resid=%ld\n", buf->bv_resid); */
+ buf->resid -= bcnt;
+ buf->sector += bcnt >> 9;
+ if (buf->resid == 0) {
+ d->inprocess = NULL;
+ } else if (buf->bv_resid == 0) {
+ buf->bv++;
+ buf->bv_resid = buf->bv->bv_len;
+ buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset;
+ }
+
+ skb = skb_prepare(d, f);
+ if (skb) {
+ skb->next = d->skblist;
+ d->skblist = skb;
+ }
+}
+
+/* enters with d->lock held */
+void
+aoecmd_work(struct aoedev *d)
+{
+ struct frame *f;
+ struct buf *buf;
+loop:
+ f = getframe(d, FREETAG);
+ if (f == NULL)
+ return;
+ if (d->inprocess == NULL) {
+ if (list_empty(&d->bufq))
+ return;
+ buf = container_of(d->bufq.next, struct buf, bufs);
+ list_del(d->bufq.next);
+/*printk(KERN_INFO "aoecmd_work: bi_size=%ld\n", buf->bio->bi_size); */
+ d->inprocess = buf;
+ }
+ aoecmd_ata_rw(d, f);
+ goto loop;
+}
+
+static void
+rexmit(struct aoedev *d, struct frame *f)
+{
+ struct sk_buff *skb;
+ struct aoe_hdr *h;
+ char buf[128];
+ u32 n;
+ u32 net_tag;
+
+ n = newtag(d);
+
+ snprintf(buf, sizeof buf,
+ "%15s e%ld.%ld oldtag=%08x@%08lx newtag=%08x\n",
+ "retransmit",
+ d->aoemajor, d->aoeminor, f->tag, jiffies, n);
+ aoechr_error(buf);
+
+ h = (struct aoe_hdr *) f->data;
+ f->tag = n;
+ net_tag = __cpu_to_be32(n);
+ memcpy(h->tag, &net_tag, sizeof net_tag);
+
+ skb = skb_prepare(d, f);
+ if (skb) {
+ skb->next = d->skblist;
+ d->skblist = skb;
+ }
+}
+
+static int
+tsince(int tag)
+{
+ int n;
+
+ n = jiffies & 0xffff;
+ n -= tag & 0xffff;
+ if (n < 0)
+ n += 1<<16;
+ return n;
+}
+
+static void
+rexmit_timer(ulong vp)
+{
+ struct aoedev *d;
+ struct frame *f, *e;
+ struct sk_buff *sl;
+ register long timeout;
+ ulong flags, n;
+
+ d = (struct aoedev *) vp;
+ sl = NULL;
+
+ /* timeout is always ~150% of the moving average */
+ timeout = d->rttavg;
+ timeout += timeout >> 1;
+
+ spin_lock_irqsave(&d->lock, flags);
+
+ if (d->flags & DEVFL_TKILL) {
+tdie: spin_unlock_irqrestore(&d->lock, flags);
+ return;
+ }
+ f = d->frames;
+ e = f + d->nframes;
+ for (; f<e; f++) {
+ if (f->tag != FREETAG && tsince(f->tag) >= timeout) {
+ n = f->waited += timeout;
+ n /= HZ;
+ if (n > MAXWAIT) { /* waited too long. device failure. */
+ aoedev_downdev(d);
+ goto tdie;
+ }
+ rexmit(d, f);
+ }
+ }
+
+ sl = d->skblist;
+ d->skblist = NULL;
+ if (sl) {
+ n = d->rttavg <<= 1;
+ if (n > MAXTIMER)
+ d->rttavg = MAXTIMER;
+ }
+
+ d->timer.expires = jiffies + TIMERTICK;
+ add_timer(&d->timer);
+
+ spin_unlock_irqrestore(&d->lock, flags);
+
+ aoenet_xmit(sl);
+}
+
+static void
+ataid_complete(struct aoedev *d, unsigned char *id)
+{
+ u64 ssize;
+ u16 n;
+
+ /* word 83: command set supported */
+ n = __le16_to_cpu(*((u16 *) &id[83<<1]));
+
+ /* word 86: command set/feature enabled */
+ n |= __le16_to_cpu(*((u16 *) &id[86<<1]));
+
+ if (n & (1<<10)) { /* bit 10: LBA 48 */
+ d->flags |= DEVFL_EXT;
+
+ /* word 100: number lba48 sectors */
+ ssize = __le64_to_cpu(*((u64 *) &id[100<<1]));
+
+ /* set as in ide-disk.c:init_idedisk_capacity */
+ d->geo.cylinders = ssize;
+ d->geo.cylinders /= (255 * 63);
+ d->geo.heads = 255;
+ d->geo.sectors = 63;
+ } else {
+ d->flags &= ~DEVFL_EXT;
+
+ /* number lba28 sectors */
+ ssize = __le32_to_cpu(*((u32 *) &id[60<<1]));
+
+ /* NOTE: obsolete in ATA 6 */
+ d->geo.cylinders = __le16_to_cpu(*((u16 *) &id[54<<1]));
+ d->geo.heads = __le16_to_cpu(*((u16 *) &id[55<<1]));
+ d->geo.sectors = __le16_to_cpu(*((u16 *) &id[56<<1]));
+ }
+ d->ssize = ssize;
+ d->geo.start = 0;
+ if (d->gd != NULL) {
+ d->gd->capacity = ssize;
+ d->flags |= DEVFL_UP;
+ return;
+ }
+ if (d->flags & DEVFL_WORKON) {
+ printk(KERN_INFO "aoe: ataid_complete: can't schedule work, it's already on! "
+ "(This really shouldn't happen).\n");
+ return;
+ }
+ INIT_WORK(&d->work, aoeblk_gdalloc, d);
+ schedule_work(&d->work);
+ d->flags |= DEVFL_WORKON;
+}
+
+static void
+calc_rttavg(struct aoedev *d, int rtt)
+{
+ register long n;
+
+ n = rtt;
+ if (n < MINTIMER)
+ n = MINTIMER;
+ else if (n > MAXTIMER)
+ n = MAXTIMER;
+
+ /* g == .25; cf. Congestion Avoidance and Control, Jacobson & Karels; 1988 */
+ n -= d->rttavg;
+ d->rttavg += n >> 2;
+}
+
+void
+aoecmd_ata_rsp(struct sk_buff *skb)
+{
+ struct aoedev *d;
+ struct aoe_hdr *hin;
+ struct aoe_atahdr *ahin, *ahout;
+ struct frame *f;
+ struct buf *buf;
+ struct sk_buff *sl;
+ register long n;
+ ulong flags;
+ char ebuf[128];
+
+ hin = (struct aoe_hdr *) skb->mac.raw;
+ d = aoedev_bymac(hin->src);
+ if (d == NULL) {
+ snprintf(ebuf, sizeof ebuf, "aoecmd_ata_rsp: ata response "
+ "for unknown device %d.%d\n",
+ __be16_to_cpu(*((u16 *) hin->major)),
+ hin->minor);
+ aoechr_error(ebuf);
+ return;
+ }
+
+ spin_lock_irqsave(&d->lock, flags);
+
+ f = getframe(d, __be32_to_cpu(*((u32 *) hin->tag)));
+ if (f == NULL) {
+ spin_unlock_irqrestore(&d->lock, flags);
+ snprintf(ebuf, sizeof ebuf,
+ "%15s e%d.%d tag=%08x@%08lx\n",
+ "unexpected rsp",
+ __be16_to_cpu(*((u16 *) hin->major)),
+ hin->minor,
+ __be32_to_cpu(*((u32 *) hin->tag)),
+ jiffies);
+ aoechr_error(ebuf);
+ return;
+ }
+
+ calc_rttavg(d, tsince(f->tag));
+
+ ahin = (struct aoe_atahdr *) (hin+1);
+ ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr));
+ buf = f->buf;
+
+ if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */
+ printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh "
+ "stat=%2.2Xh\n", ahout->cmdstat, ahin->cmdstat);
+ if (buf)
+ buf->flags |= BUFFL_FAIL;
+ } else {
+ switch (ahout->cmdstat) {
+ case WIN_READ:
+ case WIN_READ_EXT:
+ n = ahout->scnt << 9;
+ if (skb->len - sizeof *hin - sizeof *ahin < n) {
+ printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt "
+ "ata data size in read. skb->len=%d\n",
+ skb->len);
+ /* fail frame f? just returning will rexmit. */
+ spin_unlock_irqrestore(&d->lock, flags);
+ return;
+ }
+ memcpy(f->bufaddr, ahin+1, n);
+ case WIN_WRITE:
+ case WIN_WRITE_EXT:
+ break;
+ case WIN_IDENTIFY:
+ if (skb->len - sizeof *hin - sizeof *ahin < 512) {
+ printk(KERN_INFO "aoe: aoecmd_ata_rsp: runt data size "
+ "in ataid. skb->len=%d\n", skb->len);
+ spin_unlock_irqrestore(&d->lock, flags);
+ return;
+ }
+ ataid_complete(d, (char *) (ahin+1));
+ /* d->flags |= DEVFL_WC_UPDATE; */
+ break;
+ default:
+ printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized "
+ "outbound ata command %2.2Xh for %d.%d\n",
+ ahout->cmdstat,
+ __be16_to_cpu(*((u16 *) hin->major)),
+ hin->minor);
+ }
+ }
+
+ if (buf) {
+ buf->nframesout -= 1;
+ if (buf->nframesout == 0 && buf->resid == 0) {
+ n = !(buf->flags & BUFFL_FAIL);
+ bio_endio(buf->bio, buf->bio->bi_size, 0);
+ mempool_free(buf, d->bufpool);
+ }
+ }
+
+ f->buf = NULL;
+ f->tag = FREETAG;
+
+ aoecmd_work(d);
+
+ sl = d->skblist;
+ d->skblist = NULL;
+
+ spin_unlock_irqrestore(&d->lock, flags);
+
+ aoenet_xmit(sl);
+}
+
+void
+aoecmd_cfg(ushort aoemajor, unsigned char aoeminor)
+{
+ struct aoe_hdr *h;
+ struct aoe_cfghdr *ch;
+ struct sk_buff *skb, *sl;
+ struct net_device *ifp;
+ u16 aoe_type = __constant_cpu_to_be16(ETH_P_AOE);
+ u16 net_aoemajor = __cpu_to_be16(aoemajor);
+
+ sl = NULL;
+
+ read_lock(&dev_base_lock);
+ for (ifp = dev_base; ifp; dev_put(ifp), ifp = ifp->next) {
+ dev_hold(ifp);
+ if (!is_aoe_netif(ifp))
+ continue;
+
+ skb = new_skb(ifp, sizeof *h + sizeof *ch);
+ if (skb == NULL) {
+ printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n");
+ continue;
+ }
+ h = (struct aoe_hdr *) skb->mac.raw;
+ memset(h, 0, sizeof *h + sizeof *ch);
+
+ memset(h->dst, 0xff, sizeof h->dst);
+ memcpy(h->src, ifp->dev_addr, sizeof h->src);
+ memcpy(h->type, &aoe_type, sizeof aoe_type);
+ h->verfl = AOE_HVER;
+ memcpy(h->major, &net_aoemajor, sizeof net_aoemajor);
+ h->minor = aoeminor;
+ h->cmd = AOECMD_CFG;
+
+ skb->next = sl;
+ sl = skb;
+ }
+ read_unlock(&dev_base_lock);
+
+ aoenet_xmit(sl);
+}
+
+/*
+ * Since we only call this in one place (and it only prepares one frame)
+ * we just return the skb. Usually we'd chain it up to the d->skblist.
+ */
+static struct sk_buff *
+aoecmd_ata_id(struct aoedev *d)
+{
+ struct aoe_hdr *h;
+ struct aoe_atahdr *ah;
+ struct frame *f;
+ struct sk_buff *skb;
+
+ f = getframe(d, FREETAG);
+ if (f == NULL) {
+ printk(KERN_CRIT "aoe: aoecmd_ata_id: can't get a frame. "
+ "This shouldn't happen.\n");
+ return NULL;
+ }
+
+ /* initialize the headers & frame */
+ h = (struct aoe_hdr *) f->data;
+ ah = (struct aoe_atahdr *) (h+1);
+ f->ndata = sizeof *h + sizeof *ah;
+ memset(h, 0, f->ndata);
+ f->tag = aoehdr_atainit(d, h);
+ f->waited = 0;
+ f->writedatalen = 0;
+
+ /* this message initializes the device, so we reset the rttavg */
+ d->rttavg = MAXTIMER;
+
+ /* set up ata header */
+ ah->scnt = 1;
+ ah->cmdstat = WIN_IDENTIFY;
+ ah->lba3 = 0xa0;
+
+ skb = skb_prepare(d, f);
+
+ /* we now want to start the rexmit tracking */
+ d->flags &= ~DEVFL_TKILL;
+ d->timer.data = (ulong) d;
+ d->timer.function = rexmit_timer;
+ d->timer.expires = jiffies + TIMERTICK;
+ add_timer(&d->timer);
+
+ return skb;
+}
+
+void
+aoecmd_cfg_rsp(struct sk_buff *skb)
+{
+ struct aoedev *d;
+ struct aoe_hdr *h;
+ struct aoe_cfghdr *ch;
+ ulong flags, bufcnt, sysminor, aoemajor;
+ struct sk_buff *sl;
+ enum { MAXFRAMES = 8, MAXSYSMINOR = 255 };
+
+ h = (struct aoe_hdr *) skb->mac.raw;
+ ch = (struct aoe_cfghdr *) (h+1);
+
+ /*
+ * Enough people have their dip switches set backwards to
+ * warrant a loud message for this special case.
+ */
+ aoemajor = __be16_to_cpu(*((u16 *) h->major));
+ if (aoemajor == 0xfff) {
+ printk(KERN_CRIT "aoe: aoecmd_cfg_rsp: Warning: shelf "
+ "address is all ones. Check shelf dip switches\n");
+ return;
+ }
+
+ sysminor = SYSMINOR(aoemajor, h->minor);
+ if (sysminor > MAXSYSMINOR) {
+ printk(KERN_INFO "aoe: aoecmd_cfg_rsp: sysminor %ld too "
+ "large\n", sysminor);
+ return;
+ }
+
+ bufcnt = __be16_to_cpu(*((u16 *) ch->bufcnt));
+ if (bufcnt > MAXFRAMES) /* keep it reasonable */
+ bufcnt = MAXFRAMES;
+
+ d = aoedev_set(sysminor, h->src, skb->dev, bufcnt);
+ if (d == NULL) {
+ printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device set failure\n");
+ return;
+ }
+
+ spin_lock_irqsave(&d->lock, flags);
+
+ if (d->flags & (DEVFL_UP | DEVFL_CLOSEWAIT)) {
+ spin_unlock_irqrestore(&d->lock, flags);
+ return;
+ }
+
+ d->fw_ver = __be16_to_cpu(*((u16 *) ch->fwver));
+
+ /* we get here only if the device is new */
+ sl = aoecmd_ata_id(d);
+
+ spin_unlock_irqrestore(&d->lock, flags);
+
+ aoenet_xmit(sl);
+}
+
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
new file mode 100644
index 00000000000000..715b6c0cfceca3
--- /dev/null
+++ b/drivers/block/aoe/aoedev.c
@@ -0,0 +1,194 @@
+/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/*
+ * aoedev.c
+ * AoE device utility functions; maintains device list.
+ */
+
+#include <linux/hdreg.h>
+#include <linux/blkdev.h>
+#include <linux/netdevice.h>
+#include "aoe.h"
+
+static struct aoedev *devlist;
+static spinlock_t devlist_lock;
+static kmem_cache_t *buf_pool_cache;
+
+struct aoedev *
+aoedev_bymac(unsigned char *macaddr)
+{
+ struct aoedev *d;
+ ulong flags;
+
+ spin_lock_irqsave(&devlist_lock, flags);
+
+ for (d=devlist; d; d=d->next)
+ if (!memcmp(d->addr, macaddr, 6))
+ break;
+
+ spin_unlock_irqrestore(&devlist_lock, flags);
+ return d;
+}
+
+/* called with devlist lock held */
+static struct aoedev *
+aoedev_newdev(ulong nframes)
+{
+ struct aoedev *d;
+ struct frame *f, *e;
+
+ d = kcalloc(1, sizeof *d, GFP_ATOMIC);
+ if (d == NULL)
+ return NULL;
+ f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
+ if (f == NULL) {
+ kfree(d);
+ return NULL;
+ }
+
+ d->nframes = nframes;
+ d->frames = f;
+ e = f + nframes;
+ for (; f<e; f++)
+ f->tag = FREETAG;
+
+ spin_lock_init(&d->lock);
+ init_timer(&d->timer);
+ d->bufpool = mempool_create(MIN_BUFS,
+ mempool_alloc_slab, mempool_free_slab,
+ buf_pool_cache);
+ INIT_LIST_HEAD(&d->bufq);
+ d->next = devlist;
+ devlist = d;
+
+ return d;
+}
+
+void
+aoedev_downdev(struct aoedev *d)
+{
+ struct frame *f, *e;
+ struct buf *buf;
+ struct bio *bio;
+
+ d->flags |= DEVFL_TKILL;
+ del_timer(&d->timer);
+
+ f = d->frames;
+ e = f + d->nframes;
+ for (; f<e; f->tag = FREETAG, f->buf = NULL, f++) {
+ if (f->tag == FREETAG || f->buf == NULL)
+ continue;
+ buf = f->buf;
+ bio = buf->bio;
+ if (--buf->nframesout == 0) {
+ mempool_free(buf, d->bufpool);
+ bio_endio(bio, bio->bi_size, -EIO);
+ }
+ }
+ d->inprocess = NULL;
+
+ while (!list_empty(&d->bufq)) {
+ buf = container_of(d->bufq.next, struct buf, bufs);
+ list_del(d->bufq.next);
+ bio = buf->bio;
+ mempool_free(buf, d->bufpool);
+ bio_endio(bio, bio->bi_size, -EIO);
+ }
+
+ if (d->gd) {
+ struct block_device *bdev = bdget_disk(d->gd, 0);
+ if (bdev) {
+ if (bdev->bd_openers)
+ d->flags |= DEVFL_CLOSEWAIT;
+ bdput(bdev);
+ }
+ d->gd->capacity = 0;
+ }
+
+ d->flags &= ~DEVFL_UP;
+}
+
+struct aoedev *
+aoedev_set(ulong sysminor, unsigned char *addr, struct net_device *ifp, ulong bufcnt)
+{
+ struct aoedev *d;
+ ulong flags;
+
+ spin_lock_irqsave(&devlist_lock, flags);
+
+ for (d=devlist; d; d=d->next)
+ if (d->sysminor == sysminor
+ || memcmp(d->addr, addr, sizeof d->addr) == 0)
+ break;
+
+ if (d == NULL && (d = aoedev_newdev(bufcnt)) == NULL) {
+ spin_unlock_irqrestore(&devlist_lock, flags);
+ printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
+ return NULL;
+ }
+
+ spin_unlock_irqrestore(&devlist_lock, flags);
+ spin_lock_irqsave(&d->lock, flags);
+
+ d->ifp = ifp;
+
+ if (d->sysminor != sysminor
+ || memcmp(d->addr, addr, sizeof d->addr)
+ || (d->flags & DEVFL_UP) == 0) {
+ aoedev_downdev(d); /* flushes outstanding frames */
+ memcpy(d->addr, addr, sizeof d->addr);
+ d->sysminor = sysminor;
+ d->aoemajor = AOEMAJOR(sysminor);
+ d->aoeminor = AOEMINOR(sysminor);
+ }
+
+ spin_unlock_irqrestore(&d->lock, flags);
+ return d;
+}
+
+static void
+aoedev_freedev(struct aoedev *d)
+{
+ if (d->gd) {
+ aoedisk_rm_sysfs(d);
+ del_gendisk(d->gd);
+ put_disk(d->gd);
+ }
+ kfree(d->frames);
+ mempool_destroy(d->bufpool);
+ kfree(d);
+}
+
+void __exit
+aoedev_exit(void)
+{
+ struct aoedev *d;
+ ulong flags;
+
+ flush_scheduled_work();
+
+ while ((d = devlist)) {
+ devlist = d->next;
+
+ spin_lock_irqsave(&d->lock, flags);
+ aoedev_downdev(d);
+ spin_unlock_irqrestore(&d->lock, flags);
+
+ del_timer_sync(&d->timer);
+ aoedev_freedev(d);
+ }
+ kmem_cache_destroy(buf_pool_cache);
+}
+
+int __init
+aoedev_init(void)
+{
+ buf_pool_cache = kmem_cache_create("aoe_bufs",
+ sizeof(struct buf),
+ 0, 0, NULL, NULL);
+ if (buf_pool_cache == NULL)
+ return -ENOMEM;
+ spin_lock_init(&devlist_lock);
+ return 0;
+}
+
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c
new file mode 100644
index 00000000000000..3d42f764952859
--- /dev/null
+++ b/drivers/block/aoe/aoemain.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/*
+ * aoemain.c
+ * Module initialization routines, discover timer
+ */
+
+#include <linux/hdreg.h>
+#include <linux/blkdev.h>
+#include <linux/module.h>
+#include "aoe.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sam Hopkins <sah@coraid.com>");
+MODULE_DESCRIPTION("AoE block/char driver for 2.6.[0-9]+");
+MODULE_VERSION(VERSION);
+
+enum { TINIT, TRUN, TKILL };
+
+static void
+discover_timer(ulong vp)
+{
+ static struct timer_list t;
+ static volatile ulong die;
+ static spinlock_t lock;
+ ulong flags;
+ enum { DTIMERTICK = HZ * 60 }; /* one minute */
+
+ switch (vp) {
+ case TINIT:
+ init_timer(&t);
+ spin_lock_init(&lock);
+ t.data = TRUN;
+ t.function = discover_timer;
+ die = 0;
+ case TRUN:
+ spin_lock_irqsave(&lock, flags);
+ if (!die) {
+ t.expires = jiffies + DTIMERTICK;
+ add_timer(&t);
+ }
+ spin_unlock_irqrestore(&lock, flags);
+
+ aoecmd_cfg(0xffff, 0xff);
+ return;
+ case TKILL:
+ spin_lock_irqsave(&lock, flags);
+ die = 1;
+ spin_unlock_irqrestore(&lock, flags);
+
+ del_timer_sync(&t);
+ default:
+ return;
+ }
+}
+
+static void __exit
+aoe_exit(void)
+{
+ discover_timer(TKILL);
+
+ aoenet_exit();
+ aoeblk_exit();
+ aoechr_exit();
+ aoedev_exit();
+}
+
+static int __init
+aoe_init(void)
+{
+ int n, (**p)(void);
+ int (*fns[])(void) = {
+ aoedev_init, aoechr_init, aoeblk_init, aoenet_init, NULL
+ };
+
+ for (p=fns; *p != NULL; p++) {
+ n = (*p)();
+ if (n) {
+ aoe_exit();
+ printk(KERN_INFO "aoe: aoe_init: initialisation failure.\n");
+ return n;
+ }
+ }
+ printk(KERN_INFO
+ "aoe: aoe_init: AoE v2.6-%s initialised.\n",
+ VERSION);
+
+ discover_timer(TINIT);
+ return 0;
+}
+
+module_init(aoe_init);
+module_exit(aoe_exit);
+
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
new file mode 100644
index 00000000000000..13d3f9ef60dd33
--- /dev/null
+++ b/drivers/block/aoe/aoenet.c
@@ -0,0 +1,175 @@
+/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/*
+ * aoenet.c
+ * Ethernet portion of AoE driver
+ */
+
+#include <linux/hdreg.h>
+#include <linux/blkdev.h>
+#include <linux/netdevice.h>
+#include "aoe.h"
+
+#define NECODES 5
+
+static char *aoe_errlist[] =
+{
+ "no such error",
+ "unrecognized command code",
+ "bad argument parameter",
+ "device unavailable",
+ "config string present",
+ "unsupported version"
+};
+
+enum {
+ IFLISTSZ = 1024,
+};
+
+static char aoe_iflist[IFLISTSZ];
+
+int
+is_aoe_netif(struct net_device *ifp)
+{
+ register char *p, *q;
+ register int len;
+
+ if (aoe_iflist[0] == '\0')
+ return 1;
+
+ for (p = aoe_iflist; *p; p = q + strspn(q, WHITESPACE)) {
+ q = p + strcspn(p, WHITESPACE);
+ if (q != p)
+ len = q - p;
+ else
+ len = strlen(p); /* last token in aoe_iflist */
+
+ if (strlen(ifp->name) == len && !strncmp(ifp->name, p, len))
+ return 1;
+ if (q == p)
+ break;
+ }
+
+ return 0;
+}
+
+int
+set_aoe_iflist(const char __user *user_str, size_t size)
+{
+ if (size >= IFLISTSZ)
+ return -EINVAL;
+
+ if (copy_from_user(aoe_iflist, user_str, size)) {
+ printk(KERN_INFO "aoe: %s: copy from user failed\n", __FUNCTION__);
+ return -EFAULT;
+ }
+ aoe_iflist[size] = 0x00;
+ return 0;
+}
+
+u64
+mac_addr(char addr[6])
+{
+ u64 n = 0;
+ char *p = (char *) &n;
+
+ memcpy(p + 2, addr, 6); /* (sizeof addr != 6) */
+
+ return __be64_to_cpu(n);
+}
+
+static struct sk_buff *
+skb_check(struct sk_buff *skb)
+{
+ if (skb_is_nonlinear(skb))
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)))
+ if (skb_linearize(skb, GFP_ATOMIC) < 0) {
+ dev_kfree_skb(skb);
+ return NULL;
+ }
+ return skb;
+}
+
+void
+aoenet_xmit(struct sk_buff *sl)
+{
+ struct sk_buff *skb;
+
+ while ((skb = sl)) {
+ sl = sl->next;
+ skb->next = skb->prev = NULL;
+ dev_queue_xmit(skb);
+ }
+}
+
+/*
+ * (1) i have no idea if this is redundant, but i can't figure why
+ * the ifp is passed in if it is.
+ *
+ * (2) len doesn't include the header by default. I want this.
+ */
+static int
+aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt)
+{
+ struct aoe_hdr *h;
+ ulong n;
+
+ skb = skb_check(skb);
+ if (!skb)
+ return 0;
+
+ skb->dev = ifp; /* (1) */
+
+ if (!is_aoe_netif(ifp))
+ goto exit;
+
+ skb->len += ETH_HLEN; /* (2) */
+
+ h = (struct aoe_hdr *) skb->mac.raw;
+ n = __be32_to_cpu(*((u32 *) h->tag));
+ if ((h->verfl & AOEFL_RSP) == 0 || (n & 1<<31))
+ goto exit;
+
+ if (h->verfl & AOEFL_ERR) {
+ n = h->err;
+ if (n > NECODES)
+ n = 0;
+ printk(KERN_CRIT "aoe: aoenet_rcv: error packet from %d.%d; "
+ "ecode=%d '%s'\n",
+ __be16_to_cpu(*((u16 *) h->major)), h->minor,
+ h->err, aoe_errlist[n]);
+ goto exit;
+ }
+
+ switch (h->cmd) {
+ case AOECMD_ATA:
+ aoecmd_ata_rsp(skb);
+ break;
+ case AOECMD_CFG:
+ aoecmd_cfg_rsp(skb);
+ break;
+ default:
+ printk(KERN_INFO "aoe: aoenet_rcv: unknown cmd %d\n", h->cmd);
+ }
+exit:
+ dev_kfree_skb(skb);
+ return 0;
+}
+
+static struct packet_type aoe_pt = {
+ .type = __constant_htons(ETH_P_AOE),
+ .func = aoenet_rcv,
+};
+
+int __init
+aoenet_init(void)
+{
+ dev_add_pack(&aoe_pt);
+ return 0;
+}
+
+void __exit
+aoenet_exit(void)
+{
+ dev_remove_pack(&aoe_pt);
+}
+
diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
index 47c344b9c7b524..913f49e56a931d 100644
--- a/drivers/bluetooth/bfusb.c
+++ b/drivers/bluetooth/bfusb.c
@@ -683,7 +683,7 @@ static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *i
bfusb->udev = udev;
bfusb->bulk_in_ep = bulk_in_ep->desc.bEndpointAddress;
bfusb->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress;
- bfusb->bulk_pkt_size = bulk_out_ep->desc.wMaxPacketSize;
+ bfusb->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize);
rwlock_init(&bfusb->lock);
diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
index 33608621d8ce2e..673fcce8e2c82b 100644
--- a/drivers/bluetooth/hci_usb.c
+++ b/drivers/bluetooth/hci_usb.c
@@ -196,7 +196,7 @@ static int hci_usb_intr_rx_submit(struct hci_usb *husb)
BT_DBG("%s", husb->hdev->name);
- size = husb->intr_in_ep->desc.wMaxPacketSize;
+ size = le16_to_cpu(husb->intr_in_ep->desc.wMaxPacketSize);
buf = kmalloc(size, GFP_ATOMIC);
if (!buf)
@@ -271,7 +271,7 @@ static int hci_usb_isoc_rx_submit(struct hci_usb *husb)
int err, mtu, size;
void *buf;
- mtu = husb->isoc_in_ep->desc.wMaxPacketSize;
+ mtu = le16_to_cpu(husb->isoc_in_ep->desc.wMaxPacketSize);
size = mtu * HCI_MAX_ISOC_FRAMES;
buf = kmalloc(size, GFP_ATOMIC);
@@ -528,7 +528,7 @@ static inline int hci_usb_send_isoc(struct hci_usb *husb, struct sk_buff *skb)
urb->transfer_buffer = skb->data;
urb->transfer_buffer_length = skb->len;
- __fill_isoc_desc(urb, skb->len, husb->isoc_out_ep->desc.wMaxPacketSize);
+ __fill_isoc_desc(urb, skb->len, le16_to_cpu(husb->isoc_out_ep->desc.wMaxPacketSize));
_urb->priv = skb;
return __tx_submit(husb, _urb);
@@ -900,10 +900,10 @@ static int hci_usb_probe(struct usb_interface *intf, const struct usb_device_id
switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
case USB_ENDPOINT_XFER_ISOC:
- if (ep->desc.wMaxPacketSize < size ||
+ if (le16_to_cpu(ep->desc.wMaxPacketSize) < size ||
uif->desc.bAlternateSetting != isoc)
break;
- size = ep->desc.wMaxPacketSize;
+ size = le16_to_cpu(ep->desc.wMaxPacketSize);
isoc_alts = uif->desc.bAlternateSetting;
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 81536e3d70f097..0c97672bffb376 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -962,7 +962,6 @@ extern unsigned int drm_cards_limit;
extern drm_minor_t *drm_minors;
extern struct class_simple *drm_class;
extern struct proc_dir_entry *drm_proc_root;
-extern struct file_operations drm_stub_fops;
/* Proc support (drm_proc.h) */
extern int drm_proc_init(drm_device_t *dev,
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 13b11270a9f249..0937544762da76 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -207,10 +207,9 @@ static struct file_operations misc_fops = {
int misc_register(struct miscdevice * misc)
{
struct miscdevice *c;
- struct class_device *class;
dev_t dev;
int err;
-
+
down(&misc_sem);
list_for_each_entry(c, &misc_list, list) {
if (c->minor == misc->minor) {
@@ -224,8 +223,7 @@ int misc_register(struct miscdevice * misc)
while (--i >= 0)
if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
break;
- if (i<0)
- {
+ if (i<0) {
up(&misc_sem);
return -EBUSY;
}
@@ -240,10 +238,10 @@ int misc_register(struct miscdevice * misc)
}
dev = MKDEV(MISC_MAJOR, misc->minor);
- class = class_simple_device_add(misc_class, dev,
- misc->dev, misc->name);
- if (IS_ERR(class)) {
- err = PTR_ERR(class);
+ misc->class = class_simple_device_add(misc_class, dev,
+ misc->dev, misc->name);
+ if (IS_ERR(misc->class)) {
+ err = PTR_ERR(misc->class);
goto out;
}
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index cdfe0db28784e9..42bce3eea236ee 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -571,12 +571,6 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
char fw_ver_str[20];
unsigned char option_switches, dummy;
- /* See if the device offered us matches what we can accept */
- if ((udev->descriptor.idVendor != USB_PCWD_VENDOR_ID) ||
- (udev->descriptor.idProduct != USB_PCWD_PRODUCT_ID)) {
- return -ENODEV;
- }
-
cards_found++;
if (cards_found > 1) {
printk(KERN_ERR PFX "This driver only supports 1 device\n");
@@ -621,7 +615,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
usb_pcwd->udev = udev;
usb_pcwd->interface = interface;
usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
- usb_pcwd->intr_size = (endpoint->wMaxPacketSize > 8 ? endpoint->wMaxPacketSize : 8);
+ usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8);
/* set up the memory buffer's */
if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, SLAB_ATOMIC, &usb_pcwd->intr_dma))) {
diff --git a/drivers/eisa/Makefile b/drivers/eisa/Makefile
index f24512dd150bad..70abf93fe6b0e8 100644
--- a/drivers/eisa/Makefile
+++ b/drivers/eisa/Makefile
@@ -1,8 +1,5 @@
# Makefile for the Linux device tree
-# Being anal sometimes saves a crash/reboot cycle... ;-)
-EXTRA_CFLAGS := -Werror
-
obj-$(CONFIG_EISA) += eisa-bus.o
obj-${CONFIG_EISA_PCI_EISA} += pci_eisa.o
diff --git a/drivers/i2c/algos/Kconfig b/drivers/i2c/algos/Kconfig
index cf9832bdc7463a..30408015d231fa 100644
--- a/drivers/i2c/algos/Kconfig
+++ b/drivers/i2c/algos/Kconfig
@@ -53,5 +53,18 @@ config I2C_ALGO8XX
tristate "MPC8xx CPM I2C interface"
depends on 8xx && I2C
+config I2C_ALGO_SIBYTE
+ tristate "SiByte SMBus interface"
+ depends on SIBYTE_SB1xxx_SOC && I2C
+ help
+ Supports the SiByte SOC on-chip I2C interfaces (2 channels).
+
+config I2C_ALGO_SGI
+ tristate "I2C SGI interfaces"
+ depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)
+ help
+ Supports the SGI interfaces like the ones found on SGI Indy VINO
+ or SGI O2 MACE.
+
endmenu
diff --git a/drivers/i2c/algos/Makefile b/drivers/i2c/algos/Makefile
index 3545644be0f6a2..867fe1f67401c3 100644
--- a/drivers/i2c/algos/Makefile
+++ b/drivers/i2c/algos/Makefile
@@ -6,6 +6,8 @@ obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o
obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o
obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o
obj-$(CONFIG_I2C_ALGOITE) += i2c-algo-ite.o
+obj-$(CONFIG_I2C_ALGO_SIBYTE) += i2c-algo-sibyte.o
+obj-$(CONFIG_I2C_ALGO_SGI) += i2c-algo-sgi.o
ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 4ea4c7928b8e1b..fb5b732238ed81 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -511,8 +511,8 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
static u32 bit_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
- I2C_FUNC_PROTOCOL_MANGLING;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
}
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index aaad68602394d9..a8724ac9282d77 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -189,7 +189,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
state = pca_status(adap);
if ( state != 0xF8 ) {
- printk(KERN_ERR DRIVER ": bus is not idle. status is %#04x\n", state );
+ dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state );
/* FIXME: what to do. Force stop ? */
return -EREMOTEIO;
}
@@ -328,7 +328,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
static u32 pca_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static int pca_init(struct i2c_algo_pca_data *adap)
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 6dc807abc157de..fbbe1d2bdcc422 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -414,8 +414,8 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
static u32 pcf_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
- I2C_FUNC_PROTOCOL_MANGLING;
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
}
/* -----exported algorithm data: ------------------------------------- */
diff --git a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
new file mode 100644
index 00000000000000..b4e0a065b78b27
--- /dev/null
+++ b/drivers/i2c/algos/i2c-algo-sgi.c
@@ -0,0 +1,189 @@
+/*
+ * i2c-algo-sgi.c: i2c driver algorithms for SGI adapters.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-sgi.h>
+
+
+#define SGI_I2C_FORCE_IDLE (0 << 0)
+#define SGI_I2C_NOT_IDLE (1 << 0)
+#define SGI_I2C_WRITE (0 << 1)
+#define SGI_I2C_READ (1 << 1)
+#define SGI_I2C_RELEASE_BUS (0 << 2)
+#define SGI_I2C_HOLD_BUS (1 << 2)
+#define SGI_I2C_XFER_DONE (0 << 4)
+#define SGI_I2C_XFER_BUSY (1 << 4)
+#define SGI_I2C_ACK (0 << 5)
+#define SGI_I2C_NACK (1 << 5)
+#define SGI_I2C_BUS_OK (0 << 7)
+#define SGI_I2C_BUS_ERR (1 << 7)
+
+#define get_control() adap->getctrl(adap->data)
+#define set_control(val) adap->setctrl(adap->data, val)
+#define read_data() adap->rdata(adap->data)
+#define write_data(val) adap->wdata(adap->data, val)
+
+
+static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ for (i = 0; i < adap->xfer_timeout; i++) {
+ if ((get_control() & SGI_I2C_XFER_BUSY) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int wait_ack(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ if (wait_xfer_done(adap))
+ return -ETIMEDOUT;
+ for (i = 0; i < adap->ack_timeout; i++) {
+ if ((get_control() & SGI_I2C_NACK) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int force_idle(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ set_control(SGI_I2C_FORCE_IDLE);
+ for (i = 0; i < adap->xfer_timeout; i++) {
+ if ((get_control() & SGI_I2C_NOT_IDLE) == 0)
+ goto out;
+ udelay(1);
+ }
+ return -ETIMEDOUT;
+out:
+ if (get_control() & SGI_I2C_BUS_ERR)
+ return -EIO;
+ return 0;
+}
+
+static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
+ int rd)
+{
+ if (rd)
+ set_control(SGI_I2C_NOT_IDLE);
+ /* Check if bus is idle, eventually force it to do so */
+ if (get_control() & SGI_I2C_NOT_IDLE)
+ if (force_idle(adap))
+ return -EIO;
+ /* Write out the i2c chip address and specify operation */
+ set_control(SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
+ if (rd)
+ addr |= 1;
+ write_data(addr);
+ if (wait_ack(adap))
+ return -EIO;
+ return 0;
+}
+
+static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+ unsigned int len)
+{
+ int i;
+
+ set_control(SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
+ for (i = 0; i < len; i++) {
+ if (wait_xfer_done(adap))
+ return -EIO;
+ buf[i] = read_data();
+ }
+ set_control(SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
+
+ return 0;
+
+}
+
+static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+ unsigned int len)
+{
+ int i;
+
+ /* We are already in write state */
+ for (i = 0; i < len; i++) {
+ write_data(buf[i]);
+ if (wait_ack(adap))
+ return -EIO;
+ }
+ return 0;
+}
+
+static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+ int num)
+{
+ struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
+ struct i2c_msg *p;
+ int i, err = 0;
+
+ for (i = 0; !err && i < num; i++) {
+ p = &msgs[i];
+ err = do_address(adap, p->addr, p->flags & I2C_M_RD);
+ if (err || !p->len)
+ continue;
+ if (p->flags & I2C_M_RD)
+ err = i2c_read(adap, p->buf, p->len);
+ else
+ err = i2c_write(adap, p->buf, p->len);
+ }
+
+ return err;
+}
+
+static u32 sgi_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm sgi_algo = {
+ .name = "SGI algorithm",
+ .id = I2C_ALGO_SGI,
+ .master_xfer = sgi_xfer,
+ .functionality = sgi_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_sgi_add_bus(struct i2c_adapter *adap)
+{
+ adap->id |= sgi_algo.id;
+ adap->algo = &sgi_algo;
+
+ return i2c_add_adapter(adap);
+}
+
+
+int i2c_sgi_del_bus(struct i2c_adapter *adap)
+{
+ return i2c_del_adapter(adap);
+}
+
+EXPORT_SYMBOL(i2c_sgi_add_bus);
+EXPORT_SYMBOL(i2c_sgi_del_bus);
+
+MODULE_AUTHOR("Ladislav Michl <ladis@linux-mips.org>");
+MODULE_DESCRIPTION("I2C-Bus SGI algorithm");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
new file mode 100644
index 00000000000000..e4d41caf0b26bc
--- /dev/null
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -0,0 +1,231 @@
+/* ------------------------------------------------------------------------- */
+/* i2c-algo-sibyte.c i2c driver algorithms for bit-shift adapters */
+/* ------------------------------------------------------------------------- */
+/* Copyright (C) 2001,2002,2003 Broadcom Corporation
+ Copyright (C) 1995-2000 Simon G. Vogl
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+/* ------------------------------------------------------------------------- */
+
+/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
+ Frodo Looijaard <frodol@dds.nl>. */
+
+/* Ported for SiByte SOCs by Broadcom Corporation. */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_smbus.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-sibyte.h>
+
+/* ----- global defines ----------------------------------------------- */
+#define SMB_CSR(a,r) ((long)(a->reg_base + r))
+
+/* ----- global variables --------------------------------------------- */
+
+/* module parameters:
+ */
+static int bit_scan=0; /* have a look at what's hanging 'round */
+
+
+static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size, union i2c_smbus_data * data)
+{
+ struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+ int data_bytes = 0;
+ int error;
+
+ while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ csr_out32((V_SMB_ADDR(addr) | (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
+ V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
+ break;
+ case I2C_SMBUS_BYTE:
+ if (read_write == I2C_SMBUS_READ) {
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ data_bytes = 1;
+ } else {
+ csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ }
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+ if (read_write == I2C_SMBUS_READ) {
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ data_bytes = 1;
+ } else {
+ csr_out32(V_SMB_LB(data->byte), SMB_CSR(adap, R_SMB_DATA));
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ }
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+ if (read_write == I2C_SMBUS_READ) {
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ data_bytes = 2;
+ } else {
+ csr_out32(V_SMB_LB(data->word & 0xff), SMB_CSR(adap, R_SMB_DATA));
+ csr_out32(V_SMB_MB(data->word >> 8), SMB_CSR(adap, R_SMB_DATA));
+ csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+ SMB_CSR(adap, R_SMB_START));
+ }
+ break;
+ default:
+ return -1; /* XXXKW better error code? */
+ }
+
+ while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
+
+ error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
+ if (error & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
+ return -1; /* XXXKW better error code? */
+ }
+
+ if (data_bytes == 1)
+ data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
+ if (data_bytes == 2)
+ data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
+
+ return 0;
+}
+
+static int algo_control(struct i2c_adapter *adapter,
+ unsigned int cmd, unsigned long arg)
+{
+ return 0;
+}
+
+static u32 bit_func(struct i2c_adapter *adap)
+{
+ return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
+}
+
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static struct i2c_algorithm i2c_sibyte_algo = {
+ "SiByte algorithm",
+ I2C_ALGO_SIBYTE,
+ NULL, /* master_xfer */
+ smbus_xfer, /* smbus_xfer */
+ NULL, /* slave_xmit */
+ NULL, /* slave_recv */
+ algo_control, /* ioctl */
+ bit_func, /* functionality */
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
+{
+ int i;
+ struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+
+ /* register new adapter to i2c module... */
+
+ i2c_adap->id |= i2c_sibyte_algo.id;
+ i2c_adap->algo = &i2c_sibyte_algo;
+
+ /* Set the frequency to 100 kHz */
+ csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
+ csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
+
+ /* scan bus */
+ if (bit_scan) {
+ union i2c_smbus_data data;
+ int rc;
+ printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
+ i2c_adap->name);
+ for (i = 0x00; i < 0x7f; i++) {
+ /* XXXKW is this a realistic probe? */
+ rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
+ I2C_SMBUS_BYTE_DATA, &data);
+ if (!rc) {
+ printk("(%02x)",i);
+ } else
+ printk(".");
+ }
+ printk("\n");
+ }
+
+#ifdef MODULE
+ MOD_INC_USE_COUNT;
+#endif
+ i2c_add_adapter(i2c_adap);
+
+ return 0;
+}
+
+
+int i2c_sibyte_del_bus(struct i2c_adapter *adap)
+{
+ int res;
+
+ if ((res = i2c_del_adapter(adap)) < 0)
+ return res;
+
+#ifdef MODULE
+ MOD_DEC_USE_COUNT;
+#endif
+ return 0;
+}
+
+int __init i2c_algo_sibyte_init (void)
+{
+ printk("i2c-algo-sibyte.o: i2c SiByte algorithm module\n");
+ return 0;
+}
+
+
+EXPORT_SYMBOL(i2c_sibyte_add_bus);
+EXPORT_SYMBOL(i2c_sibyte_del_bus);
+
+#ifdef MODULE
+MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
+MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
+MODULE_PARM(bit_scan, "i");
+MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+ return i2c_algo_sibyte_init();
+}
+
+void cleanup_module(void)
+{
+}
+#endif
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index d0e7da45523a23..9d44bd94b712e3 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -143,8 +143,14 @@ config I2C_IBM_IIC
will be called i2c-ibm_iic.
config I2C_IOP3XX
- tristate "Intel XScale IOP3xx on-chip I2C interface"
- depends on ARCH_IOP3XX && I2C
+ tristate "Intel IOP3xx and IXP4xx on-chip I2C interface"
+ depends on (ARCH_IOP3XX || ARCH_IXP4XX) && I2C
+ help
+ Say Y here if you want to use the IIC bus controller on
+ the Intel IOP3xx I/O Processors or IXP4xx Network Processors.
+
+ This driver can also be built as a module. If so, the module
+ will be called i2c-iop3xx.
config I2C_ISA
tristate "ISA Bus support"
@@ -323,6 +329,12 @@ config I2C_SAVAGE4
This driver can also be built as a module. If so, the module
will be called i2c-savage4.
+config I2C_SIBYTE
+ tristate "SiByte SMBus interface"
+ depends on SIBYTE_SB1xxx_SOC && I2C
+ help
+ Supports the SiByte SOC on-chip I2C interfaces (2 channels).
+
config SCx200_I2C
tristate "NatSemi SCx200 I2C using GPIO pins"
depends on SCx200_GPIO && I2C
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index e414a1d1ec7729..fd58b2e609a3b4 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
+obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index dcc9365676d0ca..b00cd409822192 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -487,12 +487,7 @@ static struct i2c_adapter ali1535_adapter = {
};
static struct pci_device_id ali1535_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_AL,
- .device = PCI_DEVICE_ID_AL_M7101,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
{ },
};
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index b3ee9a812bee6f..35710818fe47cb 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -306,7 +306,7 @@ static void ali1563_enable(struct pci_dev * dev)
pci_write_config_word(dev,ALI1563_SMBBA,ctrl);
}
-static int __init ali1563_setup(struct pci_dev * dev)
+static int __devinit ali1563_setup(struct pci_dev * dev)
{
u16 ctrl;
@@ -362,7 +362,7 @@ static struct i2c_adapter ali1563_adapter = {
.algo = &ali1563_algorithm,
};
-static int __init ali1563_probe(struct pci_dev * dev,
+static int __devinit ali1563_probe(struct pci_dev * dev,
const struct pci_device_id * id_table)
{
int error;
@@ -378,19 +378,14 @@ static int __init ali1563_probe(struct pci_dev * dev,
return error;
}
-static void __exit ali1563_remove(struct pci_dev * dev)
+static void __devexit ali1563_remove(struct pci_dev * dev)
{
i2c_del_adapter(&ali1563_adapter);
ali1563_shutdown(dev);
}
static struct pci_device_id __devinitdata ali1563_id_table[] = {
- {
- .vendor = PCI_VENDOR_ID_AL,
- .device = PCI_DEVICE_ID_AL_M1563,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) },
{},
};
@@ -400,7 +395,7 @@ static struct pci_driver ali1563_pci_driver = {
.name = "ali1563_i2c",
.id_table = ali1563_id_table,
.probe = ali1563_probe,
- .remove = ali1563_remove,
+ .remove = __devexit_p(ali1563_remove),
};
static int __init ali1563_init(void)
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 8e13b834197185..5bd6a4a77c1eec 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -477,12 +477,7 @@ static struct i2c_adapter ali15x3_adapter = {
};
static struct pci_device_id ali15x3_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_AL,
- .device = PCI_DEVICE_ID_AL_M7101,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index 35a1835193c8c5..eca5ed3738b857 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -316,11 +316,16 @@ static const char* chipname[] = {
};
static struct pci_device_id amd756_ids[] = {
- {PCI_VENDOR_ID_AMD, 0x740B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD756 },
- {PCI_VENDOR_ID_AMD, 0x7413, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD766 },
- {PCI_VENDOR_ID_AMD, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768 },
- {PCI_VENDOR_ID_AMD, 0x746B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111 },
- {PCI_VENDOR_ID_NVIDIA, 0x01B4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NFORCE },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B),
+ .driver_data = AMD756 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413),
+ .driver_data = AMD766 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443),
+ .driver_data = AMD768 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS),
+ .driver_data = AMD8111 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS),
+ .driver_data = NFORCE },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index 5eb4d38bcf9d55..af22b401a38bb3 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -332,7 +332,7 @@ static struct i2c_algorithm smbus_algorithm = {
static struct pci_device_id amd8111_ids[] = {
- { 0x1022, 0x746a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 7480fd0b4e6945..e0cb3b0f92faba 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -111,12 +111,7 @@ static struct i2c_adapter hydra_adap = {
};
static struct pci_device_id hydra_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_APPLE,
- .device = PCI_DEVICE_ID_APPLE_HYDRA,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 8d6ec152573543..b4acf8891281d3 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -548,54 +548,14 @@ static struct i2c_adapter i801_adapter = {
};
static struct pci_device_id i801_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801AA_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801AB_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801BA_2,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801CA_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801DB_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82801EB_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_ESB_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_ICH6_16,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index 844aa3e03256db..961241b19f8869 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -1,35 +1,30 @@
/* ------------------------------------------------------------------------- */
-/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx */
+/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx & IXP46x */
/* ------------------------------------------------------------------------- */
-/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
- * <Peter dot Milne at D hyphen TACQ dot 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, version 2.
-
-
- 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
-/* ------------------------------------------------------------------------- */
-/*
- With acknowledgements to i2c-algo-ibm_ocp.c by
- Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
-
- And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
-
- Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
-
- And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
- Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
-
- ---------------------------------------------------------------------------*/
+/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd
+ * <Peter dot Milne at D hyphen TACQ dot com>
+ *
+ * With acknowledgements to i2c-algo-ibm_ocp.c by
+ * Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com
+ *
+ * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund:
+ *
+ * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund
+ *
+ * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com>
+ *
+ * Major cleanup by Deepak Saxena <dsaxena@plexity.net>, 01/2005:
+ *
+ * - Use driver model to pass per-chip info instead of hardcoding and #ifdefs
+ * - Use ioremap/__raw_readl/__raw_writel instead of direct dereference
+ * - Make it work with IXP46x chips
+ * - Cleanup function names, coding style, etc
+ *
+ * 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, version 2.
+ */
#include <linux/config.h>
#include <linux/interrupt.h>
@@ -40,24 +35,18 @@
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/sched.h>
+#include <linux/device.h>
#include <linux/i2c.h>
+#include <asm/io.h>
-#include <asm/arch-iop3xx/iop321.h>
-#include <asm/arch-iop3xx/iop321-irqs.h>
#include "i2c-iop3xx.h"
+/* global unit counter */
+static int i2c_id = 0;
-/* ----- global defines ----------------------------------------------- */
-#define PASSERT(x) do { if (!(x) ) \
- printk(KERN_CRIT "PASSERT %s in %s:%d\n", #x, __FILE__, __LINE__ );\
- } while (0)
-
-
-/* ----- global variables --------------------------------------------- */
-
-
-static inline unsigned char iic_cook_addr(struct i2c_msg *msg)
+static inline unsigned char
+iic_cook_addr(struct i2c_msg *msg)
{
unsigned char addr;
@@ -66,103 +55,110 @@ static inline unsigned char iic_cook_addr(struct i2c_msg *msg)
if (msg->flags & I2C_M_RD)
addr |= 1;
- /* PGM: what is M_REV_DIR_ADDR - do we need it ?? */
+ /*
+ * Read or Write?
+ */
if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
return addr;
}
-
-static inline void iop3xx_adap_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static void
+iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
/* Follows devman 9.3 */
- *iop3xx_adap->biu->CR = IOP321_ICR_UNIT_RESET;
- *iop3xx_adap->biu->SR = IOP321_ISR_CLEARBITS;
- *iop3xx_adap->biu->CR = 0;
+ __raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET);
+ __raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET);
+ __raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET);
}
-static inline void iop3xx_adap_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static void
+iop3xx_i2c_set_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
- *iop3xx_adap->biu->SAR = MYSAR;
+ __raw_writel(MYSAR, iop3xx_adap->ioaddr + SAR_OFFSET);
}
-static inline void iop3xx_adap_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static void
+iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
- u32 cr = IOP321_ICR_GCD|IOP321_ICR_SCLEN|IOP321_ICR_UE;
+ u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
+
+ /*
+ * Everytime unit enable is asserted, GPOD needs to be cleared
+ * on IOP321 to avoid data corruption on the bus.
+ */
+#ifdef CONFIG_ARCH_IOP321
+#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
+#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
+ *IOP321_GPOD &= (iop3xx_adap->id == 0) ? ~IOP321_GPOD_I2C0 :
+ ~IOP321_GPOD_I2C1;
+#endif
/* NB SR bits not same position as CR IE bits :-( */
- iop3xx_adap->biu->SR_enabled =
- IOP321_ISR_ALD | IOP321_ISR_BERRD |
- IOP321_ISR_RXFULL | IOP321_ISR_TXEMPTY;
+ iop3xx_adap->SR_enabled =
+ IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD |
+ IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY;
- cr |= IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
- IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE;
+ cr |= IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
+ IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE;
- *iop3xx_adap->biu->CR = cr;
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
}
-static void iop3xx_adap_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static void
+iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
- unsigned cr = *iop3xx_adap->biu->CR;
+ unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
- cr &= ~(IOP321_ICR_MSTART | IOP321_ICR_TBYTE |
- IOP321_ICR_MSTOP | IOP321_ICR_SCLEN);
- *iop3xx_adap->biu->CR = cr;
-}
+ cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE |
+ IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN);
-static void iop3xx_adap_final_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap)
-{
- unsigned cr = *iop3xx_adap->biu->CR;
-
- cr &= ~(IOP321_ICR_ALDIE | IOP321_ICR_BERRIE |
- IOP321_ICR_RXFULLIE | IOP321_ICR_TXEMPTYIE);
- iop3xx_adap->biu->SR_enabled = 0;
- *iop3xx_adap->biu->CR = cr;
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
}
/*
* NB: the handler has to clear the source of the interrupt!
* Then it passes the SR flags of interest to BH via adap data
*/
-static irqreturn_t iop3xx_i2c_handler(int this_irq,
- void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t
+iop3xx_i2c_irq_handler(int this_irq, void *dev_id, struct pt_regs *regs)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id;
+ u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET);
- u32 sr = *iop3xx_adap->biu->SR;
-
- if ((sr &= iop3xx_adap->biu->SR_enabled)) {
- *iop3xx_adap->biu->SR = sr;
- iop3xx_adap->biu->SR_received |= sr;
+ if ((sr &= iop3xx_adap->SR_enabled)) {
+ __raw_writel(sr, iop3xx_adap->ioaddr + SR_OFFSET);
+ iop3xx_adap->SR_received |= sr;
wake_up_interruptible(&iop3xx_adap->waitq);
}
return IRQ_HANDLED;
}
/* check all error conditions, clear them , report most important */
-static int iop3xx_adap_error(u32 sr)
+static int
+iop3xx_i2c_error(u32 sr)
{
int rc = 0;
- if ((sr&IOP321_ISR_BERRD)) {
+ if ((sr & IOP3XX_ISR_BERRD)) {
if ( !rc ) rc = -I2C_ERR_BERR;
}
- if ((sr&IOP321_ISR_ALD)) {
+ if ((sr & IOP3XX_ISR_ALD)) {
if ( !rc ) rc = -I2C_ERR_ALD;
}
return rc;
}
-static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
+static inline u32
+iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
{
unsigned long flags;
u32 sr;
spin_lock_irqsave(&iop3xx_adap->lock, flags);
- sr = iop3xx_adap->biu->SR_received;
- iop3xx_adap->biu->SR_received = 0;
+ sr = iop3xx_adap->SR_received;
+ iop3xx_adap->SR_received = 0;
spin_unlock_irqrestore(&iop3xx_adap->lock, flags);
return sr;
@@ -175,9 +171,10 @@ static inline u32 get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap)
typedef int (* compare_func)(unsigned test, unsigned mask);
/* returns 1 on correct comparison */
-static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
- unsigned flags, unsigned* status,
- compare_func compare)
+static int
+iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ unsigned flags, unsigned* status,
+ compare_func compare)
{
unsigned sr = 0;
int interrupted;
@@ -187,13 +184,13 @@ static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
do {
interrupted = wait_event_interruptible_timeout (
iop3xx_adap->waitq,
- (done = compare( sr = get_srstat(iop3xx_adap),flags )),
- iop3xx_adap->timeout
+ (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )),
+ 1 * HZ;
);
- if ((rc = iop3xx_adap_error(sr)) < 0) {
+ if ((rc = iop3xx_i2c_error(sr)) < 0) {
*status = sr;
return rc;
- }else if (!interrupted) {
+ } else if (!interrupted) {
*status = sr;
return -ETIMEDOUT;
}
@@ -207,141 +204,131 @@ static int iop3xx_adap_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap,
/*
* Concrete compare_funcs
*/
-static int all_bits_clear(unsigned test, unsigned mask)
+static int
+all_bits_clear(unsigned test, unsigned mask)
{
return (test & mask) == 0;
}
-static int any_bits_set(unsigned test, unsigned mask)
+
+static int
+any_bits_set(unsigned test, unsigned mask)
{
return (test & mask) != 0;
}
-static int iop3xx_adap_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+static int
+iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
- return iop3xx_adap_wait_event(
+ return iop3xx_i2c_wait_event(
iop3xx_adap,
- IOP321_ISR_TXEMPTY|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+ IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
status, any_bits_set);
}
-static int iop3xx_adap_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
+static int
+iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
- return iop3xx_adap_wait_event(
+ return iop3xx_i2c_wait_event(
iop3xx_adap,
- IOP321_ISR_RXFULL|IOP321_ISR_ALD|IOP321_ISR_BERRD,
+ IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD,
status, any_bits_set);
}
-static int iop3xx_adap_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
-{
- return iop3xx_adap_wait_event(
- iop3xx_adap, IOP321_ISR_UNITBUSY, status, all_bits_clear);
-}
-
-/*
- * Description: This performs the IOP3xx initialization sequence
- * Valid for IOP321. Maybe valid for IOP310?.
- */
-static int iop3xx_adap_init (struct i2c_algo_iop3xx_data *iop3xx_adap)
+static int
+iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status)
{
- *IOP321_GPOD &= ~(iop3xx_adap->channel==0 ?
- IOP321_GPOD_I2C0:
- IOP321_GPOD_I2C1);
-
- iop3xx_adap_reset(iop3xx_adap);
- iop3xx_adap_set_slave_addr(iop3xx_adap);
- iop3xx_adap_enable(iop3xx_adap);
-
- return 0;
+ return iop3xx_i2c_wait_event(
+ iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear);
}
-static int iop3xx_adap_send_target_slave_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
- struct i2c_msg* msg)
+static int
+iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap,
+ struct i2c_msg* msg)
{
- unsigned cr = *iop3xx_adap->biu->CR;
+ unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
int status;
int rc;
- *iop3xx_adap->biu->DBR = iic_cook_addr(msg);
+ __raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET);
- cr &= ~(IOP321_ICR_MSTOP | IOP321_ICR_NACK);
- cr |= IOP321_ICR_MSTART | IOP321_ICR_TBYTE;
-
- *iop3xx_adap->biu->CR = cr;
- rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
- /* this assert fires every time, contrary to IOP manual
- PASSERT((status&IOP321_ISR_UNITBUSY)!=0);
- */
- PASSERT((status&IOP321_ISR_RXREAD)==0);
-
+ cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
+ cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE;
+
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
+ rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
+
return rc;
}
-static int iop3xx_adap_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, int stop)
+static int
+iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte,
+ int stop)
{
- unsigned cr = *iop3xx_adap->biu->CR;
+ unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
int status;
int rc = 0;
- *iop3xx_adap->biu->DBR = byte;
- cr &= ~IOP321_ICR_MSTART;
+ __raw_writel(byte, iop3xx_adap->ioaddr + DBR_OFFSET);
+ cr &= ~IOP3XX_ICR_MSTART;
if (stop) {
- cr |= IOP321_ICR_MSTOP;
+ cr |= IOP3XX_ICR_MSTOP;
} else {
- cr &= ~IOP321_ICR_MSTOP;
+ cr &= ~IOP3XX_ICR_MSTOP;
}
- *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
- rc = iop3xx_adap_wait_tx_done(iop3xx_adap, &status);
+ cr |= IOP3XX_ICR_TBYTE;
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
+ rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status);
return rc;
}
-static int iop3xx_adap_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap,
- char* byte, int stop)
+static int
+iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte,
+ int stop)
{
- unsigned cr = *iop3xx_adap->biu->CR;
+ unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET);
int status;
int rc = 0;
- cr &= ~IOP321_ICR_MSTART;
+ cr &= ~IOP3XX_ICR_MSTART;
if (stop) {
- cr |= IOP321_ICR_MSTOP|IOP321_ICR_NACK;
+ cr |= IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK;
} else {
- cr &= ~(IOP321_ICR_MSTOP|IOP321_ICR_NACK);
+ cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK);
}
- *iop3xx_adap->biu->CR = cr |= IOP321_ICR_TBYTE;
+ cr |= IOP3XX_ICR_TBYTE;
+ __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET);
- rc = iop3xx_adap_wait_rx_done(iop3xx_adap, &status);
+ rc = iop3xx_i2c_wait_rx_done(iop3xx_adap, &status);
- *byte = *iop3xx_adap->biu->DBR;
+ *byte = __raw_readl(iop3xx_adap->ioaddr + DBR_OFFSET);
return rc;
}
-static int iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap,
- const char *buf, int count)
+static int
+iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int ii;
int rc = 0;
- for (ii = 0; rc == 0 && ii != count; ++ii) {
- rc = iop3xx_adap_write_byte(iop3xx_adap, buf[ii], ii==count-1);
- }
+ for (ii = 0; rc == 0 && ii != count; ++ii)
+ rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1);
return rc;
}
-static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap,
- char *buf, int count)
+static int
+iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int ii;
int rc = 0;
- for (ii = 0; rc == 0 && ii != count; ++ii) {
- rc = iop3xx_adap_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
- }
+ for (ii = 0; rc == 0 && ii != count; ++ii)
+ rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1);
+
return rc;
}
@@ -352,12 +339,13 @@ static int iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap,
* Each transfer (i.e. a read or a write) is separated by a repeated start
* condition.
*/
-static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
+static int
+iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int rc;
- rc = iop3xx_adap_send_target_slave_addr(iop3xx_adap, pmsg);
+ rc = iop3xx_i2c_send_target_addr(iop3xx_adap, pmsg);
if (rc < 0) {
return rc;
}
@@ -372,22 +360,24 @@ static int iop3xx_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg)
/*
* master_xfer() - main read/write entry
*/
-static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+static int
+iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+ int num)
{
struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
int im = 0;
int ret = 0;
int status;
- iop3xx_adap_wait_idle(iop3xx_adap, &status);
- iop3xx_adap_reset(iop3xx_adap);
- iop3xx_adap_enable(iop3xx_adap);
+ iop3xx_i2c_wait_idle(iop3xx_adap, &status);
+ iop3xx_i2c_reset(iop3xx_adap);
+ iop3xx_i2c_enable(iop3xx_adap);
for (im = 0; ret == 0 && im != num; im++) {
- ret = iop3xx_handle_msg(i2c_adap, &msgs[im]);
+ ret = iop3xx_i2c_handle_msg(i2c_adap, &msgs[im]);
}
- iop3xx_adap_transaction_cleanup(iop3xx_adap);
+ iop3xx_i2c_transaction_cleanup(iop3xx_adap);
if(ret)
return ret;
@@ -395,136 +385,165 @@ static int iop3xx_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[
return im;
}
-static int algo_control(struct i2c_adapter *adapter, unsigned int cmd,
+static int
+iop3xx_i2c_algo_control(struct i2c_adapter *adapter, unsigned int cmd,
unsigned long arg)
{
return 0;
}
-static u32 iic_func(struct i2c_adapter *adap)
+static u32
+iop3xx_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
-
-/* -----exported algorithm data: ------------------------------------- */
-
-static struct i2c_algorithm iic_algo = {
+static struct i2c_algorithm iop3xx_i2c_algo = {
.name = "IOP3xx I2C algorithm",
- .id = I2C_ALGO_OCP_IOP3XX,
- .master_xfer = iop3xx_master_xfer,
- .algo_control = algo_control,
- .functionality = iic_func,
+ .id = I2C_ALGO_IOP3XX,
+ .master_xfer = iop3xx_i2c_master_xfer,
+ .algo_control = iop3xx_i2c_algo_control,
+ .functionality = iop3xx_i2c_func,
};
-/*
- * registering functions to load algorithms at runtime
- */
-static int i2c_iop3xx_add_bus(struct i2c_adapter *iic_adap)
+static int
+iop3xx_i2c_remove(struct device *device)
{
- struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+ struct platform_device *pdev = to_platform_device(device);
+ struct i2c_adapter *padapter = dev_get_drvdata(&pdev->dev);
+ struct i2c_algo_iop3xx_data *adapter_data =
+ (struct i2c_algo_iop3xx_data *)padapter->algo_data;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET);
+
+ /*
+ * Disable the actual HW unit
+ */
+ cr &= ~(IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE |
+ IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE);
+ __raw_writel(cr, adapter_data->ioaddr + CR_OFFSET);
+
+ iounmap((void __iomem*)adapter_data->ioaddr);
+ release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
+ kfree(adapter_data);
+ kfree(padapter);
+
+ dev_set_drvdata(&pdev->dev, NULL);
+
+ return 0;
+}
- if (!request_region( REGION_START(iop3xx_adap),
- REGION_LENGTH(iop3xx_adap),
- iic_adap->name)) {
- return -ENODEV;
+static int
+iop3xx_i2c_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct resource *res;
+ int ret;
+ struct i2c_adapter *new_adapter;
+ struct i2c_algo_iop3xx_data *adapter_data;
+
+ new_adapter = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+ if (!new_adapter) {
+ ret = -ENOMEM;
+ goto out;
}
+ memset((void*)new_adapter, 0, sizeof(*new_adapter));
- init_waitqueue_head(&iop3xx_adap->waitq);
- spin_lock_init(&iop3xx_adap->lock);
+ adapter_data = kmalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL);
+ if (!adapter_data) {
+ ret = -ENOMEM;
+ goto free_adapter;
+ }
+ memset((void*)adapter_data, 0, sizeof(*adapter_data));
- if (request_irq(
- iop3xx_adap->biu->irq,
- iop3xx_i2c_handler,
- /* SA_SAMPLE_RANDOM */ 0,
- iic_adap->name,
- iop3xx_adap)) {
- return -ENODEV;
- }
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENODEV;
+ goto free_both;
+ }
- /* register new iic_adapter to i2c module... */
- iic_adap->id |= iic_algo.id;
- iic_adap->algo = &iic_algo;
+ if (!request_mem_region(res->start, IOP3XX_I2C_IO_SIZE, pdev->name)) {
+ ret = -EBUSY;
+ goto free_both;
+ }
- iic_adap->timeout = 100; /* default values, should */
- iic_adap->retries = 3; /* be replaced by defines */
+ /* set the adapter enumeration # */
+ adapter_data->id = i2c_id++;
- iop3xx_adap_init(iic_adap->algo_data);
- i2c_add_adapter(iic_adap);
- return 0;
-}
+ adapter_data->ioaddr = (u32)ioremap(res->start, IOP3XX_I2C_IO_SIZE);
+ if (!adapter_data->ioaddr) {
+ ret = -ENOMEM;
+ goto release_region;
+ }
-static int i2c_iop3xx_del_bus(struct i2c_adapter *iic_adap)
-{
- struct i2c_algo_iop3xx_data *iop3xx_adap = iic_adap->algo_data;
+ res = request_irq(platform_get_irq(pdev, 0), iop3xx_i2c_irq_handler, 0,
+ pdev->name, adapter_data);
+ if (res) {
+ ret = -EIO;
+ goto unmap;
+ }
- iop3xx_adap_final_cleanup(iop3xx_adap);
- free_irq(iop3xx_adap->biu->irq, iop3xx_adap);
+ memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
+ new_adapter->id = I2C_HW_IOP3XX;
+ new_adapter->owner = THIS_MODULE;
+ new_adapter->dev.parent = &pdev->dev;
- release_region(REGION_START(iop3xx_adap), REGION_LENGTH(iop3xx_adap));
+ /*
+ * Default values...should these come in from board code?
+ */
+ new_adapter->timeout = 100;
+ new_adapter->retries = 3;
+ new_adapter->algo = &iop3xx_i2c_algo;
- return i2c_del_adapter(iic_adap);
-}
+ init_waitqueue_head(&adapter_data->waitq);
+ spin_lock_init(&adapter_data->lock);
-#ifdef CONFIG_ARCH_IOP321
+ iop3xx_i2c_reset(adapter_data);
+ iop3xx_i2c_set_slave_addr(adapter_data);
+ iop3xx_i2c_enable(adapter_data);
-static struct iop3xx_biu biu0 = {
- .CR = IOP321_ICR0,
- .SR = IOP321_ISR0,
- .SAR = IOP321_ISAR0,
- .DBR = IOP321_IDBR0,
- .BMR = IOP321_IBMR0,
- .irq = IRQ_IOP321_I2C_0,
-};
+ dev_set_drvdata(&pdev->dev, new_adapter);
+ new_adapter->algo_data = adapter_data;
-static struct iop3xx_biu biu1 = {
- .CR = IOP321_ICR1,
- .SR = IOP321_ISR1,
- .SAR = IOP321_ISAR1,
- .DBR = IOP321_IDBR1,
- .BMR = IOP321_IBMR1,
- .irq = IRQ_IOP321_I2C_1,
-};
+ i2c_add_adapter(new_adapter);
-#define ADAPTER_NAME_ROOT "IOP321 i2c biu adapter "
-#else
-#error Please define the BIU struct iop3xx_biu for your processor arch
-#endif
+ return 0;
-static struct i2c_algo_iop3xx_data algo_iop3xx_data0 = {
- .channel = 0,
- .biu = &biu0,
- .timeout = 1*HZ,
-};
-static struct i2c_algo_iop3xx_data algo_iop3xx_data1 = {
- .channel = 1,
- .biu = &biu1,
- .timeout = 1*HZ,
-};
+unmap:
+ iounmap((void __iomem*)adapter_data->ioaddr);
-static struct i2c_adapter iop3xx_ops0 = {
- .owner = THIS_MODULE,
- .name = ADAPTER_NAME_ROOT "0",
- .id = I2C_HW_IOP321,
- .algo_data = &algo_iop3xx_data0,
-};
-static struct i2c_adapter iop3xx_ops1 = {
- .owner = THIS_MODULE,
- .name = ADAPTER_NAME_ROOT "1",
- .id = I2C_HW_IOP321,
- .algo_data = &algo_iop3xx_data1,
+release_region:
+ release_mem_region(res->start, IOP3XX_I2C_IO_SIZE);
+
+free_both:
+ kfree(adapter_data);
+
+free_adapter:
+ kfree(new_adapter);
+
+out:
+ return ret;
+}
+
+
+static struct device_driver iop3xx_i2c_driver = {
+ .name = "IOP3xx-I2C",
+ .bus = &platform_bus_type,
+ .probe = iop3xx_i2c_probe,
+ .remove = iop3xx_i2c_remove
};
-static int __init i2c_iop3xx_init (void)
+static int __init
+i2c_iop3xx_init (void)
{
- return i2c_iop3xx_add_bus(&iop3xx_ops0) ||
- i2c_iop3xx_add_bus(&iop3xx_ops1);
+ return driver_register(&iop3xx_i2c_driver);
}
-static void __exit i2c_iop3xx_exit (void)
+static void __exit
+i2c_iop3xx_exit (void)
{
- i2c_iop3xx_del_bus(&iop3xx_ops0);
- i2c_iop3xx_del_bus(&iop3xx_ops1);
+ driver_unregister(&iop3xx_i2c_driver);
+ return;
}
module_init (i2c_iop3xx_init);
diff --git a/drivers/i2c/busses/i2c-iop3xx.h b/drivers/i2c/busses/i2c-iop3xx.h
index f375881842a1a6..e46ebaea7b1edb 100644
--- a/drivers/i2c/busses/i2c-iop3xx.h
+++ b/drivers/i2c/busses/i2c-iop3xx.h
@@ -25,20 +25,20 @@
/*
* iop321 hardware bit definitions
*/
-#define IOP321_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */
-#define IOP321_ICR_UNIT_RESET 0x4000 /* 1=RESET */
-#define IOP321_ICR_SADIE 0x2000 /* 1=Slave Detect Interrupt Enable */
-#define IOP321_ICR_ALDIE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */
-#define IOP321_ICR_SSDIE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */
-#define IOP321_ICR_BERRIE 0x0400 /* 1=Bus Error Interrupt Enable */
-#define IOP321_ICR_RXFULLIE 0x0200 /* 1=Receive Full Interrupt Enable */
-#define IOP321_ICR_TXEMPTYIE 0x0100 /* 1=Transmit Empty Interrupt Enable */
-#define IOP321_ICR_GCD 0x0080 /* 1=General Call Disable */
+#define IOP3XX_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */
+#define IOP3XX_ICR_UNIT_RESET 0x4000 /* 1=RESET */
+#define IOP3XX_ICR_SAD_IE 0x2000 /* 1=Slave Detect Interrupt Enable */
+#define IOP3XX_ICR_ALD_IE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */
+#define IOP3XX_ICR_SSD_IE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */
+#define IOP3XX_ICR_BERR_IE 0x0400 /* 1=Bus Error Interrupt Enable */
+#define IOP3XX_ICR_RXFULL_IE 0x0200 /* 1=Receive Full Interrupt Enable */
+#define IOP3XX_ICR_TXEMPTY_IE 0x0100 /* 1=Transmit Empty Interrupt Enable */
+#define IOP3XX_ICR_GCD 0x0080 /* 1=General Call Disable */
/*
- * IOP321_ICR_GCD: 1 disables response as slave. "This bit must be set
+ * IOP3XX_ICR_GCD: 1 disables response as slave. "This bit must be set
* when sending a master mode general call message from the I2C unit"
*/
-#define IOP321_ICR_UE 0x0040 /* 1=Unit Enable */
+#define IOP3XX_ICR_UE 0x0040 /* 1=Unit Enable */
/*
* "NOTE: To avoid I2C bus integrity problems,
* the user needs to ensure that the GPIO Output Data Register -
@@ -47,38 +47,38 @@
* The user prepares to enable I2C port 0 and
* I2C port 1 by clearing GPOD bits 7:6 and GPOD bits 5:4, respectively.
*/
-#define IOP321_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */
-#define IOP321_ICR_MABORT 0x0010 /* 1=Send a STOP with no data
+#define IOP3XX_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */
+#define IOP3XX_ICR_MABORT 0x0010 /* 1=Send a STOP with no data
* NB TBYTE must be clear */
-#define IOP321_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */
-#define IOP321_ICR_NACK 0x0004 /* 1=reply with NACK */
-#define IOP321_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */
-#define IOP321_ICR_MSTART 0x0001 /* 1=initiate a START */
+#define IOP3XX_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */
+#define IOP3XX_ICR_NACK 0x0004 /* 1=reply with NACK */
+#define IOP3XX_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */
+#define IOP3XX_ICR_MSTART 0x0001 /* 1=initiate a START */
-#define IOP321_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */
-#define IOP321_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */
-#define IOP321_ISR_GCAD 0x0100 /* 1=General Call Address Detected */
-#define IOP321_ISR_RXFULL 0x0080 /* 1=Receive Full */
-#define IOP321_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */
-#define IOP321_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */
-#define IOP321_ISR_SSD 0x0010 /* 1=Slave STOP Detected */
-#define IOP321_ISR_BBUSY 0x0008 /* 1=Bus BUSY */
-#define IOP321_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */
-#define IOP321_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */
-#define IOP321_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */
+#define IOP3XX_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */
+#define IOP3XX_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */
+#define IOP3XX_ISR_GCAD 0x0100 /* 1=General Call Address Detected */
+#define IOP3XX_ISR_RXFULL 0x0080 /* 1=Receive Full */
+#define IOP3XX_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */
+#define IOP3XX_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */
+#define IOP3XX_ISR_SSD 0x0010 /* 1=Slave STOP Detected */
+#define IOP3XX_ISR_BBUSY 0x0008 /* 1=Bus BUSY */
+#define IOP3XX_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */
+#define IOP3XX_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */
+#define IOP3XX_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */
-#define IOP321_ISR_CLEARBITS 0x07f0
+#define IOP3XX_ISR_CLEARBITS 0x07f0
-#define IOP321_ISAR_SAMASK 0x007f
+#define IOP3XX_ISAR_SAMASK 0x007f
-#define IOP321_IDBR_MASK 0x00ff
+#define IOP3XX_IDBR_MASK 0x00ff
-#define IOP321_IBMR_SCL 0x0002
-#define IOP321_IBMR_SDA 0x0001
+#define IOP3XX_IBMR_SCL 0x0002
+#define IOP3XX_IBMR_SDA 0x0001
-#define IOP321_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
-#define IOP321_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
+#define IOP3XX_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */
+#define IOP3XX_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */
#define MYSAR 0x02 /* SWAG a suitable slave address */
@@ -87,32 +87,21 @@
#define I2C_ERR_ALD (I2C_ERR+1)
-struct iop3xx_biu { /* Bus Interface Unit - the hardware */
-/* physical hardware defs - regs*/
- u32 *CR;
- u32 *SR;
- u32 *SAR;
- u32 *DBR;
- u32 *BMR;
-/* irq bit vector */
- u32 irq;
-/* stored flags */
- u32 SR_enabled, SR_received;
-};
+#define CR_OFFSET 0
+#define SR_OFFSET 0x4
+#define SAR_OFFSET 0x8
+#define DBR_OFFSET 0xc
+#define CCR_OFFSET 0x10
+#define BMR_OFFSET 0x14
-struct i2c_algo_iop3xx_data {
- int channel;
+#define IOP3XX_I2C_IO_SIZE 0x18
+struct i2c_algo_iop3xx_data {
+ u32 ioaddr;
wait_queue_head_t waitq;
spinlock_t lock;
- int timeout;
- struct iop3xx_biu* biu;
+ u32 SR_enabled, SR_received;
+ int id;
};
-#define REGION_START(adap) ((u32)((adap)->biu->CR))
-#define REGION_END(adap) ((u32)((adap)->biu->BMR+1))
-#define REGION_LENGTH(adap) (REGION_END(adap)-REGION_START(adap))
-
-#define IRQ_STATUS_MASK(adap) (1<<adap->biu->irq)
-
#endif /* I2C_IOP3XX_H */
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index cc7ab3143f9387..b2b6081327d88e 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -28,6 +28,7 @@
nForce2 MCP 0064
nForce2 Ultra 400 MCP 0084
nForce3 Pro150 MCP 00D4
+ nForce3 250Gb MCP 00E4
This driver supports the 2 SMBuses that are included in the MCP2 of the
nForce2 chipset.
@@ -290,12 +291,10 @@ static u32 nforce2_func(struct i2c_adapter *adapter)
static struct pci_device_id nforce2_ids[] = {
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) },
{ 0 }
};
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 8bb467ade22299..646381b6b3bf9e 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -414,48 +414,18 @@ static struct i2c_adapter piix4_adapter = {
};
static struct pci_device_id piix4_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82371AB_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 3
- },
- {
- .vendor = PCI_VENDOR_ID_SERVERWORKS,
- .device = PCI_DEVICE_ID_SERVERWORKS_OSB4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 0,
- },
- {
- .vendor = PCI_VENDOR_ID_SERVERWORKS,
- .device = PCI_DEVICE_ID_SERVERWORKS_CSB5,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 0,
- },
- {
- .vendor = PCI_VENDOR_ID_SERVERWORKS,
- .device = PCI_DEVICE_ID_SERVERWORKS_CSB6,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 0,
- },
- {
- .vendor = PCI_VENDOR_ID_INTEL,
- .device = PCI_DEVICE_ID_INTEL_82443MX_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 3,
- },
- {
- .vendor = PCI_VENDOR_ID_EFAR,
- .device = PCI_DEVICE_ID_EFAR_SLC90E66_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = 0,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3),
+ .driver_data = 3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
+ .driver_data = 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
+ .driver_data = 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6),
+ .driver_data = 0 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3),
+ .driver_data = 3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3),
+ .driver_data = 0 },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index f5804568b57df4..13d66289933b9b 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -96,13 +96,6 @@ struct s_i2c_chip {
/*
* S3/VIA 8365/8375 registers
*/
-#ifndef PCI_DEVICE_ID_S3_SAVAGE4
-#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25
-#endif
-#ifndef PCI_DEVICE_ID_S3_PROSAVAGE8
-#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04
-#endif
-
#define VGA_CR_IX 0x3d4
#define VGA_CR_DATA 0x3d5
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
new file mode 100644
index 00000000000000..e5dd90bdb04aaa
--- /dev/null
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2004 Steven J. Hill
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ *
+ * 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>
+#include <linux/module.h>
+#include <linux/i2c-algo-sibyte.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_smbus.h>
+
+static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
+ { NULL, 0, (void *) (KSEG1+A_SMB_BASE(0)) },
+ { NULL, 1, (void *) (KSEG1+A_SMB_BASE(1)) }
+};
+
+static struct i2c_adapter sibyte_board_adapter[2] = {
+ {
+ .owner = THIS_MODULE,
+ .id = I2C_HW_SIBYTE,
+ .class = I2C_CLASS_HWMON,
+ .algo = NULL,
+ .algo_data = &sibyte_board_data[0],
+ .name = "SiByte SMBus 0",
+ },
+ {
+ .owner = THIS_MODULE,
+ .id = I2C_HW_SIBYTE,
+ .class = I2C_CLASS_HWMON,
+ .algo = NULL,
+ .algo_data = &sibyte_board_data[1],
+ .name = "SiByte SMBus 1",
+ },
+};
+
+static int __init i2c_sibyte_init(void)
+{
+ printk("i2c-swarm.o: i2c SMBus adapter module for SiByte board\n");
+ if (i2c_sibyte_add_bus(&sibyte_board_adapter[0], K_SMB_FREQ_100KHZ) < 0)
+ return -ENODEV;
+ if (i2c_sibyte_add_bus(&sibyte_board_adapter[1], K_SMB_FREQ_400KHZ) < 0)
+ return -ENODEV;
+ return 0;
+}
+
+static void __exit i2c_sibyte_exit(void)
+{
+ i2c_sibyte_del_bus(&sibyte_board_adapter[0]);
+ i2c_sibyte_del_bus(&sibyte_board_adapter[1]);
+}
+
+module_init(i2c_sibyte_init);
+module_exit(i2c_sibyte_exit);
+
+MODULE_AUTHOR("Kip Walker <kwalker@broadcom.com>, Steven J. Hill <sjhill@realitydiluted.com>");
+MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 69a2e7d7e44e02..3cac6d43bce576 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -51,9 +51,6 @@
*/
#define SIS96x_VERSION "1.0.0"
-/* SiS96x SMBus PCI device ID */
-#define PCI_DEVICE_ID_SI_SMBUS 0x16
-
/* base address register in PCI config space */
#define SIS96x_BAR 0x04
@@ -267,14 +264,7 @@ static struct i2c_adapter sis96x_adapter = {
};
static struct pci_device_id sis96x_ids[] = {
-
- {
- .vendor = PCI_VENDOR_ID_SI,
- .device = PCI_DEVICE_ID_SI_SMBUS,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
-
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) },
{ 0, }
};
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
index fec0bff2963d9f..19c805ead4d896 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/busses/i2c-stub.c
@@ -28,6 +28,7 @@
#include <linux/errno.h>
#include <linux/i2c.h>
+static u8 stub_pointer;
static u8 stub_bytes[256];
static u16 stub_words[256];
@@ -44,6 +45,22 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
ret = 0;
break;
+ case I2C_SMBUS_BYTE:
+ if (read_write == I2C_SMBUS_WRITE) {
+ stub_pointer = command;
+ dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
+ "wrote 0x%02x.\n",
+ addr, command);
+ } else {
+ data->byte = stub_bytes[stub_pointer++];
+ dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
+ "read 0x%02x.\n",
+ addr, data->byte);
+ }
+
+ ret = 0;
+ break;
+
case I2C_SMBUS_BYTE_DATA:
if (read_write == I2C_SMBUS_WRITE) {
stub_bytes[command] = data->byte;
@@ -56,6 +73,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
"read 0x%02x at 0x%02x.\n",
addr, data->byte, command);
}
+ stub_pointer = command + 1;
ret = 0;
break;
@@ -87,8 +105,8 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
static u32 stub_func(struct i2c_adapter *adapter)
{
- return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE_DATA |
- I2C_FUNC_SMBUS_WORD_DATA;
+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
}
static struct i2c_algorithm smbus_algorithm = {
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 83a77ba976b075..d86cdc6524e7b1 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -395,62 +395,22 @@ static void __devexit vt596_remove(struct pci_dev *pdev)
}
static struct pci_device_id vt596_ids[] = {
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_82C596_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_82C596B_3,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_82C686_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8233_0,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8233A,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3,
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8235,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8237,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA3
- },
- {
- .vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8231_4,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .driver_data = SMBBA1,
- },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3),
+ .driver_data = SMBBA1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3),
+ .driver_data = SMBBA1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4),
+ .driver_data = SMBBA1 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
+ .driver_data = SMBBA3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
+ .driver_data = SMBBA1 },
{ 0, }
};
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index f1f35409ab8dab..1c4ba561990871 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -239,6 +239,18 @@ config SENSORS_PC87360
This driver can also be built as a module. If so, the module
will be called pc87360.
+config SENSORS_SMSC47B397
+ tristate "SMSC LPC47B397-NC"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ select I2C_ISA
+ help
+ If you say yes here you get support for the SMSC LPC47B397-NC
+ sensor chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called smsc47b397.
+
config SENSORS_SMSC47M1
tristate "SMSC LPC47M10x and compatibles"
depends on I2C && EXPERIMENTAL
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 90dd7dd0ca148e..74dd56873a8bdf 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
+obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
diff --git a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
index eba1584d731f53..7c6d896e96d799 100644
--- a/drivers/i2c/chips/asb100.c
+++ b/drivers/i2c/chips/asb100.c
@@ -56,8 +56,7 @@
#define ASB100_VERSION "1.0.0"
/* I2C addresses to scan */
-static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
- 0x2e, 0x2f, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
/* ISA addresses to scan (none) */
static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index 94c8698ab11419..6da35c70f8b644 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -43,13 +43,6 @@ static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
/* Insmod parameters */
SENSORS_INSMOD_1(eeprom);
-static int checksum = 0;
-module_param(checksum, bool, 0);
-MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct");
-
-
-/* EEPROM registers */
-#define EEPROM_REG_CHECKSUM 0x3f
/* Size of EEPROM in bytes */
#define EEPROM_SIZE 256
@@ -168,7 +161,6 @@ static int eeprom_attach_adapter(struct i2c_adapter *adapter)
/* This function is called by i2c_detect */
int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
{
- int i, cs;
struct i2c_client *new_client;
struct eeprom_data *data;
int err = 0;
@@ -205,17 +197,6 @@ int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
/* prevent 24RF08 corruption */
i2c_smbus_write_quick(new_client, 0);
- /* Now, we do the remaining detection. It is not there, unless you force
- the checksum to work out. */
- if (checksum) {
- cs = 0;
- for (i = 0; i <= 0x3e; i++)
- cs += i2c_smbus_read_byte_data(new_client, i);
- cs &= 0xff;
- if (i2c_smbus_read_byte_data (new_client, EEPROM_REG_CHECKSUM) != cs)
- goto exit_kfree;
- }
-
data->nature = UNKNOWN;
/* Detect the Vaio nature of EEPROMs.
We use the "PCG-" prefix as the signature. */
diff --git a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
index f41ab9fd62d668..f8e18c9ae84272 100644
--- a/drivers/i2c/chips/fscher.c
+++ b/drivers/i2c/chips/fscher.c
@@ -198,7 +198,7 @@ sysfs_r(kind, sub, 0, reg) \
static DEVICE_ATTR(kind, S_IRUGO, show_##kind##0##sub, NULL);
#define sysfs_fan(offset, reg_status, reg_min, reg_ripple, reg_act) \
-sysfs_rw_n(fan, _pwm , offset, reg_min) \
+sysfs_rw_n(pwm, , offset, reg_min) \
sysfs_rw_n(fan, _status, offset, reg_status) \
sysfs_rw_n(fan, _div , offset, reg_ripple) \
sysfs_ro_n(fan, _input , offset, reg_act)
@@ -247,7 +247,7 @@ sysfs_watchdog(FSCHER_REG_WDOG_CONTROL, FSCHER_REG_WDOG_STATE, FSCHER_REG_WDOG_P
#define device_create_file_fan(client, offset) \
do { \
device_create_file(&client->dev, &dev_attr_fan##offset##_status); \
- device_create_file(&client->dev, &dev_attr_fan##offset##_pwm); \
+ device_create_file(&client->dev, &dev_attr_pwm##offset); \
device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
device_create_file(&client->dev, &dev_attr_fan##offset##_input); \
} while (0)
@@ -483,16 +483,17 @@ static ssize_t show_fan_status(struct fscher_data *data, char *buf, int nr)
return sprintf(buf, "%u\n", data->fan_status[FAN_INDEX_FROM_NUM(nr)] & 0x04);
}
-static ssize_t set_fan_pwm(struct i2c_client *client, struct fscher_data *data,
+static ssize_t set_pwm(struct i2c_client *client, struct fscher_data *data,
const char *buf, size_t count, int nr, int reg)
{
- data->fan_min[FAN_INDEX_FROM_NUM(nr)] = simple_strtoul(buf, NULL, 10) & 0xff;
+ unsigned long v = simple_strtoul(buf, NULL, 10);
+ data->fan_min[FAN_INDEX_FROM_NUM(nr)] = v > 0xff ? 0xff : v;
fscher_write_value(client, reg, data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
return count;
}
-static ssize_t show_fan_pwm (struct fscher_data *data, char *buf, int nr)
+static ssize_t show_pwm(struct fscher_data *data, char *buf, int nr)
{
return sprintf(buf, "%u\n", data->fan_min[FAN_INDEX_FROM_NUM(nr)]);
}
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 11d0df3b00e658..d7fec78faca819 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -934,13 +934,14 @@ static void otg_unbind(struct isp1301 *isp)
static void b_peripheral(struct isp1301 *isp)
{
- enable_vbus_draw(isp, 8);
OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
usb_gadget_vbus_connect(isp->otg.gadget);
#ifdef CONFIG_USB_OTG
+ enable_vbus_draw(isp, 8);
otg_update_isp(isp);
#else
+ enable_vbus_draw(isp, 100);
/* UDC driver just set OTG_BSESSVLD */
isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP);
isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN);
@@ -950,7 +951,7 @@ static void b_peripheral(struct isp1301 *isp)
#endif
}
-static int isp_update_otg(struct isp1301 *isp, u8 stat)
+static void isp_update_otg(struct isp1301 *isp, u8 stat)
{
u8 isp_stat, isp_bstat;
enum usb_otg_state state = isp->otg.state;
@@ -1489,12 +1490,10 @@ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind)
if (the_transceiver)
return 0;
- isp = kmalloc(sizeof *isp, GFP_KERNEL);
+ isp = kcalloc(1, sizeof *isp, GFP_KERNEL);
if (!isp)
return 0;
- memset(isp, 0, sizeof *isp);
-
INIT_WORK(&isp->work, isp1301_work, isp);
init_timer(&isp->timer);
isp->timer.function = isp1301_timer;
diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
index 36d84634d70e5e..a285086a7196ee 100644
--- a/drivers/i2c/chips/it87.c
+++ b/drivers/i2c/chips/it87.c
@@ -624,7 +624,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
/* Reserve the ISA region */
if (is_isa)
- if (!request_region(address, IT87_EXTENT, name))
+ if (!request_region(address, IT87_EXTENT, it87_driver.name))
goto ERROR0;
/* Probe whether there is anything available on this address. Already
diff --git a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
index a145346b3ff080..640aa01cd7903d 100644
--- a/drivers/i2c/chips/lm78.c
+++ b/drivers/i2c/chips/lm78.c
@@ -462,7 +462,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
/* Reserve the ISA region */
if (is_isa)
- if (!request_region(address, LM78_EXTENT, "lm78")) {
+ if (!request_region(address, LM78_EXTENT, lm78_driver.name)) {
err = -EBUSY;
goto ERROR0;
}
diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
index 0d2bf2311e2aa3..ba7c450e8874d6 100644
--- a/drivers/i2c/chips/lm90.c
+++ b/drivers/i2c/chips/lm90.c
@@ -35,12 +35,13 @@
* Among others, it has a higher accuracy than the LM90, much like the
* LM86 does.
*
- * This driver also supports the MAX6657 and MAX6658, sensor chips made
- * by Maxim. These chips are similar to the LM86. Complete datasheet
- * can be obtained at Maxim's website at:
+ * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor
+ * chips made by Maxim. These chips are similar to the LM86. Complete
+ * datasheet can be obtained at Maxim's website at:
* http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
- * Note that there is no way to differenciate between both chips (but
- * no need either).
+ * Note that there is no easy way to differenciate between the three
+ * variants. The extra address and features of the MAX6659 are not
+ * supported by this driver.
*
* Since the LM90 was the first chipset supported by this driver, most
* comments will refer to this chipset, but are actually general and
@@ -70,9 +71,11 @@
/*
* Addresses to scan
- * Address is fully defined internally and cannot be changed.
+ * Address is fully defined internally and cannot be changed except for
+ * MAX6659.
* LM86, LM89, LM90, LM99, ADM1032, MAX6657 and MAX6658 have address 0x4c.
* LM89-1, and LM99-1 have address 0x4d.
+ * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
*/
static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
@@ -386,8 +389,17 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
}
} else
if (man_id == 0x4D) { /* Maxim */
- if (address == 0x4C
- && (reg_config1 & 0x1F) == 0
+ /*
+ * The Maxim variants do NOT have a chip_id register.
+ * Reading from that address will return the last read
+ * value, which in our case is those of the man_id
+ * register. Likewise, the config1 register seems to
+ * lack a low nibble, so the value will be those of the
+ * previous read, so in our case those of the man_id
+ * register.
+ */
+ if (chip_id == man_id
+ && (reg_config1 & 0x1F) == (man_id & 0x0F)
&& reg_convrate <= 0x09) {
kind = max6657;
}
diff --git a/drivers/i2c/chips/pc87360.c b/drivers/i2c/chips/pc87360.c
index 3b1c0204a6c2b5..6ae814eaf338f5 100644
--- a/drivers/i2c/chips/pc87360.c
+++ b/drivers/i2c/chips/pc87360.c
@@ -756,7 +756,8 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
for (i = 0; i < 3; i++) {
if (((data->address[i] = extra_isa[i]))
- && !request_region(extra_isa[i], PC87360_EXTENT, "pc87360")) {
+ && !request_region(extra_isa[i], PC87360_EXTENT,
+ pc87360_driver.name)) {
dev_err(&new_client->dev, "Region 0x%x-0x%x already "
"in use!\n", extra_isa[i],
extra_isa[i]+PC87360_EXTENT-1);
diff --git a/drivers/i2c/chips/smsc47b397.c b/drivers/i2c/chips/smsc47b397.c
new file mode 100644
index 00000000000000..aab9f246d7e2a3
--- /dev/null
+++ b/drivers/i2c/chips/smsc47b397.c
@@ -0,0 +1,353 @@
+/*
+ smsc47b397.c - Part of lm_sensors, Linux kernel modules
+ for hardware monitoring
+
+ Supports the SMSC LPC47B397-NC Super-I/O chip.
+
+ Author/Maintainer: Mark M. Hoffman <mhoffman@lightlink.com>
+ Copyright (C) 2004 Utilitek Systems, Inc.
+
+ derived in part from smsc47m1.c:
+ Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+ Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+/* Address is autodetected, there is no default value */
+static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
+static struct i2c_force_data forces[] = {{NULL}};
+
+enum chips { any_chip, smsc47b397 };
+static struct i2c_address_data addr_data = {
+ .normal_i2c = normal_i2c,
+ .normal_isa = normal_isa,
+ .probe = normal_i2c, /* cheat */
+ .ignore = normal_i2c, /* cheat */
+ .forces = forces,
+};
+
+/* Super-I/0 registers and commands */
+
+#define REG 0x2e /* The register to read/write */
+#define VAL 0x2f /* The value to read/write */
+
+static inline void superio_outb(int reg, int val)
+{
+ outb(reg, REG);
+ outb(val, VAL);
+}
+
+static inline int superio_inb(int reg)
+{
+ outb(reg, REG);
+ return inb(VAL);
+}
+
+/* select superio logical device */
+static inline void superio_select(int ld)
+{
+ superio_outb(0x07, ld);
+}
+
+static inline void superio_enter(void)
+{
+ outb(0x55, REG);
+}
+
+static inline void superio_exit(void)
+{
+ outb(0xAA, REG);
+}
+
+#define SUPERIO_REG_DEVID 0x20
+#define SUPERIO_REG_DEVREV 0x21
+#define SUPERIO_REG_BASE_MSB 0x60
+#define SUPERIO_REG_BASE_LSB 0x61
+#define SUPERIO_REG_LD8 0x08
+
+#define SMSC_EXTENT 0x02
+
+/* 0 <= nr <= 3 */
+static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
+#define SMSC47B397_REG_TEMP(nr) (smsc47b397_reg_temp[(nr)])
+
+/* 0 <= nr <= 3 */
+#define SMSC47B397_REG_FAN_LSB(nr) (0x28 + 2 * (nr))
+#define SMSC47B397_REG_FAN_MSB(nr) (0x29 + 2 * (nr))
+
+struct smsc47b397_data {
+ struct i2c_client client;
+ struct semaphore lock;
+
+ struct semaphore update_lock;
+ unsigned long last_updated; /* in jiffies */
+ int valid;
+
+ /* register values */
+ u16 fan[4];
+ u8 temp[4];
+};
+
+static int smsc47b397_read_value(struct i2c_client *client, u8 reg)
+{
+ struct smsc47b397_data *data = i2c_get_clientdata(client);
+ int res;
+
+ down(&data->lock);
+ outb(reg, client->addr);
+ res = inb_p(client->addr + 1);
+ up(&data->lock);
+ return res;
+}
+
+static struct smsc47b397_data *smsc47b397_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct smsc47b397_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ if (time_after(jiffies - data->last_updated, (unsigned long)HZ)
+ || time_before(jiffies, data->last_updated) || !data->valid) {
+
+ dev_dbg(&client->dev, "starting device update...\n");
+
+ /* 4 temperature inputs, 4 fan inputs */
+ for (i = 0; i < 4; i++) {
+ data->temp[i] = smsc47b397_read_value(client,
+ SMSC47B397_REG_TEMP(i));
+
+ /* must read LSB first */
+ data->fan[i] = smsc47b397_read_value(client,
+ SMSC47B397_REG_FAN_LSB(i));
+ data->fan[i] |= smsc47b397_read_value(client,
+ SMSC47B397_REG_FAN_MSB(i)) << 8;
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+
+ dev_dbg(&client->dev, "... device update complete\n");
+ }
+
+ up(&data->update_lock);
+
+ return data;
+}
+
+/* TEMP: 0.001C/bit (-128C to +127C)
+ REG: 1C/bit, two's complement */
+static int temp_from_reg(u8 reg)
+{
+ return (s8)reg * 1000;
+}
+
+/* 0 <= nr <= 3 */
+static ssize_t show_temp(struct device *dev, char *buf, int nr)
+{
+ struct smsc47b397_data *data = smsc47b397_update_device(dev);
+ return sprintf(buf, "%d\n", temp_from_reg(data->temp[nr]));
+}
+
+#define sysfs_temp(num) \
+static ssize_t show_temp##num(struct device *dev, char *buf) \
+{ \
+ return show_temp(dev, buf, num-1); \
+} \
+static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL)
+
+sysfs_temp(1);
+sysfs_temp(2);
+sysfs_temp(3);
+sysfs_temp(4);
+
+#define device_create_file_temp(client, num) \
+ device_create_file(&client->dev, &dev_attr_temp##num##_input)
+
+/* FAN: 1 RPM/bit
+ REG: count of 90kHz pulses / revolution */
+static int fan_from_reg(u16 reg)
+{
+ return 90000 * 60 / reg;
+}
+
+/* 0 <= nr <= 3 */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+ struct smsc47b397_data *data = smsc47b397_update_device(dev);
+ return sprintf(buf, "%d\n", fan_from_reg(data->fan[nr]));
+}
+
+#define sysfs_fan(num) \
+static ssize_t show_fan##num(struct device *dev, char *buf) \
+{ \
+ return show_fan(dev, buf, num-1); \
+} \
+static DEVICE_ATTR(fan##num##_input, S_IRUGO, show_fan##num, NULL)
+
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
+sysfs_fan(4);
+
+#define device_create_file_fan(client, num) \
+ device_create_file(&client->dev, &dev_attr_fan##num##_input)
+
+static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind);
+
+static int smsc47b397_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_detect(adapter, &addr_data, smsc47b397_detect);
+}
+
+static int smsc47b397_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, "
+ "client not detached.\n");
+ return err;
+ }
+
+ release_region(client->addr, SMSC_EXTENT);
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+static struct i2c_driver smsc47b397_driver = {
+ .owner = THIS_MODULE,
+ .name = "smsc47b397",
+ .id = I2C_DRIVERID_SMSC47B397,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = smsc47b397_attach_adapter,
+ .detach_client = smsc47b397_detach_client,
+};
+
+static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
+{
+ struct i2c_client *new_client;
+ struct smsc47b397_data *data;
+ int err = 0;
+
+ if (!i2c_is_isa_adapter(adapter)) {
+ return 0;
+ }
+
+ if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) {
+ dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr);
+ return -EBUSY;
+ }
+
+ if (!(data = kmalloc(sizeof(struct smsc47b397_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto error_release;
+ }
+ memset(data, 0x00, sizeof(struct smsc47b397_data));
+
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = addr;
+ init_MUTEX(&data->lock);
+ new_client->adapter = adapter;
+ new_client->driver = &smsc47b397_driver;
+ new_client->flags = 0;
+
+ strlcpy(new_client->name, "smsc47b397", I2C_NAME_SIZE);
+
+ init_MUTEX(&data->update_lock);
+
+ if ((err = i2c_attach_client(new_client)))
+ goto error_free;
+
+ device_create_file_temp(new_client, 1);
+ device_create_file_temp(new_client, 2);
+ device_create_file_temp(new_client, 3);
+ device_create_file_temp(new_client, 4);
+
+ device_create_file_fan(new_client, 1);
+ device_create_file_fan(new_client, 2);
+ device_create_file_fan(new_client, 3);
+ device_create_file_fan(new_client, 4);
+
+ return 0;
+
+error_free:
+ kfree(new_client);
+error_release:
+ release_region(addr, SMSC_EXTENT);
+ return err;
+}
+
+static int __init smsc47b397_find(unsigned int *addr)
+{
+ u8 id, rev;
+
+ superio_enter();
+ id = superio_inb(SUPERIO_REG_DEVID);
+
+ if (id != 0x6f) {
+ superio_exit();
+ return -ENODEV;
+ }
+
+ rev = superio_inb(SUPERIO_REG_DEVREV);
+
+ superio_select(SUPERIO_REG_LD8);
+ *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
+ | superio_inb(SUPERIO_REG_BASE_LSB);
+
+ printk(KERN_INFO "smsc47b397: found SMSC LPC47B397-NC "
+ "(base address 0x%04x, revision %u)\n", *addr, rev);
+
+ superio_exit();
+ return 0;
+}
+
+static int __init smsc47b397_init(void)
+{
+ int ret;
+
+ if ((ret = smsc47b397_find(normal_isa)))
+ return ret;
+
+ return i2c_add_driver(&smsc47b397_driver);
+}
+
+static void __exit smsc47b397_exit(void)
+{
+ i2c_del_driver(&smsc47b397_driver);
+}
+
+MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
+MODULE_DESCRIPTION("SMSC LPC47B397 driver");
+MODULE_LICENSE("GPL");
+
+module_init(smsc47b397_init);
+module_exit(smsc47b397_exit);
diff --git a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c
index 39c6871bdf1636..c9f0d2b5c967ac 100644
--- a/drivers/i2c/chips/smsc47m1.c
+++ b/drivers/i2c/chips/smsc47m1.c
@@ -400,7 +400,7 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
}
- if (!request_region(address, SMSC_EXTENT, "smsc47m1")) {
+ if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
return -EBUSY;
}
diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
index d4938fa32ac914..f2e889702c56be 100644
--- a/drivers/i2c/chips/via686a.c
+++ b/drivers/i2c/chips/via686a.c
@@ -613,7 +613,7 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* Reserve the ISA region */
- if (!request_region(address, VIA686A_EXTENT, "via686a-sensor")) {
+ if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) {
dev_err(&adapter->dev,"region 0x%x already in use!\n",
address);
return -ENODEV;
diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
index cf9e88749ec8d0..697cd438237749 100644
--- a/drivers/i2c/chips/w83627hf.c
+++ b/drivers/i2c/chips/w83627hf.c
@@ -67,9 +67,9 @@ module_param(init, bool, 0);
MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
/* modified from kernel/include/traps.c */
-#define REG 0x2e /* The register to read/write */
+static int REG; /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */
-#define VAL 0x2f /* The value to read/write */
+static int VAL; /* The value to read/write */
/* logical device numbers for superio_select (below) */
#define W83627HF_LD_FDC 0x00
@@ -90,9 +90,9 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
#define DEVID 0x20 /* Register: Device ID */
+#define W83627THF_GPIO5_EN 0x30 /* w83627thf only */
#define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */
#define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */
-#define W83627THF_GPIO5_INVR 0xf5 /* w83627thf only */
static inline void
superio_outb(int reg, int val)
@@ -938,10 +938,13 @@ static int w83627hf_attach_adapter(struct i2c_adapter *adapter)
return i2c_detect(adapter, &addr_data, w83627hf_detect);
}
-static int w83627hf_find(int *address)
+static int w83627hf_find(int sioaddr, int *address)
{
u16 val;
+ REG = sioaddr;
+ VAL = sioaddr + 1;
+
superio_enter();
val= superio_inb(DEVID);
if(val != W627_DEVID &&
@@ -984,7 +987,7 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
if(force_addr)
address = force_addr & ~(WINB_EXTENT - 1);
- if (!request_region(address, WINB_EXTENT, "w83627hf")) {
+ if (!request_region(address, WINB_EXTENT, w83627hf_driver.name)) {
err = -EBUSY;
goto ERROR0;
}
@@ -1187,16 +1190,31 @@ static int w83627hf_read_value(struct i2c_client *client, u16 reg)
static int w83627thf_read_gpio5(struct i2c_client *client)
{
- struct w83627hf_data *data = i2c_get_clientdata(client);
- int res, inv;
+ int res = 0xff, sel;
- down(&data->lock);
superio_enter();
superio_select(W83627HF_LD_GPIO5);
- res = superio_inb(W83627THF_GPIO5_DR);
- inv = superio_inb(W83627THF_GPIO5_INVR);
+
+ /* Make sure these GPIO pins are enabled */
+ if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) {
+ dev_dbg(&client->dev, "GPIO5 disabled, no VID function\n");
+ goto exit;
+ }
+
+ /* Make sure the pins are configured for input
+ There must be at least five (VRM 9), and possibly 6 (VRM 10) */
+ sel = superio_inb(W83627THF_GPIO5_IOSR);
+ if ((sel & 0x1f) != 0x1f) {
+ dev_dbg(&client->dev, "GPIO5 not configured for VID "
+ "function\n");
+ goto exit;
+ }
+
+ dev_info(&client->dev, "Reading VID from GPIO5\n");
+ res = superio_inb(W83627THF_GPIO5_DR) & sel;
+
+exit:
superio_exit();
- up(&data->lock);
return res;
}
@@ -1269,7 +1287,7 @@ static void w83627hf_init_client(struct i2c_client *client)
int hi = w83627hf_read_value(client, W83781D_REG_CHIPID);
data->vid = (lo & 0x0f) | ((hi & 0x01) << 4);
} else if (w83627thf == data->type) {
- data->vid = w83627thf_read_gpio5(client) & 0x1f;
+ data->vid = w83627thf_read_gpio5(client) & 0x3f;
}
/* Read VRM & OVT Config only once */
@@ -1422,7 +1440,8 @@ static int __init sensors_w83627hf_init(void)
{
int addr;
- if (w83627hf_find(&addr)) {
+ if (w83627hf_find(0x2e, &addr)
+ && w83627hf_find(0x4e, &addr)) {
return -ENODEV;
}
normal_isa[0] = addr;
diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
index 3a44fe9e54362e..35c523e4b30bc1 100644
--- a/drivers/i2c/chips/w83781d.c
+++ b/drivers/i2c/chips/w83781d.c
@@ -1065,7 +1065,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
}
if (is_isa)
- if (!request_region(address, W83781D_EXTENT, "w83781d")) {
+ if (!request_region(address, W83781D_EXTENT,
+ w83781d_driver.name)) {
dev_dbg(&adapter->dev, "Request of region "
"0x%x-0x%x for w83781d failed\n", address,
address + W83781D_EXTENT - 1);
diff --git a/drivers/i2c/i2c-sensor-vid.c b/drivers/i2c/i2c-sensor-vid.c
index 017dcc5c6bf8b2..922e22f054bb28 100644
--- a/drivers/i2c/i2c-sensor-vid.c
+++ b/drivers/i2c/i2c-sensor-vid.c
@@ -36,8 +36,7 @@ struct vrm_model {
static struct vrm_model vrm_models[] = {
{X86_VENDOR_AMD, 0x6, ANY, 90}, /* Athlon Duron etc */
- {X86_VENDOR_AMD, 0xF, 0x4, 90}, /* Athlon 64 */
- {X86_VENDOR_AMD, 0xF, 0x5, 24}, /* Opteron */
+ {X86_VENDOR_AMD, 0xF, ANY, 24}, /* Athlon 64, Opteron */
{X86_VENDOR_INTEL, 0x6, 0x9, 85}, /* 0.13um too */
{X86_VENDOR_INTEL, 0x6, 0xB, 85}, /* 0xB Tualatin */
{X86_VENDOR_INTEL, 0x6, ANY, 82}, /* any P6 */
@@ -87,7 +86,7 @@ int i2c_which_vrm(void)
return vrm_ret;
}
-/* and now something completely different for Non-x86 world*/
+/* and now for something completely different for Non-x86 world*/
#else
int i2c_which_vrm(void)
{
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index 4490c883f7559f..fcc67afd53c591 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -1360,9 +1360,10 @@ static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id
// usb_show_device_descriptor(&dev->descriptor);
// usb_show_interface_descriptor(&iface->desc);
vend_idx=0xffff;
- for(i=0;vdata[i].vendor;i++)
- {
- if(dev->descriptor.idVendor==vdata[i].vendor && dev->descriptor.idProduct==vdata[i].prod_id) vend_idx=i;
+ for(i=0;vdata[i].vendor;i++) {
+ if (le16_to_cpu(dev->descriptor.idVendor) == vdata[i].vendor &&
+ le16_to_cpu(dev->descriptor.idProduct) == vdata[i].prod_id)
+ vend_idx = i;
}
@@ -1491,7 +1492,7 @@ static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id
case USB_ENDPOINT_XFER_INT:
context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->desc.bEndpointAddress);
context->fifos[cidx].usb_transfer_mode = USB_INT;
- packet_size = ep->desc.wMaxPacketSize; // remember max packet size
+ packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size
#ifdef VERBOSE_USB_DEBUG
printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n",
ep->desc.bInterval, idx, cidx);
@@ -1503,7 +1504,7 @@ static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id
else
context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->desc.bEndpointAddress);
context->fifos[cidx].usb_transfer_mode = USB_BULK;
- packet_size = ep->desc.wMaxPacketSize; // remember max packet size
+ packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size
#ifdef VERBOSE_USB_DEBUG
printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n",
idx, cidx);
@@ -1515,7 +1516,7 @@ static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id
else
context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->desc.bEndpointAddress);
context->fifos[cidx].usb_transfer_mode = USB_ISOC;
- iso_packet_size = ep->desc.wMaxPacketSize; // remember max packet size
+ iso_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size
#ifdef VERBOSE_USB_DEBUG
printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n",
idx, cidx);
@@ -1528,7 +1529,7 @@ static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id
if (context->fifos[cidx].pipe) {
context->fifos[cidx].fifonum = cidx;
context->fifos[cidx].hfc = context;
- context->fifos[cidx].usb_packet_maxlen = ep->desc.wMaxPacketSize;
+ context->fifos[cidx].usb_packet_maxlen = le16_to_cpu(ep->desc.wMaxPacketSize);
context->fifos[cidx].intervall = ep->desc.bInterval;
context->fifos[cidx].skbuff = NULL;
#ifdef VERBOSE_USB_DEBUG
diff --git a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c
index 880d07b3f036ba..2fcd093921d8c3 100644
--- a/drivers/isdn/hisax/st5481_b.c
+++ b/drivers/isdn/hisax/st5481_b.c
@@ -274,7 +274,7 @@ static int st5481_setup_b_out(struct st5481_bcs *bcs)
endpoint = &altsetting->endpoint[EP_B1_OUT - 1 + bcs->channel * 2];
DBG(4,"endpoint address=%02x,packet size=%d",
- endpoint->desc.bEndpointAddress, endpoint->desc.wMaxPacketSize);
+ endpoint->desc.bEndpointAddress, le16_to_cpu(endpoint->desc.wMaxPacketSize));
// Allocate memory for 8000bytes/sec + extra bytes if underrun
return st5481_setup_isocpipes(b_out->urb, dev,
diff --git a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c
index 51d12023773eb2..071b1d31999f75 100644
--- a/drivers/isdn/hisax/st5481_d.c
+++ b/drivers/isdn/hisax/st5481_d.c
@@ -669,7 +669,7 @@ static int st5481_setup_d_out(struct st5481_adapter *adapter)
endpoint = &altsetting->endpoint[EP_D_OUT-1];
DBG(2,"endpoint address=%02x,packet size=%d",
- endpoint->desc.bEndpointAddress, endpoint->desc.wMaxPacketSize);
+ endpoint->desc.bEndpointAddress, le16_to_cpu(endpoint->desc.wMaxPacketSize));
return st5481_setup_isocpipes(d_out->urb, dev,
usb_sndisocpipe(dev, endpoint->desc.bEndpointAddress),
diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c
index 251956823729f3..7aa810d5d333c9 100644
--- a/drivers/isdn/hisax/st5481_init.c
+++ b/drivers/isdn/hisax/st5481_init.c
@@ -67,7 +67,8 @@ static int probe_st5481(struct usb_interface *intf,
int retval, i;
printk(KERN_INFO "st541: found adapter VendorId %04x, ProductId %04x, LEDs %d\n",
- dev->descriptor.idVendor, dev->descriptor.idProduct,
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct),
number_of_leds);
adapter = kmalloc(sizeof(struct st5481_adapter), GFP_KERNEL);
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index 478b1a17b077ed..2369180b1cb1f6 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -268,8 +268,8 @@ int st5481_setup_usb(struct st5481_adapter *adapter)
}
// The descriptor is wrong for some early samples of the ST5481 chip
- altsetting->endpoint[3].desc.wMaxPacketSize = 32;
- altsetting->endpoint[4].desc.wMaxPacketSize = 32;
+ altsetting->endpoint[3].desc.wMaxPacketSize = __constant_cpu_to_le16(32);
+ altsetting->endpoint[4].desc.wMaxPacketSize = __constant_cpu_to_le16(32);
// Use alternative setting 3 on interface 0 to have 2B+D
if ((status = usb_set_interface (dev, 0, 3)) < 0) {
diff --git a/drivers/media/dvb/b2c2/b2c2-usb-core.c b/drivers/media/dvb/b2c2/b2c2-usb-core.c
index d46c8c0f8c153d..05aa900b4eda0e 100644
--- a/drivers/media/dvb/b2c2/b2c2-usb-core.c
+++ b/drivers/media/dvb/b2c2/b2c2-usb-core.c
@@ -370,7 +370,7 @@ static void b2c2_exit_usb(struct usb_b2c2_usb *b2c2)
static int b2c2_init_usb(struct usb_b2c2_usb *b2c2)
{
- u16 frame_size = b2c2->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize;
+ u16 frame_size = le16_to_cpu(b2c2->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret;
int buffer_offset = 0;
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb.c b/drivers/media/dvb/dibusb/dvb-dibusb.c
index e4237a94bbd20f..bb511205afefbe 100644
--- a/drivers/media/dvb/dibusb/dvb-dibusb.c
+++ b/drivers/media/dvb/dibusb/dvb-dibusb.c
@@ -602,8 +602,8 @@ static void frontend_init(struct usb_dibusb* dib)
if (dib->fe == NULL) {
printk("dvb-dibusb: A frontend driver was not found for device %04x/%04x\n",
- dib->udev->descriptor.idVendor,
- dib->udev->descriptor.idProduct);
+ le16_to_cpu(dib->udev->descriptor.idVendor),
+ le16_to_cpu(dib->udev->descriptor.idProduct));
} else {
if (dvb_register_frontend(dib->adapter, dib->fe)) {
printk("dvb-dibusb: Frontend registration failed!\n");
@@ -917,11 +917,11 @@ static int dibusb_probe(struct usb_interface *intf,
int ret = -ENOMEM,i,cold=0;
for (i = 0; i < DIBUSB_SUPPORTED_DEVICES; i++)
- if (dibusb_devices[i].cold_product_id == udev->descriptor.idProduct ||
- dibusb_devices[i].warm_product_id == udev->descriptor.idProduct) {
+ if (dibusb_devices[i].cold_product_id == le16_to_cpu(udev->descriptor.idProduct) ||
+ dibusb_devices[i].warm_product_id == le16_to_cpu(udev->descriptor.idProduct)) {
dibdev = &dibusb_devices[i];
- cold = dibdev->cold_product_id == udev->descriptor.idProduct;
+ cold = dibdev->cold_product_id == le16_to_cpu(udev->descriptor.idProduct);
if (cold)
info("found a '%s' in cold state, will try to load a firmware",dibdev->name);
@@ -931,7 +931,7 @@ static int dibusb_probe(struct usb_interface *intf,
if (dibdev == NULL) {
err("something went very wrong, "
- "unknown product ID: %.4x",udev->descriptor.idProduct);
+ "unknown product ID: %.4x",le16_to_cpu(udev->descriptor.idProduct));
return -ENODEV;
}
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 91a00d99f2ab44..0485faa51b4d02 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -1348,7 +1348,7 @@ static struct tda8083_config ttusb_novas_grundig_29504_491_config = {
static void frontend_init(struct ttusb* ttusb)
{
- switch(ttusb->dev->descriptor.idProduct) {
+ switch(le16_to_cpu(ttusb->dev->descriptor.idProduct)) {
case 0x1003: // Hauppauge/TT Nova-USB-S budget (stv0299/ALPS BSRU6(tsa5059)
// try the ALPS BSRU6 first
ttusb->fe = stv0299_attach(&alps_bsru6_config, &ttusb->i2c_adap);
@@ -1381,8 +1381,8 @@ static void frontend_init(struct ttusb* ttusb)
if (ttusb->fe == NULL) {
printk("dvb-ttusb-budget: A frontend driver was not found for device %04x/%04x\n",
- ttusb->dev->descriptor.idVendor,
- ttusb->dev->descriptor.idProduct);
+ le16_to_cpu(ttusb->dev->descriptor.idVendor),
+ le16_to_cpu(ttusb->dev->descriptor.idProduct));
} else {
if (dvb_register_frontend(ttusb->adapter, ttusb->fe)) {
printk("dvb-ttusb-budget: Frontend registration failed!\n");
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index fa494caf12e7d8..1d1122b3d0287e 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -1447,7 +1447,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
memset(dec, 0, sizeof(struct ttusb_dec));
- switch (id->idProduct) {
+ switch (le16_to_cpu(id->idProduct)) {
case 0x1006:
ttusb_dec_set_model(dec, TTUSB_DEC3000S);
break;
@@ -1471,7 +1471,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
ttusb_dec_init_dvb(dec);
dec->adapter->priv = dec;
- switch (id->idProduct) {
+ switch (le16_to_cpu(id->idProduct)) {
case 0x1006:
dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
break;
@@ -1484,8 +1484,8 @@ static int ttusb_dec_probe(struct usb_interface *intf,
if (dec->fe == NULL) {
printk("dvb-ttusb-dec: A frontend driver was not found for device %04x/%04x\n",
- dec->udev->descriptor.idVendor,
- dec->udev->descriptor.idProduct);
+ le16_to_cpu(dec->udev->descriptor.idVendor),
+ le16_to_cpu(dec->udev->descriptor.idProduct));
} else {
if (dvb_register_frontend(dec->adapter, dec->fe)) {
printk("budget-ci: Frontend registration failed!\n");
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index a2b6a19376f99e..1b1dcc8abb758e 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -3942,7 +3942,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, u32 state)
/* save pci state */
pci_save_state(pci_dev);
- if (0 != pci_set_power_state(pci_dev, state)) {
+ if (0 != pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state))) {
pci_disable_device(pci_dev);
btv->state.disabled = 1;
}
@@ -3961,7 +3961,7 @@ static int bttv_resume(struct pci_dev *pci_dev)
pci_enable_device(pci_dev);
btv->state.disabled = 0;
}
- pci_set_power_state(pci_dev, 0);
+ pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
/* restore bt878 state */
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index 179f91cf7eb0d9..3039b40bb80b26 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -219,7 +219,6 @@ struct tvcard
};
extern struct tvcard bttv_tvcards[];
-extern const unsigned int bttv_num_tvcards;
/* identification / initialization of the card */
extern void bttv_idcard(struct bttv *btv);
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index c73750625e72ba..a32429f02ae42c 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1551,7 +1551,7 @@ vortex_up(struct net_device *dev)
int i;
if (VORTEX_PCI(vp) && vp->enable_wol) {
- pci_set_power_state(VORTEX_PCI(vp), 0); /* Go active */
+ pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */
pci_restore_state(VORTEX_PCI(vp));
}
@@ -2943,7 +2943,7 @@ static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
/* The kernel core really should have pci_get_power_state() */
if(state != 0)
- pci_set_power_state(VORTEX_PCI(vp), 0);
+ pci_set_power_state(VORTEX_PCI(vp), PCI_D0);
err = vortex_do_ioctl(dev, rq, cmd);
if(state != 0)
pci_set_power_state(VORTEX_PCI(vp), state);
@@ -3142,7 +3142,7 @@ static void acpi_set_WOL(struct net_device *dev)
/* Change the power state to D3; RxEnable doesn't take effect. */
pci_enable_wake(VORTEX_PCI(vp), 0, 1);
- pci_set_power_state(VORTEX_PCI(vp), 3);
+ pci_set_power_state(VORTEX_PCI(vp), PCI_D3hot);
}
@@ -3165,7 +3165,7 @@ static void __devexit vortex_remove_one (struct pci_dev *pdev)
unregister_netdev(dev);
if (VORTEX_PCI(vp) && vp->enable_wol) {
- pci_set_power_state(VORTEX_PCI(vp), 0); /* Go active */
+ pci_set_power_state(VORTEX_PCI(vp), PCI_D0); /* Go active */
if (vp->pm_state_valid)
pci_restore_state(VORTEX_PCI(vp));
}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 80ebac6d2c9e87..58c6a85c3aa250 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -1625,7 +1625,7 @@ static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
static void cp_set_d3_state (struct cp_private *cp)
{
pci_enable_wake (cp->pdev, 0, 1); /* Enable PME# generation */
- pci_set_power_state (cp->pdev, 3);
+ pci_set_power_state (cp->pdev, PCI_D3hot);
}
static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -1815,7 +1815,7 @@ static void cp_remove_one (struct pci_dev *pdev)
BUG();
unregister_netdev(dev);
iounmap(cp->regs);
- if (cp->wol_enabled) pci_set_power_state (pdev, 0);
+ if (cp->wol_enabled) pci_set_power_state (pdev, PCI_D0);
pci_release_regions(pdev);
pci_clear_mwi(pdev);
pci_disable_device(pdev);
@@ -1865,7 +1865,7 @@ static int cp_resume (struct pci_dev *pdev)
netif_device_attach (dev);
if (cp->pdev && cp->wol_enabled) {
- pci_set_power_state (cp->pdev, 0);
+ pci_set_power_state (cp->pdev, PCI_D0);
pci_restore_state (cp->pdev);
}
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 0647535e836afe..6fa1bd83f3052a 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -2609,7 +2609,7 @@ static int rtl8139_suspend (struct pci_dev *pdev, u32 state)
spin_unlock_irqrestore (&tp->lock, flags);
- pci_set_power_state (pdev, 3);
+ pci_set_power_state (pdev, PCI_D3hot);
return 0;
}
@@ -2622,7 +2622,7 @@ static int rtl8139_resume (struct pci_dev *pdev)
pci_restore_state (pdev);
if (!netif_running (dev))
return 0;
- pci_set_power_state (pdev, 0);
+ pci_set_power_state (pdev, PCI_D0);
rtl8139_init_ring (dev);
rtl8139_hw_start (dev);
netif_device_attach (dev);
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index dbc9a9da3b9fab..f1d81901ecf1ff 100755
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -1826,17 +1826,17 @@ static int amd8111e_suspend(struct pci_dev *pci_dev, u32 state)
if(lp->options & OPTION_WAKE_PHY_ENABLE)
amd8111e_enable_link_change(lp);
- pci_enable_wake(pci_dev, 3, 1);
- pci_enable_wake(pci_dev, 4, 1); /* D3 cold */
+ pci_enable_wake(pci_dev, PCI_D3hot, 1);
+ pci_enable_wake(pci_dev, PCI_D3cold, 1);
}
else{
- pci_enable_wake(pci_dev, 3, 0);
- pci_enable_wake(pci_dev, 4, 0); /* 4 == D3 cold */
+ pci_enable_wake(pci_dev, PCI_D3hot, 0);
+ pci_enable_wake(pci_dev, PCI_D3cold, 0);
}
pci_save_state(pci_dev);
- pci_set_power_state(pci_dev, 3);
+ pci_set_power_state(pci_dev, PCI_D3hot);
return 0;
}
@@ -1848,11 +1848,11 @@ static int amd8111e_resume(struct pci_dev *pci_dev)
if (!netif_running(dev))
return 0;
- pci_set_power_state(pci_dev, 0);
+ pci_set_power_state(pci_dev, PCI_D0);
pci_restore_state(pci_dev);
- pci_enable_wake(pci_dev, 3, 0);
- pci_enable_wake(pci_dev, 4, 0); /* D3 cold */
+ pci_enable_wake(pci_dev, PCI_D3hot, 0);
+ pci_enable_wake(pci_dev, PCI_D3cold, 0); /* D3 cold */
netif_device_attach(dev);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index d9574c63900a80..62e8e4a25ccded 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -2322,7 +2322,7 @@ static int e100_suspend(struct pci_dev *pdev, u32 state)
pci_save_state(pdev);
pci_enable_wake(pdev, state, nic->flags & (wol_magic | e100_asf(nic)));
pci_disable_device(pdev);
- pci_set_power_state(pdev, state);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
return 0;
}
@@ -2332,7 +2332,7 @@ static int e100_resume(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct nic *nic = netdev_priv(netdev);
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
e100_hw_init(nic);
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
index ce26ac9d321210..ab5146fe5c8a2a 100644
--- a/drivers/net/eepro100.c
+++ b/drivers/net/eepro100.c
@@ -983,7 +983,7 @@ speedo_open(struct net_device *dev)
if (netif_msg_ifup(sp))
printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
- pci_set_power_state(sp->pdev, 0);
+ pci_set_power_state(sp->pdev, PCI_D0);
/* Set up the Tx queue early.. */
sp->cur_tx = 0;
@@ -1933,7 +1933,7 @@ speedo_close(struct net_device *dev)
if (netif_msg_ifdown(sp))
printk(KERN_DEBUG "%s: %d multicast blocks dropped.\n", dev->name, i);
- pci_set_power_state(sp->pdev, 2);
+ pci_set_power_state(sp->pdev, PCI_D2);
return 0;
}
@@ -2058,7 +2058,7 @@ static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
access from the timeout handler.
They are currently serialized only with MDIO access from the
timer routine. 2000/05/09 SAW */
- saved_acpi = pci_set_power_state(sp->pdev, 0);
+ saved_acpi = pci_set_power_state(sp->pdev, PCI_D0);
t = del_timer_sync(&sp->timer);
data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
if (t)
@@ -2069,7 +2069,7 @@ static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case SIOCSMIIREG: /* Write MII PHY register. */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- saved_acpi = pci_set_power_state(sp->pdev, 0);
+ saved_acpi = pci_set_power_state(sp->pdev, PCI_D0);
t = del_timer_sync(&sp->timer);
mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
if (t)
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index 84292c0e046433..9e93080d2a13bd 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -1220,7 +1220,7 @@ static inline int irda_usb_parse_endpoints(struct irda_usb_cb *self, struct usb_
ep = endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
dir = endpoint[i].desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK;
attr = endpoint[i].desc.bmAttributes;
- psize = endpoint[i].desc.wMaxPacketSize;
+ psize = le16_to_cpu(endpoint[i].desc.wMaxPacketSize);
/* Is it a bulk endpoint ??? */
if(attr == USB_ENDPOINT_XFER_BULK) {
@@ -1360,8 +1360,8 @@ static int irda_usb_probe(struct usb_interface *intf,
* Jean II */
MESSAGE("IRDA-USB found at address %d, Vendor: %x, Product: %x\n",
- dev->devnum, dev->descriptor.idVendor,
- dev->descriptor.idProduct);
+ dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
net = alloc_irdadev(sizeof(*self));
if (!net)
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index f80a19e83a1433..4bbd29cb182273 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -1072,8 +1072,8 @@ static int stir_probe(struct usb_interface *intf,
printk(KERN_INFO "SigmaTel STIr4200 IRDA/USB found at address %d, "
"Vendor: %x, Product: %x\n",
- dev->devnum, dev->descriptor.idVendor,
- dev->descriptor.idProduct);
+ dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&stir->qos);
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 81dee74b4b1c9f..bb1c3d8981ee30 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -1921,7 +1921,7 @@ static int netdrv_suspend (struct pci_dev *pdev, u32 state)
spin_unlock_irqrestore (&tp->lock, flags);
pci_save_state (pdev);
- pci_set_power_state (pdev, 3);
+ pci_set_power_state (pdev, PCI_D3hot);
return 0;
}
@@ -1934,7 +1934,7 @@ static int netdrv_resume (struct pci_dev *pdev)
if (!netif_running(dev))
return 0;
- pci_set_power_state (pdev, 0);
+ pci_set_power_state (pdev, PCI_D0);
pci_restore_state (pdev);
netif_device_attach (dev);
netdrv_hw_start (dev);
diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig
index 90d093736e9696..74f862001247b6 100644
--- a/drivers/net/pcmcia/Kconfig
+++ b/drivers/net/pcmcia/Kconfig
@@ -3,7 +3,7 @@
#
menu "PCMCIA network device support"
- depends on NETDEVICES && HOTPLUG && PCMCIA!=n
+ depends on NETDEVICES && PCMCIA!=n
config NET_PCMCIA
bool "PCMCIA network device support"
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 4c792f0a17a1f7..d2a9fff5e76f58 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -2240,7 +2240,7 @@ static int sis900_suspend(struct pci_dev *pci_dev, u32 state)
/* Stop the chip's Tx and Rx Status Machine */
outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
- pci_set_power_state(pci_dev, 3);
+ pci_set_power_state(pci_dev, PCI_D3hot);
pci_save_state(pci_dev);
return 0;
@@ -2255,7 +2255,7 @@ static int sis900_resume(struct pci_dev *pci_dev)
if(!netif_running(net_dev))
return 0;
pci_restore_state(pci_dev);
- pci_set_power_state(pci_dev, 0);
+ pci_set_power_state(pci_dev, PCI_D0);
sis900_init_rxfilter(net_dev);
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 1ed2a7896f233d..236bdd3f6ba034 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -2160,7 +2160,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
/* XXX: add wakeup code -- requires firmware for MagicPacket */
- pci_set_power_state(pdev, 3); /* go to sleep in D3 mode */
+ pci_set_power_state(pdev, PCI_D3hot); /* go to sleep in D3 mode */
pci_disable_device(pdev);
iounmap(np->base);
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
index 9e91287c124407..23d0fa4bbceb7b 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -84,7 +84,7 @@ config 3C359
config TMS380TR
tristate "Generic TMS380 Token Ring ISA/PCI adapter support"
- depends on TR && (PCI || ISA) && HOTPLUG
+ depends on TR && (PCI || ISA)
select FW_LOADER
---help---
This driver provides generic support for token ring adapters
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 3b245853eda83c..5712cac903d41a 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -1889,7 +1889,7 @@ typhoon_sleep(struct typhoon *tp, int state, u16 events)
pci_enable_wake(tp->pdev, state, 1);
pci_disable_device(pdev);
- return pci_set_power_state(pdev, state);
+ return pci_set_power_state(pdev, pci_choose_state(pdev, state));
}
static int
@@ -1898,7 +1898,7 @@ typhoon_wakeup(struct typhoon *tp, int wait_type)
struct pci_dev *pdev = tp->pdev;
void __iomem *ioaddr = tp->ioaddr;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
/* Post 2.x.x versions of the Sleep Image require a reset before
@@ -2552,7 +2552,7 @@ typhoon_remove_one(struct pci_dev *pdev)
struct typhoon *tp = netdev_priv(dev);
unregister_netdev(dev);
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
typhoon_reset(tp->ioaddr, NoWait);
iounmap(tp->ioaddr);
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 04eced2181c7d0..26f35773279543 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -1970,7 +1970,7 @@ static int rhine_resume(struct pci_dev *pdev)
if (request_irq(dev->irq, rhine_interrupt, SA_SHIRQ, dev->name, dev))
printk(KERN_ERR "via-rhine %s: request_irq failed\n", dev->name);
- ret = pci_set_power_state(pdev, 0);
+ ret = pci_set_power_state(pdev, PCI_D0);
if (debug > 1)
printk(KERN_INFO "%s: Entering power state D0 %s (%d).\n",
dev->name, ret ? "failed" : "succeeded", ret);
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index c889078c315f57..7964bc3d6971fc 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -804,7 +804,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
/* and leave the chip powered down */
- pci_set_power_state(pdev, 3);
+ pci_set_power_state(pdev, PCI_D3hot);
#ifdef CONFIG_PM
{
unsigned long flags;
@@ -1742,7 +1742,7 @@ static int velocity_open(struct net_device *dev)
goto err_free_rd_ring;
/* Ensure chip is running */
- pci_set_power_state(vptr->pdev, 0);
+ pci_set_power_state(vptr->pdev, PCI_D0);
velocity_init_registers(vptr, VELOCITY_INIT_COLD);
@@ -1750,7 +1750,7 @@ static int velocity_open(struct net_device *dev)
dev->name, dev);
if (ret < 0) {
/* Power down the chip */
- pci_set_power_state(vptr->pdev, 3);
+ pci_set_power_state(vptr->pdev, PCI_D3hot);
goto err_free_td_ring;
}
@@ -1868,7 +1868,7 @@ static int velocity_close(struct net_device *dev)
free_irq(dev->irq, dev);
/* Power down the chip */
- pci_set_power_state(vptr->pdev, 3);
+ pci_set_power_state(vptr->pdev, PCI_D3hot);
/* Free the resources */
velocity_free_td_ring(vptr);
@@ -2194,8 +2194,8 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
/* If we are asked for information and the device is power
saving then we need to bring the device back up to talk to it */
- if(!netif_running(dev))
- pci_set_power_state(vptr->pdev, 0);
+ if (!netif_running(dev))
+ pci_set_power_state(vptr->pdev, PCI_D0);
switch (cmd) {
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
@@ -2207,8 +2207,8 @@ static int velocity_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
default:
ret = -EOPNOTSUPP;
}
- if(!netif_running(dev))
- pci_set_power_state(vptr->pdev, 3);
+ if (!netif_running(dev))
+ pci_set_power_state(vptr->pdev, PCI_D3hot);
return ret;
@@ -2818,8 +2818,8 @@ static void enable_flow_control_ability(struct velocity_info *vptr)
static int velocity_ethtool_up(struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
- if(!netif_running(dev))
- pci_set_power_state(vptr->pdev, 0);
+ if (!netif_running(dev))
+ pci_set_power_state(vptr->pdev, PCI_D0);
return 0;
}
@@ -2834,8 +2834,8 @@ static int velocity_ethtool_up(struct net_device *dev)
static void velocity_ethtool_down(struct net_device *dev)
{
struct velocity_info *vptr = dev->priv;
- if(!netif_running(dev))
- pci_set_power_state(vptr->pdev, 3);
+ if (!netif_running(dev))
+ pci_set_power_state(vptr->pdev, PCI_D3hot);
}
static int velocity_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -3229,15 +3229,15 @@ static int velocity_suspend(struct pci_dev *pdev, u32 state)
velocity_shutdown(vptr);
velocity_set_wol(vptr);
pci_enable_wake(pdev, 3, 1);
- pci_set_power_state(pdev, 3);
+ pci_set_power_state(pdev, PCI_D3hot);
} else {
velocity_save_context(vptr, &vptr->context);
velocity_shutdown(vptr);
pci_disable_device(pdev);
- pci_set_power_state(pdev, state);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
}
#else
- pci_set_power_state(pdev, state);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
#endif
spin_unlock_irqrestore(&vptr->lock, flags);
return 0;
@@ -3252,7 +3252,7 @@ static int velocity_resume(struct pci_dev *pdev)
if(!netif_running(vptr->dev))
return 0;
- pci_set_power_state(pdev, 0);
+ pci_set_power_state(pdev, PCI_D0);
pci_enable_wake(pdev, 0, 0);
pci_restore_state(pdev);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index b1a30eeba8da9c..915180146f15c6 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -311,7 +311,7 @@ comment "Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support"
depends on NET_RADIO && PCI
config PRISM54
tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus'
- depends on PCI && NET_RADIO && EXPERIMENTAL && HOTPLUG
+ depends on PCI && NET_RADIO && EXPERIMENTAL
select FW_LOADER
---help---
Enable PCI and Cardbus support for the following chipset based cards:
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index db8fe4c495905a..31dc05d0817549 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -83,7 +83,7 @@ config PARPORT_PC_SUPERIO
config PARPORT_PC_PCMCIA
tristate "Support for PCMCIA management for PC-style ports"
- depends on PARPORT!=n && HOTPLUG && (PCMCIA!=n && PARPORT_PC=m && PARPORT_PC || PARPORT_PC=y && PCMCIA)
+ depends on PARPORT!=n && (PCMCIA!=n && PARPORT_PC=m && PARPORT_PC || PARPORT_PC=y && PCMCIA)
help
Say Y here if you need PCMCIA support for your PC-style parallel
ports. If unsure, say N.
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 9117a95a3b218c..5f8e5022d817c7 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -3,11 +3,11 @@
#
menu "PCI Hotplug Support"
- depends on HOTPLUG
config HOTPLUG_PCI
tristate "Support for PCI Hotplug (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
+ select HOTPLUG
---help---
Say Y here if you have a motherboard with a PCI Hotplug controller.
This allows you to add and remove PCI cards while the machine is
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index aced6616634ea9..7e7f913ba7b9e4 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -47,7 +47,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
MODULE_VERSION(DRIVER_VERSION);
-module_param(debug, bool, 644);
+module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, " Debugging mode enabled or not");
#define MY_NAME "acpiphp_ibm"
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 6942f7149ddd83..2e969616f298d6 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -32,7 +32,7 @@
#include "pci_hotplug.h"
#include "cpci_hotplug.h"
-#if !defined(CONFIG_HOTPLUG_CPCI_MODULE)
+#if !defined(MODULE)
#define MY_NAME "cpci_hotplug"
#else
#define MY_NAME THIS_MODULE->name
diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c
index ef4f598ab9d7a2..a62a4345b46631 100644
--- a/drivers/pci/hotplug/cpcihp_generic.c
+++ b/drivers/pci/hotplug/cpcihp_generic.c
@@ -45,7 +45,7 @@
#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
#define DRIVER_DESC "Generic port I/O CompactPCI Hot Plug Driver"
-#if !defined(CONFIG_HOTPLUG_CPCI_GENERIC_MODULE)
+#if !defined(MODULE)
#define MY_NAME "cpcihp_generic"
#else
#define MY_NAME THIS_MODULE->name
diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c
index 225973d86331d6..93e39c4096a927 100644
--- a/drivers/pci/hotplug/cpqphp_pci.c
+++ b/drivers/pci/hotplug/cpqphp_pci.c
@@ -151,18 +151,29 @@ static int PCI_RefinedAccessConfig(struct pci_bus *bus, unsigned int devfn, u8 o
*/
int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
{
- int rc;
- u16 temp_word;
- struct pci_dev fakedev;
- struct pci_bus fakebus;
+ int rc = 0;
if (cpqhp_legacy_mode) {
- fakedev.devfn = dev_num << 3;
- fakedev.bus = &fakebus;
- fakebus.number = bus_num;
+ struct pci_dev *fakedev;
+ struct pci_bus *fakebus;
+ u16 temp_word;
+
+ fakedev = kmalloc(sizeof(*fakedev), GFP_KERNEL);
+ fakebus = kmalloc(sizeof(*fakebus), GFP_KERNEL);
+ if (!fakedev || !fakebus) {
+ kfree(fakedev);
+ kfree(fakebus);
+ return -ENOMEM;
+ }
+
+ fakedev->devfn = dev_num << 3;
+ fakedev->bus = fakebus;
+ fakebus->number = bus_num;
dbg("%s: dev %d, bus %d, pin %d, num %d\n",
__FUNCTION__, dev_num, bus_num, int_pin, irq_num);
- rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
+ rc = pcibios_set_irq_routing(fakedev, int_pin - 0x0a, irq_num);
+ kfree(fakedev);
+ kfree(fakebus);
dbg("%s: rc %d\n", __FUNCTION__, rc);
if (!rc)
return !rc;
@@ -176,9 +187,10 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
// This should only be for x86 as it sets the Edge Level Control Register
outb((u8) (temp_word & 0xFF), 0x4d0);
outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
+ rc = 0;
}
- return 0;
+ return rc;
}
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 7cf086a551872a..8e47fa66e25eca 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -40,7 +40,7 @@
#include "pci_hotplug.h"
#include "../pci.h"
-#if !defined(CONFIG_HOTPLUG_PCI_FAKE_MODULE)
+#if !defined(MODULE)
#define MY_NAME "fakephp"
#else
#define MY_NAME THIS_MODULE->name
diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h
index b42346b023f269..5bc039da647f1e 100644
--- a/drivers/pci/hotplug/ibmphp.h
+++ b/drivers/pci/hotplug/ibmphp.h
@@ -34,7 +34,7 @@
extern int ibmphp_debug;
-#if !defined(CONFIG_HOTPLUG_PCI_IBM_MODULE)
+#if !defined(MODULE)
#define MY_NAME "ibmphpd"
#else
#define MY_NAME THIS_MODULE->name
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index 048e7ea0e91029..0392e004258f66 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -59,7 +59,8 @@ MODULE_DESCRIPTION (DRIVER_DESC);
struct pci_bus *ibmphp_pci_bus;
static int max_slots;
-static int irqs[16]; /* PIC mode IRQ's we're using so far (in case MPS tables don't provide default info for empty slots */
+static int irqs[16]; /* PIC mode IRQ's we're using so far (in case MPS
+ * tables don't provide default info for empty slots */
static int init_flag;
@@ -71,36 +72,40 @@ static inline int get_max_adapter_speed (struct hotplug_slot *hs, u8 *value)
return get_max_adapter_speed_1 (hs, value, 1);
}
*/
-static inline int get_cur_bus_info (struct slot **sl)
+static inline int get_cur_bus_info(struct slot **sl)
{
int rc = 1;
struct slot * slot_cur = *sl;
- debug ("options = %x\n", slot_cur->ctrl->options);
- debug ("revision = %x\n", slot_cur->ctrl->revision);
+ debug("options = %x\n", slot_cur->ctrl->options);
+ debug("revision = %x\n", slot_cur->ctrl->revision);
- if (READ_BUS_STATUS (slot_cur->ctrl))
- rc = ibmphp_hpc_readslot (slot_cur, READ_BUSSTATUS, NULL);
+ if (READ_BUS_STATUS(slot_cur->ctrl))
+ rc = ibmphp_hpc_readslot(slot_cur, READ_BUSSTATUS, NULL);
if (rc)
return rc;
- slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED (slot_cur->busstatus);
- if (READ_BUS_MODE (slot_cur->ctrl))
- slot_cur->bus_on->current_bus_mode = CURRENT_BUS_MODE (slot_cur->busstatus);
+ slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED(slot_cur->busstatus);
+ if (READ_BUS_MODE(slot_cur->ctrl))
+ slot_cur->bus_on->current_bus_mode =
+ CURRENT_BUS_MODE(slot_cur->busstatus);
else
slot_cur->bus_on->current_bus_mode = 0xFF;
- debug ("busstatus = %x, bus_speed = %x, bus_mode = %x\n", slot_cur->busstatus, slot_cur->bus_on->current_speed, slot_cur->bus_on->current_bus_mode);
+ debug("busstatus = %x, bus_speed = %x, bus_mode = %x\n",
+ slot_cur->busstatus,
+ slot_cur->bus_on->current_speed,
+ slot_cur->bus_on->current_bus_mode);
*sl = slot_cur;
return 0;
}
-static inline int slot_update (struct slot **sl)
+static inline int slot_update(struct slot **sl)
{
int rc;
- rc = ibmphp_hpc_readslot (*sl, READ_ALLSTAT, NULL);
+ rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL);
if (rc)
return rc;
if (!init_flag)
@@ -114,10 +119,10 @@ static int __init get_max_slots (void)
struct list_head * tmp;
u8 slot_count = 0;
- list_for_each (tmp, &ibmphp_slot_head) {
- slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
+ list_for_each(tmp, &ibmphp_slot_head) {
+ slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
/* sometimes the hot-pluggable slots start with 4 (not always from 1) */
- slot_count = max (slot_count, slot_cur->number);
+ slot_count = max(slot_count, slot_cur->number);
}
return slot_count;
}
@@ -128,46 +133,61 @@ static int __init get_max_slots (void)
* Parameters: struct slot
* Returns 0 or errors
*/
-int ibmphp_init_devno (struct slot **cur_slot)
+int ibmphp_init_devno(struct slot **cur_slot)
{
struct irq_routing_table *rtable;
int len;
int loop;
int i;
- rtable = pcibios_get_irq_routing_table ();
+ rtable = pcibios_get_irq_routing_table();
if (!rtable) {
- err ("no BIOS routing table...\n");
+ err("no BIOS routing table...\n");
return -ENOMEM;
}
- len = (rtable->size - sizeof (struct irq_routing_table)) / sizeof (struct irq_info);
+ len = (rtable->size - sizeof(struct irq_routing_table)) /
+ sizeof(struct irq_info);
if (!len)
return -1;
for (loop = 0; loop < len; loop++) {
if ((*cur_slot)->number == rtable->slots[loop].slot) {
if ((*cur_slot)->bus == rtable->slots[loop].bus) {
- (*cur_slot)->device = PCI_SLOT (rtable->slots[loop].devfn);
+ (*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn);
for (i = 0; i < 4; i++)
- (*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector ((int) (*cur_slot)->bus, (int) (*cur_slot)->device, i);
-
- debug ("(*cur_slot)->irq[0] = %x\n", (*cur_slot)->irq[0]);
- debug ("(*cur_slot)->irq[1] = %x\n", (*cur_slot)->irq[1]);
- debug ("(*cur_slot)->irq[2] = %x\n", (*cur_slot)->irq[2]);
- debug ("(*cur_slot)->irq[3] = %x\n", (*cur_slot)->irq[3]);
-
- debug ("rtable->exlusive_irqs = %x\n", rtable->exclusive_irqs);
- debug ("rtable->slots[loop].irq[0].bitmap = %x\n", rtable->slots[loop].irq[0].bitmap);
- debug ("rtable->slots[loop].irq[1].bitmap = %x\n", rtable->slots[loop].irq[1].bitmap);
- debug ("rtable->slots[loop].irq[2].bitmap = %x\n", rtable->slots[loop].irq[2].bitmap);
- debug ("rtable->slots[loop].irq[3].bitmap = %x\n", rtable->slots[loop].irq[3].bitmap);
-
- debug ("rtable->slots[loop].irq[0].link= %x\n", rtable->slots[loop].irq[0].link);
- debug ("rtable->slots[loop].irq[1].link = %x\n", rtable->slots[loop].irq[1].link);
- debug ("rtable->slots[loop].irq[2].link = %x\n", rtable->slots[loop].irq[2].link);
- debug ("rtable->slots[loop].irq[3].link = %x\n", rtable->slots[loop].irq[3].link);
- debug ("end of init_devno\n");
+ (*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus,
+ (int) (*cur_slot)->device, i);
+
+ debug("(*cur_slot)->irq[0] = %x\n",
+ (*cur_slot)->irq[0]);
+ debug("(*cur_slot)->irq[1] = %x\n",
+ (*cur_slot)->irq[1]);
+ debug("(*cur_slot)->irq[2] = %x\n",
+ (*cur_slot)->irq[2]);
+ debug("(*cur_slot)->irq[3] = %x\n",
+ (*cur_slot)->irq[3]);
+
+ debug("rtable->exlusive_irqs = %x\n",
+ rtable->exclusive_irqs);
+ debug("rtable->slots[loop].irq[0].bitmap = %x\n",
+ rtable->slots[loop].irq[0].bitmap);
+ debug("rtable->slots[loop].irq[1].bitmap = %x\n",
+ rtable->slots[loop].irq[1].bitmap);
+ debug("rtable->slots[loop].irq[2].bitmap = %x\n",
+ rtable->slots[loop].irq[2].bitmap);
+ debug("rtable->slots[loop].irq[3].bitmap = %x\n",
+ rtable->slots[loop].irq[3].bitmap);
+
+ debug("rtable->slots[loop].irq[0].link = %x\n",
+ rtable->slots[loop].irq[0].link);
+ debug("rtable->slots[loop].irq[1].link = %x\n",
+ rtable->slots[loop].irq[1].link);
+ debug("rtable->slots[loop].irq[2].link = %x\n",
+ rtable->slots[loop].irq[2].link);
+ debug("rtable->slots[loop].irq[3].link = %x\n",
+ rtable->slots[loop].irq[3].link);
+ debug("end of init_devno\n");
return 0;
}
}
@@ -176,49 +196,50 @@ int ibmphp_init_devno (struct slot **cur_slot)
return -1;
}
-static inline int power_on (struct slot *slot_cur)
+static inline int power_on(struct slot *slot_cur)
{
u8 cmd = HPC_SLOT_ON;
int retval;
- retval = ibmphp_hpc_writeslot (slot_cur, cmd);
+ retval = ibmphp_hpc_writeslot(slot_cur, cmd);
if (retval) {
- err ("power on failed\n");
+ err("power on failed\n");
return retval;
}
- if (CTLR_RESULT (slot_cur->ctrl->status)) {
- err ("command not completed successfully in power_on\n");
+ if (CTLR_RESULT(slot_cur->ctrl->status)) {
+ err("command not completed successfully in power_on\n");
return -EIO;
}
msleep(3000); /* For ServeRAID cards, and some 66 PCI */
return 0;
}
-static inline int power_off (struct slot *slot_cur)
+static inline int power_off(struct slot *slot_cur)
{
u8 cmd = HPC_SLOT_OFF;
int retval;
- retval = ibmphp_hpc_writeslot (slot_cur, cmd);
+ retval = ibmphp_hpc_writeslot(slot_cur, cmd);
if (retval) {
- err ("power off failed\n");
+ err("power off failed\n");
return retval;
}
- if (CTLR_RESULT (slot_cur->ctrl->status)) {
- err ("command not completed successfully in power_off\n");
+ if (CTLR_RESULT(slot_cur->ctrl->status)) {
+ err("command not completed successfully in power_off\n");
retval = -EIO;
}
return retval;
}
-static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 value)
+static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)
{
int rc = 0;
struct slot *pslot;
u8 cmd;
- debug ("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n", (ulong) hotplug_slot, value);
- ibmphp_lock_operations ();
+ debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n",
+ (ulong) hotplug_slot, value);
+ ibmphp_lock_operations();
cmd = 0x00; // avoid compiler warning
if (hotplug_slot) {
@@ -234,11 +255,12 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 value)
break;
default:
rc = -ENODEV;
- err ("set_attention_status - Error : invalid input [%x]\n", value);
+ err("set_attention_status - Error : invalid input [%x]\n",
+ value);
break;
}
if (rc == 0) {
- pslot = (struct slot *) hotplug_slot->private;
+ pslot = hotplug_slot->private;
if (pslot)
rc = ibmphp_hpc_writeslot(pslot, cmd);
else
@@ -247,101 +269,114 @@ static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 value)
} else
rc = -ENODEV;
- ibmphp_unlock_operations ();
+ ibmphp_unlock_operations();
- debug ("set_attention_status - Exit rc[%d]\n", rc);
+ debug("set_attention_status - Exit rc[%d]\n", rc);
return rc;
}
-static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 * value)
+static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
{
int rc = -ENODEV;
struct slot *pslot;
struct slot myslot;
- debug ("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
+ debug("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
+ (ulong) hotplug_slot, (ulong) value);
- ibmphp_lock_operations ();
+ ibmphp_lock_operations();
if (hotplug_slot && value) {
- pslot = (struct slot *) hotplug_slot->private;
+ pslot = hotplug_slot->private;
if (pslot) {
- memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
- rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status));
+ memcpy(&myslot, pslot, sizeof(struct slot));
+ rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,
+ &(myslot.status));
if (!rc)
- rc = ibmphp_hpc_readslot(pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status));
+ rc = ibmphp_hpc_readslot(pslot,
+ READ_EXTSLOTSTATUS,
+ &(myslot.ext_status));
if (!rc)
- *value = SLOT_ATTN (myslot.status, myslot.ext_status);
+ *value = SLOT_ATTN(myslot.status,
+ myslot.ext_status);
}
}
- ibmphp_unlock_operations ();
+ ibmphp_unlock_operations();
debug("get_attention_status - Exit rc[%d] value[%x]\n", rc, *value);
return rc;
}
-static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 * value)
+static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
{
int rc = -ENODEV;
struct slot *pslot;
struct slot myslot;
- debug ("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
- ibmphp_lock_operations ();
+ debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
+ (ulong) hotplug_slot, (ulong) value);
+ ibmphp_lock_operations();
if (hotplug_slot && value) {
- pslot = (struct slot *) hotplug_slot->private;
+ pslot = hotplug_slot->private;
if (pslot) {
- memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
- rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status));
+ memcpy(&myslot, pslot, sizeof(struct slot));
+ rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,
+ &(myslot.status));
if (!rc)
- *value = SLOT_LATCH (myslot.status);
+ *value = SLOT_LATCH(myslot.status);
}
}
- ibmphp_unlock_operations ();
- debug("get_latch_status - Exit rc[%d] rc[%x] value[%x]\n", rc, rc, *value);
+ ibmphp_unlock_operations();
+ debug("get_latch_status - Exit rc[%d] rc[%x] value[%x]\n",
+ rc, rc, *value);
return rc;
}
-static int get_power_status (struct hotplug_slot *hotplug_slot, u8 * value)
+static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
{
int rc = -ENODEV;
struct slot *pslot;
struct slot myslot;
- debug ("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
- ibmphp_lock_operations ();
+ debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
+ (ulong) hotplug_slot, (ulong) value);
+ ibmphp_lock_operations();
if (hotplug_slot && value) {
- pslot = (struct slot *) hotplug_slot->private;
+ pslot = hotplug_slot->private;
if (pslot) {
- memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
- rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status));
+ memcpy(&myslot, pslot, sizeof(struct slot));
+ rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,
+ &(myslot.status));
if (!rc)
- *value = SLOT_PWRGD (myslot.status);
+ *value = SLOT_PWRGD(myslot.status);
}
}
- ibmphp_unlock_operations ();
- debug("get_power_status - Exit rc[%d] rc[%x] value[%x]\n", rc, rc, *value);
+ ibmphp_unlock_operations();
+ debug("get_power_status - Exit rc[%d] rc[%x] value[%x]\n",
+ rc, rc, *value);
return rc;
}
-static int get_adapter_present (struct hotplug_slot *hotplug_slot, u8 * value)
+static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value)
{
int rc = -ENODEV;
struct slot *pslot;
u8 present;
struct slot myslot;
- debug ("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong) hotplug_slot, (ulong) value);
- ibmphp_lock_operations ();
+ debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",
+ (ulong) hotplug_slot, (ulong) value);
+ ibmphp_lock_operations();
if (hotplug_slot && value) {
- pslot = (struct slot *) hotplug_slot->private;
+ pslot = hotplug_slot->private;
if (pslot) {
- memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
- rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status));
+ memcpy(&myslot, pslot, sizeof(struct slot));
+ rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,
+ &(myslot.status));
if (!rc) {
- present = SLOT_PRESENT (myslot.status);
+ present = SLOT_PRESENT(myslot.status);
if (present == HPC_SLOT_EMPTY)
*value = 0;
else
@@ -350,24 +385,24 @@ static int get_adapter_present (struct hotplug_slot *hotplug_slot, u8 * value)
}
}
- ibmphp_unlock_operations ();
+ ibmphp_unlock_operations();
debug("get_adapter_present - Exit rc[%d] value[%x]\n", rc, *value);
return rc;
}
-static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
{
int rc = -ENODEV;
struct slot *pslot;
u8 mode = 0;
- debug ("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
+ debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
hotplug_slot, value);
- ibmphp_lock_operations ();
+ ibmphp_lock_operations();
if (hotplug_slot && value) {
- pslot = (struct slot *) hotplug_slot->private;
+ pslot = hotplug_slot->private;
if (pslot) {
rc = 0;
mode = pslot->supported_bus_mode;
@@ -390,26 +425,26 @@ static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
}
}
- ibmphp_unlock_operations ();
- debug ("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
+ ibmphp_unlock_operations();
+ debug("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
return rc;
}
-static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
+static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
{
int rc = -ENODEV;
struct slot *pslot;
u8 mode = 0;
- debug ("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
+ debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __FUNCTION__,
hotplug_slot, value);
- ibmphp_lock_operations ();
+ ibmphp_lock_operations();
if (hotplug_slot && value) {
- pslot = (struct slot *) hotplug_slot->private;
+ pslot = hotplug_slot->private;
if (pslot) {
- rc = get_cur_bus_info (&pslot);
+ rc = get_cur_bus_info(&pslot);
if (!rc) {
mode = pslot->bus_on->current_bus_mode;
*value = pslot->bus_on->current_speed;
@@ -436,121 +471,129 @@ static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_sp
}
}
- ibmphp_unlock_operations ();
- debug ("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
+ ibmphp_unlock_operations();
+ debug("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);
return rc;
}
+
/*
-static int get_max_adapter_speed_1 (struct hotplug_slot *hotplug_slot, u8 * value, u8 flag)
+static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 * value, u8 flag)
{
int rc = -ENODEV;
struct slot *pslot;
struct slot myslot;
- debug ("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value);
+ debug("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n",
+ (ulong)hotplug_slot, (ulong) value);
if (flag)
- ibmphp_lock_operations ();
+ ibmphp_lock_operations();
if (hotplug_slot && value) {
- pslot = (struct slot *) hotplug_slot->private;
+ pslot = hotplug_slot->private;
if (pslot) {
- memcpy ((void *) &myslot, (void *) pslot, sizeof (struct slot));
- rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS, &(myslot.status));
-
- if (!(SLOT_LATCH (myslot.status)) && (SLOT_PRESENT (myslot.status))) {
- rc = ibmphp_hpc_readslot(pslot, READ_EXTSLOTSTATUS, &(myslot.ext_status));
+ memcpy(&myslot, pslot, sizeof(struct slot));
+ rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,
+ &(myslot.status));
+
+ if (!(SLOT_LATCH (myslot.status)) &&
+ (SLOT_PRESENT (myslot.status))) {
+ rc = ibmphp_hpc_readslot(pslot,
+ READ_EXTSLOTSTATUS,
+ &(myslot.ext_status));
if (!rc)
- *value = SLOT_SPEED (myslot.ext_status);
+ *value = SLOT_SPEED(myslot.ext_status);
} else
*value = MAX_ADAPTER_NONE;
}
}
if (flag)
- ibmphp_unlock_operations ();
+ ibmphp_unlock_operations();
debug("get_max_adapter_speed_1 - Exit rc[%d] value[%x]\n", rc, *value);
return rc;
}
-static int get_bus_name (struct hotplug_slot *hotplug_slot, char * value)
+static int get_bus_name(struct hotplug_slot *hotplug_slot, char * value)
{
int rc = -ENODEV;
struct slot *pslot = NULL;
- debug ("get_bus_name - Entry hotplug_slot[%lx]\n", (ulong)hotplug_slot);
+ debug("get_bus_name - Entry hotplug_slot[%lx]\n", (ulong)hotplug_slot);
- ibmphp_lock_operations ();
+ ibmphp_lock_operations();
if (hotplug_slot) {
- pslot = (struct slot *) hotplug_slot->private;
+ pslot = hotplug_slot->private;
if (pslot) {
rc = 0;
- snprintf (value, 100, "Bus %x", pslot->bus);
+ snprintf(value, 100, "Bus %x", pslot->bus);
}
} else
rc = -ENODEV;
- ibmphp_unlock_operations ();
- debug ("get_bus_name - Exit rc[%d] value[%x]\n", rc, *value);
+ ibmphp_unlock_operations();
+ debug("get_bus_name - Exit rc[%d] value[%x]\n", rc, *value);
return rc;
}
*/
-/*******************************************************************************
+/****************************************************************************
* This routine will initialize the ops data structure used in the validate
* function. It will also power off empty slots that are powered on since BIOS
* leaves those on, albeit disconnected
- ******************************************************************************/
-static int __init init_ops (void)
+ ****************************************************************************/
+static int __init init_ops(void)
{
struct slot *slot_cur;
struct list_head *tmp;
int retval;
int rc;
- list_for_each (tmp, &ibmphp_slot_head) {
- slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
+ list_for_each(tmp, &ibmphp_slot_head) {
+ slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
if (!slot_cur)
return -ENODEV;
- debug ("BEFORE GETTING SLOT STATUS, slot # %x\n", slot_cur->number);
+ debug("BEFORE GETTING SLOT STATUS, slot # %x\n",
+ slot_cur->number);
if (slot_cur->ctrl->revision == 0xFF)
- if (get_ctrl_revision (slot_cur, &slot_cur->ctrl->revision))
+ if (get_ctrl_revision(slot_cur,
+ &slot_cur->ctrl->revision))
return -1;
if (slot_cur->bus_on->current_speed == 0xFF)
- if (get_cur_bus_info (&slot_cur))
+ if (get_cur_bus_info(&slot_cur))
return -1;
if (slot_cur->ctrl->options == 0xFF)
- if (get_hpc_options (slot_cur, &slot_cur->ctrl->options))
+ if (get_hpc_options(slot_cur, &slot_cur->ctrl->options))
return -1;
- retval = slot_update (&slot_cur);
+ retval = slot_update(&slot_cur);
if (retval)
return retval;
- debug ("status = %x\n", slot_cur->status);
- debug ("ext_status = %x\n", slot_cur->ext_status);
- debug ("SLOT_POWER = %x\n", SLOT_POWER (slot_cur->status));
- debug ("SLOT_PRESENT = %x\n", SLOT_PRESENT (slot_cur->status));
- debug ("SLOT_LATCH = %x\n", SLOT_LATCH (slot_cur->status));
-
- if ((SLOT_PWRGD (slot_cur->status)) &&
- !(SLOT_PRESENT (slot_cur->status)) &&
- !(SLOT_LATCH (slot_cur->status))) {
- debug ("BEFORE POWER OFF COMMAND\n");
- rc = power_off (slot_cur);
+ debug("status = %x\n", slot_cur->status);
+ debug("ext_status = %x\n", slot_cur->ext_status);
+ debug("SLOT_POWER = %x\n", SLOT_POWER(slot_cur->status));
+ debug("SLOT_PRESENT = %x\n", SLOT_PRESENT(slot_cur->status));
+ debug("SLOT_LATCH = %x\n", SLOT_LATCH(slot_cur->status));
+
+ if ((SLOT_PWRGD(slot_cur->status)) &&
+ !(SLOT_PRESENT(slot_cur->status)) &&
+ !(SLOT_LATCH(slot_cur->status))) {
+ debug("BEFORE POWER OFF COMMAND\n");
+ rc = power_off(slot_cur);
if (rc)
return rc;
- /* retval = slot_update (&slot_cur);
+ /* retval = slot_update(&slot_cur);
* if (retval)
* return retval;
- * ibmphp_update_slot_info (slot_cur);
+ * ibmphp_update_slot_info(slot_cur);
*/
}
}
@@ -563,7 +606,7 @@ static int __init init_ops (void)
* Parameters: slot, operation
* Returns: 0 or error codes
*/
-static int validate (struct slot *slot_cur, int opn)
+static int validate(struct slot *slot_cur, int opn)
{
int number;
int retval;
@@ -573,89 +616,91 @@ static int validate (struct slot *slot_cur, int opn)
number = slot_cur->number;
if ((number > max_slots) || (number < 0))
return -EBADSLT;
- debug ("slot_number in validate is %d\n", slot_cur->number);
+ debug("slot_number in validate is %d\n", slot_cur->number);
- retval = slot_update (&slot_cur);
+ retval = slot_update(&slot_cur);
if (retval)
return retval;
switch (opn) {
case ENABLE:
- if (!(SLOT_PWRGD (slot_cur->status)) &&
- (SLOT_PRESENT (slot_cur->status)) &&
- !(SLOT_LATCH (slot_cur->status)))
+ if (!(SLOT_PWRGD(slot_cur->status)) &&
+ (SLOT_PRESENT(slot_cur->status)) &&
+ !(SLOT_LATCH(slot_cur->status)))
return 0;
break;
case DISABLE:
- if ((SLOT_PWRGD (slot_cur->status)) &&
- (SLOT_PRESENT (slot_cur->status)) &&
- !(SLOT_LATCH (slot_cur->status)))
+ if ((SLOT_PWRGD(slot_cur->status)) &&
+ (SLOT_PRESENT(slot_cur->status)) &&
+ !(SLOT_LATCH(slot_cur->status)))
return 0;
break;
default:
break;
}
- err ("validate failed....\n");
+ err("validate failed....\n");
return -EINVAL;
}
-/********************************************************************************
+/****************************************************************************
* This routine is for updating the data structures in the hotplug core
* Parameters: struct slot
* Returns: 0 or error
- *******************************************************************************/
-int ibmphp_update_slot_info (struct slot *slot_cur)
+ ****************************************************************************/
+int ibmphp_update_slot_info(struct slot *slot_cur)
{
struct hotplug_slot_info *info;
int rc;
u8 bus_speed;
u8 mode;
- info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL);
+ info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL);
if (!info) {
- err ("out of system memory\n");
+ err("out of system memory\n");
return -ENOMEM;
}
- info->power_status = SLOT_PWRGD (slot_cur->status);
- info->attention_status = SLOT_ATTN (slot_cur->status, slot_cur->ext_status);
- info->latch_status = SLOT_LATCH (slot_cur->status);
- if (!SLOT_PRESENT (slot_cur->status)) {
+ info->power_status = SLOT_PWRGD(slot_cur->status);
+ info->attention_status = SLOT_ATTN(slot_cur->status,
+ slot_cur->ext_status);
+ info->latch_status = SLOT_LATCH(slot_cur->status);
+ if (!SLOT_PRESENT(slot_cur->status)) {
info->adapter_status = 0;
-// info->max_adapter_speed_status = MAX_ADAPTER_NONE;
+/* info->max_adapter_speed_status = MAX_ADAPTER_NONE; */
} else {
info->adapter_status = 1;
-// get_max_adapter_speed_1 (slot_cur->hotplug_slot, &info->max_adapter_speed_status, 0);
+/* get_max_adapter_speed_1(slot_cur->hotplug_slot,
+ &info->max_adapter_speed_status, 0); */
}
bus_speed = slot_cur->bus_on->current_speed;
mode = slot_cur->bus_on->current_bus_mode;
switch (bus_speed) {
- case BUS_SPEED_33:
- break;
- case BUS_SPEED_66:
- if (mode == BUS_MODE_PCIX)
+ case BUS_SPEED_33:
+ break;
+ case BUS_SPEED_66:
+ if (mode == BUS_MODE_PCIX)
+ bus_speed += 0x01;
+ else if (mode == BUS_MODE_PCI)
+ ;
+ else
+ bus_speed = PCI_SPEED_UNKNOWN;
+ break;
+ case BUS_SPEED_100:
+ case BUS_SPEED_133:
bus_speed += 0x01;
- else if (mode == BUS_MODE_PCI)
- ;
- else
+ break;
+ default:
bus_speed = PCI_SPEED_UNKNOWN;
- break;
- case BUS_SPEED_100:
- case BUS_SPEED_133:
- bus_speed += 0x01;
- break;
- default:
- bus_speed = PCI_SPEED_UNKNOWN;
}
info->cur_bus_speed = bus_speed;
info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed;
// To do: bus_names
- rc = pci_hp_change_slot_info (slot_cur->hotplug_slot, info);
- kfree (info);
+ rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info);
+ kfree(info);
return rc;
}
@@ -665,17 +710,19 @@ int ibmphp_update_slot_info (struct slot *slot_cur)
* is called from visit routines
******************************************************************************/
-static struct pci_func *ibm_slot_find (u8 busno, u8 device, u8 function)
+static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function)
{
struct pci_func *func_cur;
struct slot *slot_cur;
struct list_head * tmp;
- list_for_each (tmp, &ibmphp_slot_head) {
- slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
+ list_for_each(tmp, &ibmphp_slot_head) {
+ slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
if (slot_cur->func) {
func_cur = slot_cur->func;
while (func_cur) {
- if ((func_cur->busno == busno) && (func_cur->device == device) && (func_cur->function == function))
+ if ((func_cur->busno == busno) &&
+ (func_cur->device == device) &&
+ (func_cur->function == function))
return func_cur;
func_cur = func_cur->next;
}
@@ -689,19 +736,19 @@ static struct pci_func *ibm_slot_find (u8 busno, u8 device, u8 function)
* the pointers to pci_func, bus, hotplug_slot, controller,
* and deregistering from the hotplug core
*************************************************************/
-static void free_slots (void)
+static void free_slots(void)
{
struct slot *slot_cur;
struct list_head * tmp;
struct list_head * next;
- debug ("%s -- enter\n", __FUNCTION__);
+ debug("%s -- enter\n", __FUNCTION__);
- list_for_each_safe (tmp, next, &ibmphp_slot_head) {
- slot_cur = list_entry (tmp, struct slot, ibm_slot_list);
- pci_hp_deregister (slot_cur->hotplug_slot);
+ list_for_each_safe(tmp, next, &ibmphp_slot_head) {
+ slot_cur = list_entry(tmp, struct slot, ibm_slot_list);
+ pci_hp_deregister(slot_cur->hotplug_slot);
}
- debug ("%s -- exit\n", __FUNCTION__);
+ debug("%s -- exit\n", __FUNCTION__);
}
static void ibm_unconfigure_device(struct pci_func *func)
@@ -710,7 +757,8 @@ static void ibm_unconfigure_device(struct pci_func *func)
u8 j;
debug("inside %s\n", __FUNCTION__);
- debug("func->device = %x, func->function = %x\n", func->device, func->function);
+ debug("func->device = %x, func->function = %x\n",
+ func->device, func->function);
debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0);
for (j = 0; j < 0x08; j++) {
@@ -725,25 +773,24 @@ static void ibm_unconfigure_device(struct pci_func *func)
* getting bus entries, here we manually add those primary
* bus entries to kernel bus structure whenever apply
*/
-
-static u8 bus_structure_fixup (u8 busno)
+static u8 bus_structure_fixup(u8 busno)
{
struct pci_bus *bus;
struct pci_dev *dev;
u16 l;
- if (pci_find_bus(0, busno) || !(ibmphp_find_same_bus_num (busno)))
+ if (pci_find_bus(0, busno) || !(ibmphp_find_same_bus_num(busno)))
return 1;
- bus = kmalloc (sizeof (*bus), GFP_KERNEL);
+ bus = kmalloc(sizeof(*bus), GFP_KERNEL);
if (!bus) {
- err ("%s - out of memory\n", __FUNCTION__);
+ err("%s - out of memory\n", __FUNCTION__);
return 1;
}
- dev = kmalloc (sizeof (*dev), GFP_KERNEL);
+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
- kfree (bus);
- err ("%s - out of memory\n", __FUNCTION__);
+ kfree(bus);
+ err("%s - out of memory\n", __FUNCTION__);
return 1;
}
@@ -751,50 +798,56 @@ static u8 bus_structure_fixup (u8 busno)
bus->ops = ibmphp_pci_bus->ops;
dev->bus = bus;
for (dev->devfn = 0; dev->devfn < 256; dev->devfn += 8) {
- if (!pci_read_config_word (dev, PCI_VENDOR_ID, &l) && l != 0x0000 && l != 0xffff) {
- debug ("%s - Inside bus_struture_fixup()\n", __FUNCTION__);
- pci_scan_bus (busno, ibmphp_pci_bus->ops, NULL);
+ if (!pci_read_config_word(dev, PCI_VENDOR_ID, &l) &&
+ (l != 0x0000) && (l != 0xffff)) {
+ debug("%s - Inside bus_struture_fixup()\n",
+ __FUNCTION__);
+ pci_scan_bus(busno, ibmphp_pci_bus->ops, NULL);
break;
}
}
- kfree (dev);
- kfree (bus);
+ kfree(dev);
+ kfree(bus);
return 0;
}
-static int ibm_configure_device (struct pci_func *func)
+static int ibm_configure_device(struct pci_func *func)
{
unsigned char bus;
struct pci_bus *child;
int num;
- int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */
+ int flag = 0; /* this is to make sure we don't double scan the bus,
+ for bridged devices primarily */
- if (!(bus_structure_fixup (func->busno)))
+ if (!(bus_structure_fixup(func->busno)))
flag = 1;
if (func->dev == NULL)
- func->dev = pci_find_slot (func->busno, PCI_DEVFN(func->device, func->function));
+ func->dev = pci_find_slot(func->busno,
+ PCI_DEVFN(func->device, func->function));
if (func->dev == NULL) {
struct pci_bus *bus = pci_find_bus(0, func->busno);
if (!bus)
return 0;
- num = pci_scan_slot(bus, PCI_DEVFN(func->device, func->function));
+ num = pci_scan_slot(bus,
+ PCI_DEVFN(func->device, func->function));
if (num)
pci_bus_add_devices(bus);
- func->dev = pci_find_slot(func->busno, PCI_DEVFN(func->device, func->function));
+ func->dev = pci_find_slot(func->busno,
+ PCI_DEVFN(func->device, func->function));
if (func->dev == NULL) {
- err ("ERROR... : pci_dev still NULL\n");
+ err("ERROR... : pci_dev still NULL\n");
return 0;
}
}
if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
- pci_read_config_byte (func->dev, PCI_SECONDARY_BUS, &bus);
- child = (struct pci_bus *) pci_add_new_bus (func->dev->bus, (func->dev), bus);
- pci_do_scan_bus (child);
+ pci_read_config_byte(func->dev, PCI_SECONDARY_BUS, &bus);
+ child = pci_add_new_bus(func->dev->bus, func->dev, bus);
+ pci_do_scan_bus(child);
}
return 0;
@@ -803,7 +856,7 @@ static int ibm_configure_device (struct pci_func *func)
/*******************************************************
* Returns whether the bus is empty or not
*******************************************************/
-static int is_bus_empty (struct slot * slot_cur)
+static int is_bus_empty(struct slot * slot_cur)
{
int rc;
struct slot * tmp_slot;
@@ -814,13 +867,14 @@ static int is_bus_empty (struct slot * slot_cur)
i++;
continue;
}
- tmp_slot = ibmphp_get_slot_from_physical_num (i);
+ tmp_slot = ibmphp_get_slot_from_physical_num(i);
if (!tmp_slot)
return 0;
- rc = slot_update (&tmp_slot);
+ rc = slot_update(&tmp_slot);
if (rc)
return 0;
- if (SLOT_PRESENT (tmp_slot->status) && SLOT_PWRGD (tmp_slot->status))
+ if (SLOT_PRESENT(tmp_slot->status) &&
+ SLOT_PWRGD(tmp_slot->status))
return 0;
i++;
}
@@ -833,7 +887,7 @@ static int is_bus_empty (struct slot * slot_cur)
* Parameters: slot
* Returns: bus is set (0) or error code
***********************************************************/
-static int set_bus (struct slot * slot_cur)
+static int set_bus(struct slot * slot_cur)
{
int rc;
u8 speed;
@@ -844,22 +898,23 @@ static int set_bus (struct slot * slot_cur)
{ },
};
- debug ("%s - entry slot # %d\n", __FUNCTION__, slot_cur->number);
- if (SET_BUS_STATUS (slot_cur->ctrl) && is_bus_empty (slot_cur)) {
- rc = slot_update (&slot_cur);
+ debug("%s - entry slot # %d\n", __FUNCTION__, slot_cur->number);
+ if (SET_BUS_STATUS(slot_cur->ctrl) && is_bus_empty(slot_cur)) {
+ rc = slot_update(&slot_cur);
if (rc)
return rc;
- speed = SLOT_SPEED (slot_cur->ext_status);
- debug ("ext_status = %x, speed = %x\n", slot_cur->ext_status, speed);
+ speed = SLOT_SPEED(slot_cur->ext_status);
+ debug("ext_status = %x, speed = %x\n", slot_cur->ext_status, speed);
switch (speed) {
case HPC_SLOT_SPEED_33:
cmd = HPC_BUS_33CONVMODE;
break;
case HPC_SLOT_SPEED_66:
- if (SLOT_PCIX (slot_cur->ext_status)) {
- if ((slot_cur->supported_speed >= BUS_SPEED_66) && (slot_cur->supported_bus_mode == BUS_MODE_PCIX))
+ if (SLOT_PCIX(slot_cur->ext_status)) {
+ if ((slot_cur->supported_speed >= BUS_SPEED_66) &&
+ (slot_cur->supported_bus_mode == BUS_MODE_PCIX))
cmd = HPC_BUS_66PCIXMODE;
- else if (!SLOT_BUS_MODE (slot_cur->ext_status))
+ else if (!SLOT_BUS_MODE(slot_cur->ext_status))
/* if max slot/bus capability is 66 pci
and there's no bus mode mismatch, then
the adapter supports 66 pci */
@@ -890,33 +945,35 @@ static int set_bus (struct slot * slot_cur)
case BUS_SPEED_133:
/* This is to take care of the bug in CIOBX chip */
if (pci_dev_present(ciobx))
- ibmphp_hpc_writeslot (slot_cur, HPC_BUS_100PCIXMODE);
+ ibmphp_hpc_writeslot(slot_cur,
+ HPC_BUS_100PCIXMODE);
cmd = HPC_BUS_133PCIXMODE;
break;
default:
- err ("Wrong bus speed\n");
+ err("Wrong bus speed\n");
return -ENODEV;
}
break;
default:
- err ("wrong slot speed\n");
+ err("wrong slot speed\n");
return -ENODEV;
}
- debug ("setting bus speed for slot %d, cmd %x\n", slot_cur->number, cmd);
- retval = ibmphp_hpc_writeslot (slot_cur, cmd);
+ debug("setting bus speed for slot %d, cmd %x\n",
+ slot_cur->number, cmd);
+ retval = ibmphp_hpc_writeslot(slot_cur, cmd);
if (retval) {
- err ("setting bus speed failed\n");
+ err("setting bus speed failed\n");
return retval;
}
- if (CTLR_RESULT (slot_cur->ctrl->status)) {
- err ("command not completed successfully in set_bus\n");
+ if (CTLR_RESULT(slot_cur->ctrl->status)) {
+ err("command not completed successfully in set_bus\n");
return -EIO;
}
}
/* This is for x440, once Brandon fixes the firmware,
will not need this delay */
msleep(1000);
- debug ("%s -Exit\n", __FUNCTION__);
+ debug("%s -Exit\n", __FUNCTION__);
return 0;
}
@@ -927,7 +984,7 @@ static int set_bus (struct slot * slot_cur)
* Parameters: slot
* Returns: 0 = no limitations, -EINVAL = exceeded limitations on the bus
*/
-static int check_limitations (struct slot *slot_cur)
+static int check_limitations(struct slot *slot_cur)
{
u8 i;
struct slot * tmp_slot;
@@ -935,13 +992,14 @@ static int check_limitations (struct slot *slot_cur)
u8 limitation = 0;
for (i = slot_cur->bus_on->slot_min; i <= slot_cur->bus_on->slot_max; i++) {
- tmp_slot = ibmphp_get_slot_from_physical_num (i);
+ tmp_slot = ibmphp_get_slot_from_physical_num(i);
if (!tmp_slot)
return -ENODEV;
- if ((SLOT_PWRGD (tmp_slot->status)) && !(SLOT_CONNECT (tmp_slot->status)))
+ if ((SLOT_PWRGD(tmp_slot->status)) &&
+ !(SLOT_CONNECT(tmp_slot->status)))
count++;
}
- get_cur_bus_info (&slot_cur);
+ get_cur_bus_info(&slot_cur);
switch (slot_cur->bus_on->current_speed) {
case BUS_SPEED_33:
limitation = slot_cur->bus_on->slots_at_33_conv;
@@ -965,17 +1023,17 @@ static int check_limitations (struct slot *slot_cur)
return 0;
}
-static inline void print_card_capability (struct slot *slot_cur)
+static inline void print_card_capability(struct slot *slot_cur)
{
- info ("capability of the card is ");
+ info("capability of the card is ");
if ((slot_cur->ext_status & CARD_INFO) == PCIX133)
- info (" 133 MHz PCI-X\n");
+ info(" 133 MHz PCI-X\n");
else if ((slot_cur->ext_status & CARD_INFO) == PCIX66)
- info (" 66 MHz PCI-X\n");
+ info(" 66 MHz PCI-X\n");
else if ((slot_cur->ext_status & CARD_INFO) == PCI66)
- info (" 66 MHz PCI\n");
+ info(" 66 MHz PCI\n");
else
- info (" 33 MHz PCI\n");
+ info(" 33 MHz PCI\n");
}
@@ -984,118 +1042,128 @@ static inline void print_card_capability (struct slot *slot_cur)
* Parameters: hotplug_slot
* Returns: 0 or failure codes
*/
-static int enable_slot (struct hotplug_slot *hs)
+static int enable_slot(struct hotplug_slot *hs)
{
int rc, i, rcpr;
struct slot *slot_cur;
u8 function;
struct pci_func *tmp_func;
- ibmphp_lock_operations ();
+ ibmphp_lock_operations();
- debug ("ENABLING SLOT........\n");
- slot_cur = (struct slot *) hs->private;
+ debug("ENABLING SLOT........\n");
+ slot_cur = hs->private;
- if ((rc = validate (slot_cur, ENABLE))) {
- err ("validate function failed\n");
+ if ((rc = validate(slot_cur, ENABLE))) {
+ err("validate function failed\n");
goto error_nopower;
}
- attn_LED_blink (slot_cur);
+ attn_LED_blink(slot_cur);
- rc = set_bus (slot_cur);
+ rc = set_bus(slot_cur);
if (rc) {
- err ("was not able to set the bus\n");
+ err("was not able to set the bus\n");
goto error_nopower;
}
/*-----------------debugging------------------------------*/
- get_cur_bus_info (&slot_cur);
- debug ("the current bus speed right after set_bus = %x\n", slot_cur->bus_on->current_speed);
+ get_cur_bus_info(&slot_cur);
+ debug("the current bus speed right after set_bus = %x\n",
+ slot_cur->bus_on->current_speed);
/*----------------------------------------------------------*/
- rc = check_limitations (slot_cur);
+ rc = check_limitations(slot_cur);
if (rc) {
- err ("Adding this card exceeds the limitations of this bus.\n");
- err ("(i.e., >1 133MHz cards running on same bus, or "
+ err("Adding this card exceeds the limitations of this bus.\n");
+ err("(i.e., >1 133MHz cards running on same bus, or "
">2 66 PCI cards running on same bus\n.");
- err ("Try hot-adding into another bus\n");
+ err("Try hot-adding into another bus\n");
rc = -EINVAL;
goto error_nopower;
}
- rc = power_on (slot_cur);
+ rc = power_on(slot_cur);
if (rc) {
- err ("something wrong when powering up... please see below for details\n");
+ err("something wrong when powering up... please see below for details\n");
/* need to turn off before on, otherwise, blinking overwrites */
attn_off(slot_cur);
- attn_on (slot_cur);
- if (slot_update (&slot_cur)) {
- attn_off (slot_cur);
- attn_on (slot_cur);
+ attn_on(slot_cur);
+ if (slot_update(&slot_cur)) {
+ attn_off(slot_cur);
+ attn_on(slot_cur);
rc = -ENODEV;
goto exit;
}
/* Check to see the error of why it failed */
- if ((SLOT_POWER (slot_cur->status)) && !(SLOT_PWRGD (slot_cur->status)))
- err ("power fault occurred trying to power up\n");
- else if (SLOT_BUS_SPEED (slot_cur->status)) {
- err ("bus speed mismatch occurred. please check current bus speed and card capability\n");
- print_card_capability (slot_cur);
- } else if (SLOT_BUS_MODE (slot_cur->ext_status)) {
- err ("bus mode mismatch occurred. please check current bus mode and card capability\n");
- print_card_capability (slot_cur);
+ if ((SLOT_POWER(slot_cur->status)) &&
+ !(SLOT_PWRGD(slot_cur->status)))
+ err("power fault occurred trying to power up\n");
+ else if (SLOT_BUS_SPEED(slot_cur->status)) {
+ err("bus speed mismatch occurred. please check "
+ "current bus speed and card capability\n");
+ print_card_capability(slot_cur);
+ } else if (SLOT_BUS_MODE(slot_cur->ext_status)) {
+ err("bus mode mismatch occurred. please check "
+ "current bus mode and card capability\n");
+ print_card_capability(slot_cur);
}
- ibmphp_update_slot_info (slot_cur);
+ ibmphp_update_slot_info(slot_cur);
goto exit;
}
- debug ("after power_on\n");
+ debug("after power_on\n");
/*-----------------------debugging---------------------------*/
- get_cur_bus_info (&slot_cur);
- debug ("the current bus speed right after power_on = %x\n", slot_cur->bus_on->current_speed);
+ get_cur_bus_info(&slot_cur);
+ debug("the current bus speed right after power_on = %x\n",
+ slot_cur->bus_on->current_speed);
/*----------------------------------------------------------*/
- rc = slot_update (&slot_cur);
+ rc = slot_update(&slot_cur);
if (rc)
goto error_power;
rc = -EINVAL;
- if (SLOT_POWER (slot_cur->status) && !(SLOT_PWRGD (slot_cur->status))) {
- err ("power fault occurred trying to power up...\n");
+ if (SLOT_POWER(slot_cur->status) && !(SLOT_PWRGD(slot_cur->status))) {
+ err("power fault occurred trying to power up...\n");
goto error_power;
}
- if (SLOT_POWER (slot_cur->status) && (SLOT_BUS_SPEED (slot_cur->status))) {
- err ("bus speed mismatch occurred. please check current bus speed and card capability\n");
- print_card_capability (slot_cur);
+ if (SLOT_POWER(slot_cur->status) && (SLOT_BUS_SPEED(slot_cur->status))) {
+ err("bus speed mismatch occurred. please check current bus "
+ "speed and card capability\n");
+ print_card_capability(slot_cur);
goto error_power;
}
- /* Don't think this case will happen after above checks... but just in case, for paranoia sake */
- if (!(SLOT_POWER (slot_cur->status))) {
- err ("power on failed...\n");
+ /* Don't think this case will happen after above checks...
+ * but just in case, for paranoia sake */
+ if (!(SLOT_POWER(slot_cur->status))) {
+ err("power on failed...\n");
goto error_power;
}
- slot_cur->func = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+ slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL);
if (!slot_cur->func) {
/* We cannot do update_slot_info here, since no memory for
* kmalloc n.e.ways, and update_slot_info allocates some */
- err ("out of system memory\n");
+ err("out of system memory\n");
rc = -ENOMEM;
goto error_power;
}
- memset (slot_cur->func, 0, sizeof (struct pci_func));
+ memset(slot_cur->func, 0, sizeof(struct pci_func));
slot_cur->func->busno = slot_cur->bus;
slot_cur->func->device = slot_cur->device;
for (i = 0; i < 4; i++)
slot_cur->func->irq[i] = slot_cur->irq[i];
- debug ("b4 configure_card, slot_cur->bus = %x, slot_cur->device = %x\n", slot_cur->bus, slot_cur->device);
+ debug("b4 configure_card, slot_cur->bus = %x, slot_cur->device = %x\n",
+ slot_cur->bus, slot_cur->device);
- if (ibmphp_configure_card (slot_cur->func, slot_cur->number)) {
- err ("configure_card was unsuccessful...\n");
- ibmphp_unconfigure_card (&slot_cur, 1); /* true because don't need to actually deallocate resources, just remove references */
- debug ("after unconfigure_card\n");
+ if (ibmphp_configure_card(slot_cur->func, slot_cur->number)) {
+ err("configure_card was unsuccessful...\n");
+ /* true because don't need to actually deallocate resources,
+ * just remove references */
+ ibmphp_unconfigure_card(&slot_cur, 1);
+ debug("after unconfigure_card\n");
slot_cur->func = NULL;
rc = -ENOMEM;
goto error_power;
@@ -1103,38 +1171,39 @@ static int enable_slot (struct hotplug_slot *hs)
function = 0x00;
do {
- tmp_func = ibm_slot_find (slot_cur->bus, slot_cur->func->device, function++);
+ tmp_func = ibm_slot_find(slot_cur->bus, slot_cur->func->device,
+ function++);
if (tmp_func && !(tmp_func->dev))
- ibm_configure_device (tmp_func);
+ ibm_configure_device(tmp_func);
} while (tmp_func);
- attn_off (slot_cur);
- if (slot_update (&slot_cur)) {
+ attn_off(slot_cur);
+ if (slot_update(&slot_cur)) {
rc = -EFAULT;
goto exit;
}
- ibmphp_print_test ();
- rc = ibmphp_update_slot_info (slot_cur);
+ ibmphp_print_test();
+ rc = ibmphp_update_slot_info(slot_cur);
exit:
ibmphp_unlock_operations();
return rc;
error_nopower:
- attn_off (slot_cur); /* need to turn off if was blinking b4 */
- attn_on (slot_cur);
+ attn_off(slot_cur); /* need to turn off if was blinking b4 */
+ attn_on(slot_cur);
error_cont:
- rcpr = slot_update (&slot_cur);
+ rcpr = slot_update(&slot_cur);
if (rcpr) {
rc = rcpr;
goto exit;
}
- ibmphp_update_slot_info (slot_cur);
+ ibmphp_update_slot_info(slot_cur);
goto exit;
error_power:
- attn_off (slot_cur); /* need to turn off if was blinking b4 */
- attn_on (slot_cur);
- rcpr = power_off (slot_cur);
+ attn_off(slot_cur); /* need to turn off if was blinking b4 */
+ attn_on(slot_cur);
+ rcpr = power_off(slot_cur);
if (rcpr) {
rc = rcpr;
goto exit;
@@ -1148,7 +1217,7 @@ error_power:
* OUTPUT: SUCCESS 0 ; FAILURE: UNCONFIGURE , VALIDATE *
DISABLE POWER , *
**************************************************************/
-static int ibmphp_disable_slot (struct hotplug_slot *hotplug_slot)
+static int ibmphp_disable_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
int rc;
@@ -1159,12 +1228,12 @@ static int ibmphp_disable_slot (struct hotplug_slot *hotplug_slot)
return rc;
}
-int ibmphp_do_disable_slot (struct slot *slot_cur)
+int ibmphp_do_disable_slot(struct slot *slot_cur)
{
int rc;
u8 flag;
- debug ("DISABLING SLOT...\n");
+ debug("DISABLING SLOT...\n");
if ((slot_cur == NULL) || (slot_cur->ctrl == NULL)) {
return -ENODEV;
@@ -1174,21 +1243,22 @@ int ibmphp_do_disable_slot (struct slot *slot_cur)
slot_cur->flag = TRUE;
if (flag == TRUE) {
- rc = validate (slot_cur, DISABLE); /* checking if powered off already & valid slot # */
+ rc = validate(slot_cur, DISABLE);
+ /* checking if powered off already & valid slot # */
if (rc)
goto error;
}
- attn_LED_blink (slot_cur);
+ attn_LED_blink(slot_cur);
if (slot_cur->func == NULL) {
/* We need this for fncs's that were there on bootup */
- slot_cur->func = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+ slot_cur->func = kmalloc(sizeof(struct pci_func), GFP_KERNEL);
if (!slot_cur->func) {
- err ("out of system memory\n");
+ err("out of system memory\n");
rc = -ENOMEM;
goto error;
}
- memset (slot_cur->func, 0, sizeof (struct pci_func));
+ memset(slot_cur->func, 0, sizeof(struct pci_func));
slot_cur->func->busno = slot_cur->bus;
slot_cur->func->device = slot_cur->device;
}
@@ -1202,42 +1272,42 @@ int ibmphp_do_disable_slot (struct slot *slot_cur)
lists at least */
if (!flag) {
- attn_off (slot_cur);
+ attn_off(slot_cur);
return 0;
}
- rc = ibmphp_unconfigure_card (&slot_cur, 0);
+ rc = ibmphp_unconfigure_card(&slot_cur, 0);
slot_cur->func = NULL;
- debug ("in disable_slot. after unconfigure_card\n");
+ debug("in disable_slot. after unconfigure_card\n");
if (rc) {
- err ("could not unconfigure card.\n");
+ err("could not unconfigure card.\n");
goto error;
}
- rc = ibmphp_hpc_writeslot (slot_cur, HPC_SLOT_OFF);
+ rc = ibmphp_hpc_writeslot(slot_cur, HPC_SLOT_OFF);
if (rc)
goto error;
- attn_off (slot_cur);
- rc = slot_update (&slot_cur);
+ attn_off(slot_cur);
+ rc = slot_update(&slot_cur);
if (rc)
goto exit;
- rc = ibmphp_update_slot_info (slot_cur);
- ibmphp_print_test ();
+ rc = ibmphp_update_slot_info(slot_cur);
+ ibmphp_print_test();
exit:
return rc;
error:
/* Need to turn off if was blinking b4 */
- attn_off (slot_cur);
- attn_on (slot_cur);
- if (slot_update (&slot_cur)) {
+ attn_off(slot_cur);
+ attn_on(slot_cur);
+ if (slot_update(&slot_cur)) {
rc = -EFAULT;
goto exit;
}
if (flag)
- ibmphp_update_slot_info (slot_cur);
+ ibmphp_update_slot_info(slot_cur);
goto exit;
}
@@ -1258,22 +1328,22 @@ struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {
*/
};
-static void ibmphp_unload (void)
+static void ibmphp_unload(void)
{
- free_slots ();
- debug ("after slots\n");
- ibmphp_free_resources ();
- debug ("after resources\n");
- ibmphp_free_bus_info_queue ();
- debug ("after bus info\n");
- ibmphp_free_ebda_hpc_queue ();
- debug ("after ebda hpc\n");
- ibmphp_free_ebda_pci_rsrc_queue ();
- debug ("after ebda pci rsrc\n");
- kfree (ibmphp_pci_bus);
+ free_slots();
+ debug("after slots\n");
+ ibmphp_free_resources();
+ debug("after resources\n");
+ ibmphp_free_bus_info_queue();
+ debug("after bus info\n");
+ ibmphp_free_ebda_hpc_queue();
+ debug("after ebda hpc\n");
+ ibmphp_free_ebda_pci_rsrc_queue();
+ debug("after ebda pci rsrc\n");
+ kfree(ibmphp_pci_bus);
}
-static int __init ibmphp_init (void)
+static int __init ibmphp_init(void)
{
struct pci_bus *bus;
int i = 0;
@@ -1281,50 +1351,50 @@ static int __init ibmphp_init (void)
init_flag = 1;
- info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- ibmphp_pci_bus = kmalloc (sizeof (*ibmphp_pci_bus), GFP_KERNEL);
+ ibmphp_pci_bus = kmalloc(sizeof(*ibmphp_pci_bus), GFP_KERNEL);
if (!ibmphp_pci_bus) {
- err ("out of memory\n");
+ err("out of memory\n");
rc = -ENOMEM;
goto exit;
}
bus = pci_find_bus(0, 0);
if (!bus) {
- err ("Can't find the root pci bus, can not continue\n");
+ err("Can't find the root pci bus, can not continue\n");
rc = -ENODEV;
goto error;
}
- memcpy (ibmphp_pci_bus, bus, sizeof (*ibmphp_pci_bus));
+ memcpy(ibmphp_pci_bus, bus, sizeof(*ibmphp_pci_bus));
ibmphp_debug = debug;
- ibmphp_hpc_initvars ();
+ ibmphp_hpc_initvars();
for (i = 0; i < 16; i++)
irqs[i] = 0;
- if ((rc = ibmphp_access_ebda ()))
+ if ((rc = ibmphp_access_ebda()))
goto error;
- debug ("after ibmphp_access_ebda ()\n");
+ debug("after ibmphp_access_ebda()\n");
- if ((rc = ibmphp_rsrc_init ()))
+ if ((rc = ibmphp_rsrc_init()))
goto error;
- debug ("AFTER Resource & EBDA INITIALIZATIONS\n");
+ debug("AFTER Resource & EBDA INITIALIZATIONS\n");
- max_slots = get_max_slots ();
+ max_slots = get_max_slots();
- if ((rc = ibmphp_register_pci ()))
+ if ((rc = ibmphp_register_pci()))
goto error;
- if (init_ops ()) {
+ if (init_ops()) {
rc = -ENODEV;
goto error;
}
- ibmphp_print_test ();
- if ((rc = ibmphp_hpc_start_poll_thread ())) {
+ ibmphp_print_test();
+ if ((rc = ibmphp_hpc_start_poll_thread())) {
goto error;
}
@@ -1336,17 +1406,17 @@ exit:
return rc;
error:
- ibmphp_unload ();
+ ibmphp_unload();
goto exit;
}
-static void __exit ibmphp_exit (void)
+static void __exit ibmphp_exit(void)
{
- ibmphp_hpc_stop_poll_thread ();
- debug ("after polling\n");
- ibmphp_unload ();
- debug ("done\n");
+ ibmphp_hpc_stop_poll_thread();
+ debug("after polling\n");
+ ibmphp_unload();
+ debug("done\n");
}
-module_init (ibmphp_init);
-module_exit (ibmphp_exit);
+module_init(ibmphp_init);
+module_exit(ibmphp_exit);
diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
index 97bb68f8c4e893..ee0a3845ccd7a5 100644
--- a/drivers/pci/hotplug/ibmphp_pci.c
+++ b/drivers/pci/hotplug/ibmphp_pci.c
@@ -164,7 +164,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
cleanup_count = 6;
goto error;
}
- newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+ newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
if (!newfunc) {
err ("out of system memory\n");
return -ENOMEM;
@@ -203,7 +203,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
flag = FALSE;
for (i = 0; i < 32; i++) {
if (func->devices[i]) {
- newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+ newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
if (!newfunc) {
err ("out of system memory\n");
return -ENOMEM;
@@ -232,7 +232,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
}
}
- newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+ newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
if (!newfunc) {
err ("out of system memory\n");
return -ENOMEM;
@@ -279,7 +279,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)
for (i = 0; i < 32; i++) {
if (func->devices[i]) {
debug ("inside for loop, device is %x\n", i);
- newfunc = (struct pci_func *) kmalloc (sizeof (struct pci_func), GFP_KERNEL);
+ newfunc = kmalloc(sizeof(*newfunc), GFP_KERNEL);
if (!newfunc) {
err (" out of system memory\n");
return -ENOMEM;
@@ -414,7 +414,7 @@ static int configure_device (struct pci_func *func)
memset (io[count], 0, sizeof (struct resource_node));
io[count]->type = IO;
io[count]->busno = func->busno;
- io[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+ io[count]->devfunc = PCI_DEVFN(func->device, func->function);
io[count]->len = len[count];
if (ibmphp_check_resource(io[count], 0) == 0) {
ibmphp_add_resource (io[count]);
@@ -452,14 +452,15 @@ static int configure_device (struct pci_func *func)
memset (pfmem[count], 0, sizeof (struct resource_node));
pfmem[count]->type = PFMEM;
pfmem[count]->busno = func->busno;
- pfmem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+ pfmem[count]->devfunc = PCI_DEVFN(func->device,
+ func->function);
pfmem[count]->len = len[count];
pfmem[count]->fromMem = FALSE;
if (ibmphp_check_resource (pfmem[count], 0) == 0) {
ibmphp_add_resource (pfmem[count]);
func->pfmem[count] = pfmem[count];
} else {
- mem_tmp = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+ mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL);
if (!mem_tmp) {
err ("out of system memory\n");
kfree (pfmem[count]);
@@ -519,7 +520,8 @@ static int configure_device (struct pci_func *func)
memset (mem[count], 0, sizeof (struct resource_node));
mem[count]->type = MEM;
mem[count]->busno = func->busno;
- mem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+ mem[count]->devfunc = PCI_DEVFN(func->device,
+ func->function);
mem[count]->len = len[count];
if (ibmphp_check_resource (mem[count], 0) == 0) {
ibmphp_add_resource (mem[count]);
@@ -685,7 +687,8 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
memset (bus_io[count], 0, sizeof (struct resource_node));
bus_io[count]->type = IO;
bus_io[count]->busno = func->busno;
- bus_io[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+ bus_io[count]->devfunc = PCI_DEVFN(func->device,
+ func->function);
bus_io[count]->len = len[count];
if (ibmphp_check_resource (bus_io[count], 0) == 0) {
ibmphp_add_resource (bus_io[count]);
@@ -717,14 +720,15 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
memset (bus_pfmem[count], 0, sizeof (struct resource_node));
bus_pfmem[count]->type = PFMEM;
bus_pfmem[count]->busno = func->busno;
- bus_pfmem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+ bus_pfmem[count]->devfunc = PCI_DEVFN(func->device,
+ func->function);
bus_pfmem[count]->len = len[count];
bus_pfmem[count]->fromMem = FALSE;
if (ibmphp_check_resource (bus_pfmem[count], 0) == 0) {
ibmphp_add_resource (bus_pfmem[count]);
func->pfmem[count] = bus_pfmem[count];
} else {
- mem_tmp = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+ mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL);
if (!mem_tmp) {
err ("out of system memory\n");
retval = -ENOMEM;
@@ -775,7 +779,8 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
memset (bus_mem[count], 0, sizeof (struct resource_node));
bus_mem[count]->type = MEM;
bus_mem[count]->busno = func->busno;
- bus_mem[count]->devfunc = ((func->device << 3) | (func->function & 0x7));
+ bus_mem[count]->devfunc = PCI_DEVFN(func->device,
+ func->function);
bus_mem[count]->len = len[count];
if (ibmphp_check_resource (bus_mem[count], 0) == 0) {
ibmphp_add_resource (bus_mem[count]);
@@ -836,7 +841,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
flag_io = TRUE;
} else {
debug ("it wants %x IO behind the bridge\n", amount_needed->io);
- io = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+ io = kmalloc(sizeof(*io), GFP_KERNEL);
if (!io) {
err ("out of system memory\n");
@@ -846,7 +851,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
memset (io, 0, sizeof (struct resource_node));
io->type = IO;
io->busno = func->busno;
- io->devfunc = ((func->device << 3) | (func->function & 0x7));
+ io->devfunc = PCI_DEVFN(func->device, func->function);
io->len = amount_needed->io;
if (ibmphp_check_resource (io, 1) == 0) {
debug ("were we able to add io\n");
@@ -860,7 +865,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
flag_mem = TRUE;
} else {
debug ("it wants %x memory behind the bridge\n", amount_needed->mem);
- mem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+ mem = kmalloc(sizeof(*mem), GFP_KERNEL);
if (!mem) {
err ("out of system memory\n");
retval = -ENOMEM;
@@ -869,7 +874,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
memset (mem, 0, sizeof (struct resource_node));
mem->type = MEM;
mem->busno = func->busno;
- mem->devfunc = ((func->device << 3) | (func->function & 0x7));
+ mem->devfunc = PCI_DEVFN(func->device, func->function);
mem->len = amount_needed->mem;
if (ibmphp_check_resource (mem, 1) == 0) {
ibmphp_add_resource (mem);
@@ -883,7 +888,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
flag_pfmem = TRUE;
} else {
debug ("it wants %x pfmemory behind the bridge\n", amount_needed->pfmem);
- pfmem = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+ pfmem = kmalloc(sizeof(*pfmem), GFP_KERNEL);
if (!pfmem) {
err ("out of system memory\n");
retval = -ENOMEM;
@@ -892,14 +897,14 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
memset (pfmem, 0, sizeof (struct resource_node));
pfmem->type = PFMEM;
pfmem->busno = func->busno;
- pfmem->devfunc = ((func->device << 3) | (func->function & 0x7));
+ pfmem->devfunc = PCI_DEVFN(func->device, func->function);
pfmem->len = amount_needed->pfmem;
pfmem->fromMem = FALSE;
if (ibmphp_check_resource (pfmem, 1) == 0) {
ibmphp_add_resource (pfmem);
flag_pfmem = TRUE;
} else {
- mem_tmp = kmalloc (sizeof (struct resource_node), GFP_KERNEL);
+ mem_tmp = kmalloc(sizeof(*mem_tmp), GFP_KERNEL);
if (!mem_tmp) {
err ("out of system memory\n");
retval = -ENOMEM;
@@ -931,7 +936,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
*/
bus = ibmphp_find_res_bus (sec_number);
if (!bus) {
- bus = kmalloc (sizeof (struct bus_node), GFP_KERNEL);
+ bus = kmalloc(sizeof(*bus), GFP_KERNEL);
if (!bus) {
err ("out of system memory\n");
retval = -ENOMEM;
@@ -1057,8 +1062,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)
}
error:
- if (amount_needed)
- kfree (amount_needed);
+ kfree(amount_needed);
if (pfmem)
ibmphp_remove_resource (pfmem);
if (io)
@@ -1107,7 +1111,7 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)
};
struct res_needed *amount;
- amount = kmalloc (sizeof (struct res_needed), GFP_KERNEL);
+ amount = kmalloc(sizeof(*amount), GFP_KERNEL);
if (amount == NULL)
return NULL;
memset (amount, 0, sizeof (struct res_needed));
@@ -1680,7 +1684,7 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r
list_add (&bus->bus_list, &cur_bus->bus_list);
}
if (io) {
- io_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+ io_range = kmalloc(sizeof(*io_range), GFP_KERNEL);
if (!io_range) {
err ("out of system memory\n");
return -ENOMEM;
@@ -1693,7 +1697,7 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r
bus->rangeIO = io_range;
}
if (mem) {
- mem_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+ mem_range = kmalloc(sizeof(*mem_range), GFP_KERNEL);
if (!mem_range) {
err ("out of system memory\n");
return -ENOMEM;
@@ -1706,7 +1710,7 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r
bus->rangeMem = mem_range;
}
if (pfmem) {
- pfmem_range = kmalloc (sizeof (struct range_node), GFP_KERNEL);
+ pfmem_range = kmalloc(sizeof(*pfmem_range), GFP_KERNEL);
if (!pfmem_range) {
err ("out of system memory\n");
return -ENOMEM;
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index cb8569e0bbfa48..7bdfe4c6bf7043 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -33,7 +33,6 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index 89f192286fc837..67b6a3370ceba6 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -36,7 +36,7 @@
#include <asm/io.h>
#include "pci_hotplug.h"
-#if !defined(CONFIG_HOTPLUG_PCI_SHPC_MODULE)
+#if !defined(MODULE)
#define MY_NAME "shpchp"
#else
#define MY_NAME THIS_MODULE->name
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index f11217230917db..f0c53f850aedb1 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -33,7 +33,6 @@
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
-#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <linux/pci.h>
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 7fcf935c51b516..0765bc508d0931 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -20,6 +20,7 @@
#include <linux/pci.h>
#include <linux/stat.h>
#include <linux/topology.h>
+#include <linux/mm.h>
#include "pci.h"
@@ -178,6 +179,164 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
return count;
}
+#ifdef HAVE_PCI_LEGACY
+/**
+ * pci_read_legacy_io - read byte(s) from legacy I/O port space
+ * @kobj: kobject corresponding to file to read from
+ * @buf: buffer to store results
+ * @off: offset into legacy I/O port space
+ * @count: number of bytes to read
+ *
+ * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific
+ * callback routine (pci_legacy_read).
+ */
+ssize_t
+pci_read_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ struct pci_bus *bus = to_pci_bus(container_of(kobj,
+ struct class_device,
+ kobj));
+
+ /* Only support 1, 2 or 4 byte accesses */
+ if (count != 1 && count != 2 && count != 4)
+ return -EINVAL;
+
+ return pci_legacy_read(bus, off, (u32 *)buf, count);
+}
+
+/**
+ * pci_write_legacy_io - write byte(s) to legacy I/O port space
+ * @kobj: kobject corresponding to file to read from
+ * @buf: buffer containing value to be written
+ * @off: offset into legacy I/O port space
+ * @count: number of bytes to write
+ *
+ * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific
+ * callback routine (pci_legacy_write).
+ */
+ssize_t
+pci_write_legacy_io(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ struct pci_bus *bus = to_pci_bus(container_of(kobj,
+ struct class_device,
+ kobj));
+ /* Only support 1, 2 or 4 byte accesses */
+ if (count != 1 && count != 2 && count != 4)
+ return -EINVAL;
+
+ return pci_legacy_write(bus, off, *(u32 *)buf, count);
+}
+
+/**
+ * pci_mmap_legacy_mem - map legacy PCI memory into user memory space
+ * @kobj: kobject corresponding to device to be mapped
+ * @attr: struct bin_attribute for this file
+ * @vma: struct vm_area_struct passed to mmap
+ *
+ * Uses an arch specific callback, pci_mmap_legacy_page_range, to mmap
+ * legacy memory space (first meg of bus space) into application virtual
+ * memory space.
+ */
+int
+pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
+ struct vm_area_struct *vma)
+{
+ struct pci_bus *bus = to_pci_bus(container_of(kobj,
+ struct class_device,
+ kobj));
+
+ return pci_mmap_legacy_page_range(bus, vma);
+}
+#endif /* HAVE_PCI_LEGACY */
+
+#ifdef HAVE_PCI_MMAP
+/**
+ * pci_mmap_resource - map a PCI resource into user memory space
+ * @kobj: kobject for mapping
+ * @attr: struct bin_attribute for the file being mapped
+ * @vma: struct vm_area_struct passed into the mmap
+ *
+ * Use the regular PCI mapping routines to map a PCI resource into userspace.
+ * FIXME: write combining? maybe automatic for prefetchable regions?
+ */
+static int
+pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
+ struct vm_area_struct *vma)
+{
+ struct pci_dev *pdev = to_pci_dev(container_of(kobj,
+ struct device, kobj));
+ struct resource *res = (struct resource *)attr->private;
+ enum pci_mmap_state mmap_type;
+
+ vma->vm_pgoff += res->start >> PAGE_SHIFT;
+ mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
+
+ return pci_mmap_page_range(pdev, vma, mmap_type, 0);
+}
+
+/**
+ * pci_create_resource_files - create resource files in sysfs for @dev
+ * @dev: dev in question
+ *
+ * Walk the resources in @dev creating files for each resource available.
+ */
+static void
+pci_create_resource_files(struct pci_dev *pdev)
+{
+ int i;
+
+ /* Expose the PCI resources from this device as files */
+ for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+ struct bin_attribute *res_attr;
+
+ /* skip empty resources */
+ if (!pci_resource_len(pdev, i))
+ continue;
+
+ res_attr = kmalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
+ if (res_attr) {
+ memset(res_attr, 0, sizeof(*res_attr) + 10);
+ pdev->res_attr[i] = res_attr;
+ /* Allocated above after the res_attr struct */
+ res_attr->attr.name = (char *)(res_attr + 1);
+ sprintf(res_attr->attr.name, "resource%d", i);
+ res_attr->size = pci_resource_len(pdev, i);
+ res_attr->attr.mode = S_IRUSR | S_IWUSR;
+ res_attr->attr.owner = THIS_MODULE;
+ res_attr->mmap = pci_mmap_resource;
+ res_attr->private = &pdev->resource[i];
+ sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
+ }
+ }
+}
+
+/**
+ * pci_remove_resource_files - cleanup resource files
+ * @dev: dev to cleanup
+ *
+ * If we created resource files for @dev, remove them from sysfs and
+ * free their resources.
+ */
+static void
+pci_remove_resource_files(struct pci_dev *pdev)
+{
+ int i;
+
+ for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+ struct bin_attribute *res_attr;
+
+ res_attr = pdev->res_attr[i];
+ if (res_attr) {
+ sysfs_remove_bin_file(&pdev->dev.kobj, res_attr);
+ kfree(res_attr);
+ }
+ }
+}
+#else /* !HAVE_PCI_MMAP */
+static inline void pci_create_resource_files(struct pci_dev *dev) { return; }
+static inline void pci_remove_resource_files(struct pci_dev *dev) { return; }
+#endif /* HAVE_PCI_MMAP */
+
/**
* pci_write_rom - used to enable access to the PCI ROM display
* @kobj: kernel object handle
@@ -269,6 +428,8 @@ int pci_create_sysfs_dev_files (struct pci_dev *pdev)
else
sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+ pci_create_resource_files(pdev);
+
/* If the device has a ROM, try to expose it in sysfs. */
if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
struct bin_attribute *rom_attr;
@@ -304,6 +465,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
else
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
+ pci_remove_resource_files(pdev);
+
if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
if (pdev->rom_attr) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5e7a94a8c9caa3..0f6ff9fe7760c5 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -229,7 +229,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
/**
* pci_set_power_state - Set the power state of a PCI device
* @dev: PCI device to be suspended
- * @state: Power state we're entering
+ * @state: PCI power state (D0, D1, D2, D3hot, D3cold) we're entering
*
* Transition a device to a new power state, using the Power Management
* Capabilities in the device's config space.
@@ -242,19 +242,20 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
*/
int
-pci_set_power_state(struct pci_dev *dev, int state)
+pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
int pm;
- u16 pmcsr;
+ u16 pmcsr, pmc;
/* bound the state we're entering */
- if (state > 3) state = 3;
+ if (state > PCI_D3hot)
+ state = PCI_D3hot;
/* Validate current state:
* Can enter D0 from any state, but if we can only go deeper
* to sleep if we're already in a low power state
*/
- if (state > 0 && dev->current_state > state)
+ if (state != PCI_D0 && dev->current_state > state)
return -EINVAL;
else if (dev->current_state == state)
return 0; /* we're already there */
@@ -263,21 +264,30 @@ pci_set_power_state(struct pci_dev *dev, int state)
pm = pci_find_capability(dev, PCI_CAP_ID_PM);
/* abort if the device doesn't support PM capabilities */
- if (!pm) return -EIO;
+ if (!pm)
+ return -EIO;
+
+ pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);
+ if ((pmc & PCI_PM_CAP_VER_MASK) != 2) {
+ printk(KERN_WARNING
+ "PCI: %s has unsupported PM cap regs version (%u)\n",
+ dev->slot_name, pmc & PCI_PM_CAP_VER_MASK);
+ return -EIO;
+ }
/* check if this device supports the desired state */
- if (state == 1 || state == 2) {
- u16 pmc;
- pci_read_config_word(dev,pm + PCI_PM_PMC,&pmc);
- if (state == 1 && !(pmc & PCI_PM_CAP_D1)) return -EIO;
- else if (state == 2 && !(pmc & PCI_PM_CAP_D2)) return -EIO;
+ if (state == PCI_D1 || state == PCI_D2) {
+ if (state == PCI_D1 && !(pmc & PCI_PM_CAP_D1))
+ return -EIO;
+ else if (state == PCI_D2 && !(pmc & PCI_PM_CAP_D2))
+ return -EIO;
}
/* If we're in D3, force entire word to 0.
* This doesn't affect PME_Status, disables PME_En, and
* sets PowerState to 0.
*/
- if (dev->current_state >= 3)
+ if (dev->current_state >= PCI_D3hot)
pmcsr = 0;
else {
pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
@@ -290,9 +300,9 @@ pci_set_power_state(struct pci_dev *dev, int state)
/* Mandatory power management transition delays */
/* see PCI PM 1.1 5.6.1 table 18 */
- if(state == 3 || dev->current_state == 3)
+ if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
msleep(10);
- else if(state == 2 || dev->current_state == 2)
+ else if (state == PCI_D2 || dev->current_state == PCI_D2)
udelay(200);
dev->current_state = state;
@@ -300,6 +310,31 @@ pci_set_power_state(struct pci_dev *dev, int state)
}
/**
+ * pci_choose_state - Choose the power state of a PCI device
+ * @dev: PCI device to be suspended
+ * @state: target sleep state for the whole system
+ *
+ * Returns PCI power state suitable for given device and given system
+ * message.
+ */
+
+pci_power_t pci_choose_state(struct pci_dev *dev, u32 state)
+{
+ if (!pci_find_capability(dev, PCI_CAP_ID_PM))
+ return PCI_D0;
+
+ switch (state) {
+ case 0: return PCI_D0;
+ case 2: return PCI_D2;
+ case 3: return PCI_D3hot;
+ default: BUG();
+ }
+ return PCI_D0;
+}
+
+EXPORT_SYMBOL(pci_choose_state);
+
+/**
* pci_save_state - save the PCI configuration space of a device before suspending
* @dev: - PCI device that we're dealing with
* @buffer: - buffer to hold config space context
@@ -348,7 +383,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
{
int err;
- pci_set_power_state(dev, 0);
+ pci_set_power_state(dev, PCI_D0);
if ((err = pcibios_enable_device(dev, bars)) < 0)
return err;
return 0;
@@ -422,7 +457,7 @@ pci_disable_device(struct pci_dev *dev)
* 0 if operation is successful.
*
*/
-int pci_enable_wake(struct pci_dev *dev, u32 state, int enable)
+int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
{
int pm;
u16 value;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 1c70dd5a19e63d..ae2be18ac27e11 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -2,6 +2,7 @@
* probe.c - PCI detection and setup code
*/
+#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
@@ -27,27 +28,50 @@ EXPORT_SYMBOL(pci_root_buses);
LIST_HEAD(pci_devices);
-/*
- * PCI Bus Class
+#ifdef HAVE_PCI_LEGACY
+/**
+ * pci_create_legacy_files - create legacy I/O port and memory files
+ * @b: bus to create files under
+ *
+ * Some platforms allow access to legacy I/O port and ISA memory space on
+ * a per-bus basis. This routine creates the files and ties them into
+ * their associated read, write and mmap files from pci-sysfs.c
*/
-static void release_pcibus_dev(struct class_device *class_dev)
+static void pci_create_legacy_files(struct pci_bus *b)
{
- struct pci_bus *pci_bus = to_pci_bus(class_dev);
- if (pci_bus->bridge)
- put_device(pci_bus->bridge);
- kfree(pci_bus);
+ b->legacy_io = kmalloc(sizeof(struct bin_attribute) * 2,
+ GFP_ATOMIC);
+ if (b->legacy_io) {
+ memset(b->legacy_io, 0, sizeof(struct bin_attribute) * 2);
+ b->legacy_io->attr.name = "legacy_io";
+ b->legacy_io->size = 0xffff;
+ b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
+ b->legacy_io->attr.owner = THIS_MODULE;
+ b->legacy_io->read = pci_read_legacy_io;
+ b->legacy_io->write = pci_write_legacy_io;
+ class_device_create_bin_file(&b->class_dev, b->legacy_io);
+
+ /* Allocated above after the legacy_io struct */
+ b->legacy_mem = b->legacy_io + 1;
+ b->legacy_mem->attr.name = "legacy_mem";
+ b->legacy_mem->size = 1024*1024;
+ b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
+ b->legacy_mem->attr.owner = THIS_MODULE;
+ b->legacy_mem->mmap = pci_mmap_legacy_mem;
+ class_device_create_bin_file(&b->class_dev, b->legacy_mem);
+ }
}
-static struct class pcibus_class = {
- .name = "pci_bus",
- .release = &release_pcibus_dev,
-};
-
-static int __init pcibus_class_init(void)
+static void pci_remove_legacy_files(struct pci_bus *b)
{
- return class_register(&pcibus_class);
+ class_device_remove_bin_file(&b->class_dev, b->legacy_io);
+ class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
+ kfree(b->legacy_io); /* both are allocated here */
}
-postcore_initcall(pcibus_class_init);
+#else /* !HAVE_PCI_LEGACY */
+static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
+static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
+#endif /* HAVE_PCI_LEGACY */
/*
* PCI Bus Class Devices
@@ -65,6 +89,33 @@ static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev, char *bu
static CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
/*
+ * PCI Bus Class
+ */
+static void release_pcibus_dev(struct class_device *class_dev)
+{
+ struct pci_bus *pci_bus = to_pci_bus(class_dev);
+
+ pci_remove_legacy_files(pci_bus);
+ class_device_remove_file(&pci_bus->class_dev,
+ &class_device_attr_cpuaffinity);
+ sysfs_remove_link(&pci_bus->class_dev.kobj, "bridge");
+ if (pci_bus->bridge)
+ put_device(pci_bus->bridge);
+ kfree(pci_bus);
+}
+
+static struct class pcibus_class = {
+ .name = "pci_bus",
+ .release = &release_pcibus_dev,
+};
+
+static int __init pcibus_class_init(void)
+{
+ return class_register(&pcibus_class);
+}
+postcore_initcall(pcibus_class_init);
+
+/*
* Translate the low bits of the PCI base
* to the resource type
*/
@@ -336,6 +387,22 @@ struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_de
return child;
}
+static void pci_enable_crs(struct pci_dev *dev)
+{
+ u16 cap, rpctl;
+ int rpcap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ if (!rpcap)
+ return;
+
+ pci_read_config_word(dev, rpcap + PCI_CAP_FLAGS, &cap);
+ if (((cap & PCI_EXP_FLAGS_TYPE) >> 4) != PCI_EXP_TYPE_ROOT_PORT)
+ return;
+
+ pci_read_config_word(dev, rpcap + PCI_EXP_RTCTL, &rpctl);
+ rpctl |= PCI_EXP_RTCTL_CRSSVE;
+ pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl);
+}
+
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
/*
@@ -366,6 +433,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
+ pci_enable_crs(dev);
+
if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) {
unsigned int cmax, busnr;
/*
@@ -375,6 +444,17 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
if (pass)
return max;
busnr = (buses >> 8) & 0xFF;
+
+ /*
+ * If we already got to this bus through a different bridge,
+ * ignore it. This can happen with the i450NX chipset.
+ */
+ if (pci_find_bus(pci_domain_nr(bus), busnr)) {
+ printk(KERN_INFO "PCI: Bus %04x:%02x already known\n",
+ pci_domain_nr(bus), busnr);
+ return max;
+ }
+
child = pci_alloc_child_bus(bus, dev, busnr);
if (!child)
return max;
@@ -490,6 +570,7 @@ static int pci_setup_device(struct pci_dev * dev)
/* Early fixups, before probing the BARs */
pci_fixup_device(pci_fixup_early, dev);
+ class = dev->class >> 8;
switch (dev->hdr_type) { /* header type */
case PCI_HEADER_TYPE_NORMAL: /* standard header */
@@ -602,9 +683,7 @@ pci_scan_device(struct pci_bus *bus, int devfn)
struct pci_dev *dev;
u32 l;
u8 hdr_type;
-
- if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
- return NULL;
+ int delay = 1;
if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
return NULL;
@@ -614,6 +693,25 @@ pci_scan_device(struct pci_bus *bus, int devfn)
l == 0x0000ffff || l == 0xffff0000)
return NULL;
+ /* Configuration request Retry Status */
+ while (l == 0xffff0001) {
+ msleep(delay);
+ delay *= 2;
+ if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l))
+ return NULL;
+ /* Card hasn't responded in 60 seconds? Must be stuck. */
+ if (delay > 60 * 1000) {
+ printk(KERN_WARNING "Device %04x:%02x:%02x.%d not "
+ "responding\n", pci_domain_nr(bus),
+ bus->number, PCI_SLOT(devfn),
+ PCI_FUNC(devfn));
+ return NULL;
+ }
+ }
+
+ if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type))
+ return NULL;
+
dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
if (!dev)
return NULL;
@@ -785,7 +883,7 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
if (pci_find_bus(pci_domain_nr(b), bus)) {
/* If we already got to this bus through a different bridge, ignore it */
- DBG("PCI: Bus %02x already known\n", bus);
+ DBG("PCI: Bus %04:%02x already known\n", pci_domain_nr(b), bus);
goto err_out;
}
list_add_tail(&b->node, &pci_root_buses);
@@ -808,6 +906,9 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus,
if (error)
goto class_dev_create_file_err;
+ /* Create legacy_io and legacy_mem files for this bus */
+ pci_create_legacy_files(b);
+
error = sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge");
if (error)
goto sys_create_link_err;
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 288645ab8ba628..75740ad01f3e70 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1243,6 +1243,8 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_f
}
}
+extern struct pci_fixup __start_pci_fixups_early[];
+extern struct pci_fixup __end_pci_fixups_early[];
extern struct pci_fixup __start_pci_fixups_header[];
extern struct pci_fixup __end_pci_fixups_header[];
extern struct pci_fixup __start_pci_fixups_final[];
@@ -1256,6 +1258,11 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
struct pci_fixup *start, *end;
switch(pass) {
+ case pci_fixup_early:
+ start = __start_pci_fixups_early;
+ end = __end_pci_fixups_early;
+ break;
+
case pci_fixup_header:
start = __start_pci_fixups_header;
end = __end_pci_fixups_header;
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 830baa225061fe..82d877c4051f73 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -57,8 +57,13 @@ pbus_assign_resources_sorted(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list) {
u16 class = dev->class >> 8;
- if (class == PCI_CLASS_DISPLAY_VGA
- || class == PCI_CLASS_NOT_DEFINED_VGA)
+ /* Don't touch classless devices and host bridges. */
+ if (class == PCI_CLASS_NOT_DEFINED ||
+ class == PCI_CLASS_BRIDGE_HOST)
+ continue;
+
+ if (class == PCI_CLASS_DISPLAY_VGA ||
+ class == PCI_CLASS_NOT_DEFINED_VGA)
bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
pdev_sort_resources(dev, &head);
diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
index 677f1e7af352bd..d02bebfa25d432 100644
--- a/drivers/pci/setup-irq.c
+++ b/drivers/pci/setup-irq.c
@@ -53,7 +53,8 @@ pdev_fixup_irq(struct pci_dev *dev,
irq = 0;
dev->irq = irq;
- DBGC((KERN_ERR "PCI fixup irq: (%s) got %d\n", dev->dev.name, dev->irq));
+ DBGC((KERN_ERR "PCI fixup irq: (%s) got %d\n",
+ dev->dev.kobj.name, dev->irq));
/* Always tell the device, so the driver knows what is
the real IRQ to use; the device does not use it. */
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 63e5190e5025ea..37b643d24825d3 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -6,10 +6,10 @@
#
menu "PCCARD (PCMCIA/CardBus) support"
- depends on HOTPLUG
config PCCARD
tristate "PCCard (PCMCIA/CardBus) support"
+ select HOTPLUG
---help---
Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
computer. These are credit-card size devices such as network cards,
diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c
index d8875ae2c47d57..d40f69c117e3cd 100644
--- a/drivers/serial/mcfserial.c
+++ b/drivers/serial/mcfserial.c
@@ -58,11 +58,16 @@ struct timer_list mcfrs_timer_struct;
* keep going. Perhaps one day the cflag settings for the
* console can be used instead.
*/
-#if defined(CONFIG_ARNEWSH) || defined(CONFIG_MOTOROLA) || defined(CONFIG_senTec)
+#if defined(CONFIG_ARNEWSH) || defined(CONFIG_MOTOROLA) || defined(CONFIG_senTec) || defined(CONFIG_SNEHA)
#define CONSOLE_BAUD_RATE 19200
#define DEFAULT_CBAUD B19200
#endif
+#if defined(CONFIG_HW_FEITH)
+ #define CONSOLE_BAUD_RATE 38400
+ #define DEFAULT_CBAUD B38400
+#endif
+
#ifndef CONSOLE_BAUD_RATE
#define CONSOLE_BAUD_RATE 9600
#define DEFAULT_CBAUD B9600
@@ -86,8 +91,8 @@ static struct tty_driver *mcfrs_serial_driver;
#undef SERIAL_DEBUG_OPEN
#undef SERIAL_DEBUG_FLOW
-#ifdef CONFIG_M5282
-#define IRQBASE 77
+#if defined(CONFIG_M527x) || defined(CONFIG_M528x)
+#define IRQBASE (MCFINT_VECBASE+MCFINT_UART0)
#else
#define IRQBASE 73
#endif
@@ -337,20 +342,24 @@ static inline void receive_chars(struct mcf_serial *info)
#endif
tty->flip.count++;
- if (status & MCFUART_USR_RXERR)
+ if (status & MCFUART_USR_RXERR) {
uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR;
- if (status & MCFUART_USR_RXBREAK) {
- info->stats.rxbreak++;
- *tty->flip.flag_buf_ptr++ = TTY_BREAK;
- } else if (status & MCFUART_USR_RXPARITY) {
- info->stats.rxparity++;
- *tty->flip.flag_buf_ptr++ = TTY_PARITY;
- } else if (status & MCFUART_USR_RXOVERRUN) {
- info->stats.rxoverrun++;
- *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
- } else if (status & MCFUART_USR_RXFRAMING) {
- info->stats.rxframing++;
- *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ if (status & MCFUART_USR_RXBREAK) {
+ info->stats.rxbreak++;
+ *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+ } else if (status & MCFUART_USR_RXPARITY) {
+ info->stats.rxparity++;
+ *tty->flip.flag_buf_ptr++ = TTY_PARITY;
+ } else if (status & MCFUART_USR_RXOVERRUN) {
+ info->stats.rxoverrun++;
+ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+ } else if (status & MCFUART_USR_RXFRAMING) {
+ info->stats.rxframing++;
+ *tty->flip.flag_buf_ptr++ = TTY_FRAME;
+ } else {
+ /* This should never happen... */
+ *tty->flip.flag_buf_ptr++ = 0;
+ }
} else {
*tty->flip.flag_buf_ptr++ = 0;
}
@@ -724,13 +733,25 @@ static void mcfrs_flush_chars(struct tty_struct *tty)
if (serial_paranoia_check(info, tty->name, "mcfrs_flush_chars"))
return;
+ uartp = (volatile unsigned char *) info->addr;
+
+ /*
+ * re-enable receiver interrupt
+ */
+ local_irq_save(flags);
+ if ((!(info->imr & MCFUART_UIR_RXREADY)) &&
+ (info->flags & ASYNC_INITIALIZED) ) {
+ info->imr |= MCFUART_UIR_RXREADY;
+ uartp[MCFUART_UIMR] = info->imr;
+ }
+ local_irq_restore(flags);
+
if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
!info->xmit_buf)
return;
/* Enable transmitter */
local_irq_save(flags);
- uartp = info->addr;
info->imr |= MCFUART_UIR_TXREADY;
uartp[MCFUART_UIMR] = info->imr;
local_irq_restore(flags);
@@ -984,7 +1005,7 @@ static void send_break( struct mcf_serial * info, int duration)
local_irq_save(flags);
uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTART;
- schedule_timeout(jiffies + duration);
+ schedule_timeout(duration);
uartp[MCFUART_UCR] = MCFUART_UCR_CMDBREAKSTOP;
local_irq_restore(flags);
}
@@ -1506,7 +1527,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
*portp = (*portp & ~0x000000ff) | 0x00000055;
portp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_PDCNT);
*portp = (*portp & ~0x000003fc) | 0x000002a8;
-#elif defined(CONFIG_M5282)
+#elif defined(CONFIG_M527x) || defined(CONFIG_M528x)
volatile unsigned char *icrp, *uartp;
volatile unsigned long *imrp;
@@ -1518,7 +1539,7 @@ static void mcfrs_irqinit(struct mcf_serial *info)
imrp = (volatile unsigned long *) (MCF_MBAR + MCFICM_INTC0 +
MCFINTC_IMRL);
- *imrp &= ~((1 << (info->irq - 64)) | 1);
+ *imrp &= ~((1 << (info->irq - MCFINT_VECBASE)) | 1);
#else
volatile unsigned char *icrp, *uartp;
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 9e63dfde09fd3a..aac5a6fe608508 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_USB) += core/
obj-$(CONFIG_USB_EHCI_HCD) += host/
obj-$(CONFIG_USB_OHCI_HCD) += host/
obj-$(CONFIG_USB_UHCI_HCD) += host/
-obj-$(CONFIG_USB_SL811HS) += host/
+obj-$(CONFIG_USB_SL811_HCD) += host/
obj-$(CONFIG_ETRAX_USB_HOST) += host/
obj-$(CONFIG_USB_ACM) += class/
@@ -49,7 +49,6 @@ obj-$(CONFIG_USB_PEGASUS) += net/
obj-$(CONFIG_USB_RTL8150) += net/
obj-$(CONFIG_USB_USBNET) += net/
-obj-$(CONFIG_USB_DC2XX) += image/
obj-$(CONFIG_USB_HPUSBSCSI) += image/
obj-$(CONFIG_USB_MDC800) += image/
obj-$(CONFIG_USB_MICROTEK) += image/
@@ -65,7 +64,6 @@ obj-$(CONFIG_USB_LED) += misc/
obj-$(CONFIG_USB_LEGOTOWER) += misc/
obj-$(CONFIG_USB_RIO500) += misc/
obj-$(CONFIG_USB_TEST) += misc/
-obj-$(CONFIG_USB_TIGL) += misc/
obj-$(CONFIG_USB_USS720) += misc/
obj-$(CONFIG_USB_PHIDGETSERVO) += misc/
diff --git a/drivers/usb/README b/drivers/usb/README
index 1a299646695d78..3c8434128554a4 100644
--- a/drivers/usb/README
+++ b/drivers/usb/README
@@ -1,14 +1,37 @@
+To understand all the Linux-USB framework, you'll use these resources:
+
+ * This source code. This is necessarily an evolving work, and
+ includes kerneldoc that should help you get a current overview.
+ ("make pdfdocs", and then look at "usb.pdf" for host side and
+ "gadget.pdf" for peripheral side.) Also, Documentation/usb has
+ more information.
+
+ * The USB 2.0 specification (from www.usb.org), with supplements
+ such as those for USB OTG and the various device classes.
+ The USB specification has a good overview chapter, and USB
+ peripherals conform to the widely known "Chapter 9".
+
+ * Chip specifications for USB controllers. Examples include
+ host controllers (on PCs, servers, and more); peripheral
+ controllers (in devices with Linux firmware, like printers or
+ cell phones); and hard-wired peripherals like Ethernet adapters.
+
+ * Specifications for other protocols implemented by USB peripheral
+ functions. Some are vendor-specific; others are vendor-neutral
+ but just standardized outside of the www.usb.org team.
+
Here is a list of what each subdirectory here is, and what is contained in
them.
core/ - This is for the core USB host code, including the
- usbfs files.
+ usbfs files and the hub class driver ("khubd").
-host/ - This is for all of the USB host drivers. This
- includes UHCI, OHCI, EHCI, and any others that might
- be created in the future.
+host/ - This is for USB host controller drivers. This
+ includes UHCI, OHCI, EHCI, and others that might
+ be used with more specialized "embedded" systems.
-gadget/ - This is for all of the USB device controller drivers.
+gadget/ - This is for USB peripheral controller drivers and
+ the various gadget drivers which talk to them.
Individual USB driver directories. A new driver should be added to the
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index f17e576d12ec56..060607ec7a500f 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -44,30 +44,10 @@
#include "usb_atm.h"
-/*
-#define DEBUG
-#define VERBOSE_DEBUG
-*/
-
-#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
-# define DEBUG
-#endif
-
-#include <linux/usb.h>
-
#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
# define USE_FW_LOADER
#endif
-#ifdef VERBOSE_DEBUG
-static int udsl_print_packet(const unsigned char *data, int len);
-#define PACKETDEBUG(arg...) udsl_print_packet (arg)
-#define vdbg(arg...) dbg (arg)
-#else
-#define PACKETDEBUG(arg...)
-#define vdbg(arg...)
-#endif
-
#define DRIVER_AUTHOR "Johan Verrept, Duncan Sands <duncan.sands@free.fr>"
#define DRIVER_VERSION "1.8"
#define DRIVER_DESC "Alcatel SpeedTouch USB driver version " DRIVER_VERSION
@@ -594,7 +574,7 @@ static int speedtch_find_firmware(struct speedtch_instance_data
const struct firmware **fw_p)
{
char buf[24];
- const u16 bcdDevice = instance->u.usb_dev->descriptor.bcdDevice;
+ const u16 bcdDevice = le16_to_cpu(instance->u.usb_dev->descriptor.bcdDevice);
const u8 major_revision = bcdDevice >> 8;
const u8 minor_revision = bcdDevice & 0xff;
@@ -737,11 +717,12 @@ static int speedtch_usb_probe(struct usb_interface *intf,
int ret, i;
char buf7[SIZE_7];
- dbg("speedtch_usb_probe: trying device with vendor=0x%x, product=0x%x, ifnum %d", dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum);
+ dbg("speedtch_usb_probe: trying device with vendor=0x%x, product=0x%x, ifnum %d",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct), ifnum);
- if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) ||
- (dev->descriptor.idVendor != SPEEDTOUCH_VENDORID) ||
- (dev->descriptor.idProduct != SPEEDTOUCH_PRODUCTID) || (ifnum != 1))
+ if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) ||
+ (ifnum != 1))
return -ENODEV;
dbg("speedtch_usb_probe: device accepted");
diff --git a/drivers/usb/atm/usb_atm.c b/drivers/usb/atm/usb_atm.c
index d1e271e007a045..a4cd4476d49aaa 100644
--- a/drivers/usb/atm/usb_atm.c
+++ b/drivers/usb/atm/usb_atm.c
@@ -83,23 +83,6 @@
#include "usb_atm.h"
-/*
-#define DEBUG
-#define VERBOSE_DEBUG
-*/
-
-#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
-# define DEBUG
-#endif
-
-#include <linux/usb.h>
-
-#ifdef DEBUG
-#define UDSL_ASSERT(x) BUG_ON(!(x))
-#else
-#define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '" #x "' at line %d", __LINE__); } while(0)
-#endif
-
#ifdef VERBOSE_DEBUG
static int udsl_print_packet(const unsigned char *data, int len);
#define PACKETDEBUG(arg...) udsl_print_packet (arg)
diff --git a/drivers/usb/atm/usb_atm.h b/drivers/usb/atm/usb_atm.h
index 219763cc324216..cf8c532835306d 100644
--- a/drivers/usb/atm/usb_atm.h
+++ b/drivers/usb/atm/usb_atm.h
@@ -21,13 +21,30 @@
*
******************************************************************************/
+#include <linux/config.h>
#include <linux/list.h>
-#include <linux/usb.h>
#include <linux/kref.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <asm/semaphore.h>
+/*
+#define DEBUG
+#define VERBOSE_DEBUG
+*/
+
+#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
+# define DEBUG
+#endif
+
+#include <linux/usb.h>
+
+#ifdef DEBUG
+#define UDSL_ASSERT(x) BUG_ON(!(x))
+#else
+#define UDSL_ASSERT(x) do { if (!(x)) warn("failed assertion '" #x "' at line %d", __LINE__); } while(0)
+#endif
+
#define UDSL_MAX_RCV_URBS 4
#define UDSL_MAX_SND_URBS 4
#define UDSL_MAX_RCV_BUFS 8
diff --git a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
index 675b5ffa30c8ae..e5b6194bbb4b2e 100644
--- a/drivers/usb/class/audio.c
+++ b/drivers/usb/class/audio.c
@@ -2971,7 +2971,8 @@ static void usb_audio_parsestreaming(struct usb_audio_state *s, unsigned char *b
}
format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8);
/* Dallas DS4201 workaround */
- if (dev->descriptor.idVendor == 0x04fa && dev->descriptor.idProduct == 0x4201)
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x4201)
format = (AFMT_S16_LE | AFMT_S8);
fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifout, i);
if (!fmt) {
@@ -3716,7 +3717,7 @@ static struct usb_audio_state *usb_audio_parsecontrol(struct usb_device *dev, un
if (alt->desc.bNumEndpoints > 0) {
/* Check all endpoints; should they all have a bandwidth of 0 ? */
for (k = 0; k < alt->desc.bNumEndpoints; k++) {
- if (alt->endpoint[k].desc.wMaxPacketSize > 0) {
+ if (le16_to_cpu(alt->endpoint[k].desc.wMaxPacketSize) > 0) {
printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u endpoint %d does not have 0 bandwidth at alt[0]\n", dev->devnum, ctrlif, k);
break;
}
@@ -3800,7 +3801,7 @@ static int usb_audio_probe(struct usb_interface *intf,
* find which configuration number is active
*/
buffer = dev->rawdescriptors[dev->actconfig - dev->config];
- buflen = dev->actconfig->desc.wTotalLength;
+ buflen = le16_to_cpu(dev->actconfig->desc.wTotalLength);
s = usb_audio_parsecontrol(dev, buffer, buflen, intf->altsetting->desc.bInterfaceNumber);
if (s) {
usb_set_intfdata (intf, s);
diff --git a/drivers/usb/class/bluetty.c b/drivers/usb/class/bluetty.c
index 6585faa2882d53..6bac65e0ade74e 100644
--- a/drivers/usb/class/bluetty.c
+++ b/drivers/usb/class/bluetty.c
@@ -1086,7 +1086,7 @@ static int usb_bluetooth_probe (struct usb_interface *intf,
err("No free urbs available");
goto probe_error;
}
- bluetooth->bulk_in_buffer_size = buffer_size = endpoint->wMaxPacketSize;
+ bluetooth->bulk_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
bluetooth->bulk_in_endpointAddress = endpoint->bEndpointAddress;
bluetooth->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!bluetooth->bulk_in_buffer) {
@@ -1098,7 +1098,7 @@ static int usb_bluetooth_probe (struct usb_interface *intf,
endpoint = bulk_out_endpoint[0];
bluetooth->bulk_out_endpointAddress = endpoint->bEndpointAddress;
- bluetooth->bulk_out_buffer_size = endpoint->wMaxPacketSize * 2;
+ bluetooth->bulk_out_buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2;
endpoint = interrupt_in_endpoint[0];
bluetooth->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -1106,7 +1106,7 @@ static int usb_bluetooth_probe (struct usb_interface *intf,
err("No free urbs available");
goto probe_error;
}
- bluetooth->interrupt_in_buffer_size = buffer_size = endpoint->wMaxPacketSize;
+ bluetooth->interrupt_in_buffer_size = buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
bluetooth->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
bluetooth->interrupt_in_interval = endpoint->bInterval;
bluetooth->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index cf7fcf8294508b..49caeb73a86610 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -532,7 +532,17 @@ static int acm_probe (struct usb_interface *intf,
u8 call_management_function = 0;
int call_interface_num = -1;
int data_interface_num;
-
+ unsigned long quirks;
+
+ /* handle quirks deadly to normal probing*/
+ quirks = (unsigned long)id->driver_info;
+ if (quirks == NO_UNION_NORMAL) {
+ data_interface = usb_ifnum_to_if(usb_dev, 1);
+ control_interface = usb_ifnum_to_if(usb_dev, 0);
+ goto skip_normal_probe;
+ }
+
+ /* normal probing*/
if (!buffer) {
err("Wierd descriptor references");
return -EINVAL;
@@ -607,6 +617,7 @@ next_desc:
if (data_interface_num != call_interface_num)
dev_dbg(&intf->dev,"Seperate call control interface. That is not fully supported.");
+skip_normal_probe:
if (usb_interface_claimed(data_interface)) { /* valid in this context */
dev_dbg(&intf->dev,"The data interface isn't available\n");
return -EBUSY;
@@ -657,9 +668,9 @@ next_desc:
}
memset(acm, 0, sizeof(struct acm));
- ctrlsize = epctrl->wMaxPacketSize;
- readsize = epread->wMaxPacketSize;
- acm->writesize = epwrite->wMaxPacketSize;
+ ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
+ readsize = le16_to_cpu(epread->wMaxPacketSize);
+ acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize);
acm->control = control_interface;
acm->data = data_interface;
acm->minor = minor;
@@ -805,6 +816,10 @@ static void acm_disconnect(struct usb_interface *intf)
*/
static struct usb_device_id acm_ids[] = {
+ /* quirky and broken devices */
+ { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */
+ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */
+ },
/* control interfaces with various AT-command sets */
{ USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 1) },
{ USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 2) },
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index da945b367a854d..c98a8c2b2a4404 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -125,4 +125,5 @@ struct union_desc {
#define CDC_DATA_INTERFACE_TYPE 0x0a
-
+/* constants describing various quirks and errors */
+#define NO_UNION_NORMAL 1
diff --git a/drivers/usb/class/usb-midi.c b/drivers/usb/class/usb-midi.c
index 1dc952e9bc8188..b5f85504cf5595 100644
--- a/drivers/usb/class/usb-midi.c
+++ b/drivers/usb/class/usb-midi.c
@@ -1306,8 +1306,8 @@ static struct usb_midi_device *parse_descriptor( struct usb_device *d, unsigned
return NULL;
}
u->deviceName = NULL;
- u->idVendor = d->descriptor.idVendor;
- u->idProduct = d->descriptor.idProduct;
+ u->idVendor = le16_to_cpu(d->descriptor.idVendor);
+ u->idProduct = le16_to_cpu(d->descriptor.idProduct);
u->interface = ifnum;
u->altSetting = altSetting;
u->in[0].endpoint = -1;
@@ -1661,11 +1661,11 @@ static int alloc_usb_midi_device( struct usb_device *d, struct usb_midi_state *s
}
/* Failsafe */
if ( !u->deviceName[0] ) {
- if ( d->descriptor.idVendor == USB_VENDOR_ID_ROLAND ) {
+ if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_ROLAND ) {
strcpy(u->deviceName, "Unknown Roland");
- } else if ( d->descriptor.idVendor == USB_VENDOR_ID_STEINBERG ) {
+ } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_STEINBERG ) {
strcpy(u->deviceName, "Unknown Steinberg");
- } else if ( d->descriptor.idVendor == USB_VENDOR_ID_YAMAHA ) {
+ } else if (le16_to_cpu(d->descriptor.idVendor) == USB_VENDOR_ID_YAMAHA ) {
strcpy(u->deviceName, "Unknown Yamaha");
} else {
strcpy(u->deviceName, "Unknown");
@@ -1782,7 +1782,7 @@ static int detect_yamaha_device( struct usb_device *d,
int alts=-1;
int ret;
- if (d->descriptor.idVendor != USB_VENDOR_ID_YAMAHA) {
+ if (le16_to_cpu(d->descriptor.idVendor) != USB_VENDOR_ID_YAMAHA) {
return -EINVAL;
}
@@ -1799,11 +1799,12 @@ static int detect_yamaha_device( struct usb_device *d,
}
printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n",
- d->descriptor.idVendor, d->descriptor.idProduct, ifnum);
+ le16_to_cpu(d->descriptor.idVendor),
+ le16_to_cpu(d->descriptor.idProduct), ifnum);
i = d->actconfig - d->config;
buffer = d->rawdescriptors[i];
- bufSize = d->actconfig->desc.wTotalLength;
+ bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength);
u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1);
if ( u == NULL ) {
@@ -1833,8 +1834,8 @@ static int detect_vendor_specific_device( struct usb_device *d, unsigned int ifn
for ( i=0; i<VENDOR_SPECIFIC_USB_MIDI_DEVICES ; i++ ) {
u=&(usb_midi_devices[i]);
- if ( d->descriptor.idVendor != u->idVendor ||
- d->descriptor.idProduct != u->idProduct ||
+ if ( le16_to_cpu(d->descriptor.idVendor) != u->idVendor ||
+ le16_to_cpu(d->descriptor.idProduct) != u->idProduct ||
ifnum != u->interface )
continue;
@@ -1875,7 +1876,8 @@ static int detect_midi_subclass(struct usb_device *d,
}
printk(KERN_INFO "usb-midi: Found MIDISTREAMING on dev %04x:%04x, iface %d\n",
- d->descriptor.idVendor, d->descriptor.idProduct, ifnum);
+ le16_to_cpu(d->descriptor.idVendor),
+ le16_to_cpu(d->descriptor.idProduct), ifnum);
/* From USB Spec v2.0, Section 9.5.
@@ -1890,7 +1892,7 @@ static int detect_midi_subclass(struct usb_device *d,
i = d->actconfig - d->config;
buffer = d->rawdescriptors[i];
- bufSize = d->actconfig->desc.wTotalLength;
+ bufSize = le16_to_cpu(d->actconfig->desc.wTotalLength);
u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0);
if ( u == NULL ) {
@@ -1915,8 +1917,8 @@ static int detect_by_hand(struct usb_device *d, unsigned int ifnum, struct usb_m
{
struct usb_midi_device u;
- if ( d->descriptor.idVendor != uvendor ||
- d->descriptor.idProduct != uproduct ||
+ if ( le16_to_cpu(d->descriptor.idVendor) != uvendor ||
+ le16_to_cpu(d->descriptor.idProduct) != uproduct ||
ifnum != uinterface ) {
return -EINVAL;
}
diff --git a/drivers/usb/class/usb-midi.h b/drivers/usb/class/usb-midi.h
index 0e6eac11602aef..358cdef8492eaf 100644
--- a/drivers/usb/class/usb-midi.h
+++ b/drivers/usb/class/usb-midi.h
@@ -63,8 +63,8 @@ struct usb_midi_endpoint {
struct usb_midi_device {
char *deviceName;
- int idVendor;
- int idProduct;
+ u16 idVendor;
+ u16 idProduct;
int interface;
int altSetting; /* -1: auto detect */
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index 3bde7c622b12c8..a775f94ff11b3b 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -527,7 +527,7 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
case IOCNR_HP_SET_CHANNEL:
if (_IOC_DIR(cmd) != _IOC_WRITE ||
- usblp->dev->descriptor.idVendor != 0x03F0 ||
+ le16_to_cpu(usblp->dev->descriptor.idVendor) != 0x03F0 ||
usblp->quirks & USBLP_QUIRK_BIDIR) {
retval = -EINVAL;
goto done;
@@ -574,8 +574,8 @@ static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
goto done;
}
- twoints[0] = usblp->dev->descriptor.idVendor;
- twoints[1] = usblp->dev->descriptor.idProduct;
+ twoints[0] = le16_to_cpu(usblp->dev->descriptor.idVendor);
+ twoints[1] = le16_to_cpu(usblp->dev->descriptor.idProduct);
if (copy_to_user((void __user *)arg,
(unsigned char *)twoints,
sizeof(twoints))) {
@@ -910,15 +910,15 @@ static int usblp_probe(struct usb_interface *intf,
/* Lookup quirks for this printer. */
usblp->quirks = usblp_quirks(
- dev->descriptor.idVendor,
- dev->descriptor.idProduct);
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
/* Analyze and pick initial alternate settings and endpoints. */
protocol = usblp_select_alts(usblp);
if (protocol < 0) {
dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
- dev->descriptor.idVendor,
- dev->descriptor.idProduct);
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
goto abort;
}
@@ -938,8 +938,9 @@ static int usblp_probe(struct usb_interface *intf,
usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
usblp->ifnum,
usblp->protocol[usblp->current_protocol].alt_setting,
- usblp->current_protocol, usblp->dev->descriptor.idVendor,
- usblp->dev->descriptor.idProduct);
+ usblp->current_protocol,
+ le16_to_cpu(usblp->dev->descriptor.idVendor),
+ le16_to_cpu(usblp->dev->descriptor.idProduct));
usb_set_intfdata (intf, usblp);
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 33c51714f49c0c..42e9f84662720a 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -87,7 +87,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
++ifp->desc.bNumEndpoints;
memcpy(&endpoint->desc, d, n);
- le16_to_cpus(&endpoint->desc.wMaxPacketSize);
+ INIT_LIST_HEAD(&endpoint->urb_list);
/* Skip over any Class Specific or Vendor Specific descriptors;
* find the next endpoint or interface descriptor */
@@ -319,7 +319,7 @@ int usb_parse_configuration(struct device *ddev, int cfgidx,
} /* for ((buffer2 = buffer, size2 = size); ...) */
size = buffer2 - buffer;
- config->desc.wTotalLength = buffer2 - buffer0;
+ config->desc.wTotalLength = cpu_to_le16(buffer2 - buffer0);
if (n != nintf)
dev_warn(ddev, "config %d has %d interface%s, different from "
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index 50009ed51e8d1b..a6961efc2cf0c4 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -180,7 +180,7 @@ static char *usb_dump_endpoint_descriptor (
in = (desc->bEndpointAddress & USB_DIR_IN);
dir = in ? 'I' : 'O';
if (speed == USB_SPEED_HIGH) {
- switch (desc->wMaxPacketSize & (0x03 << 11)) {
+ switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
case 1 << 11: bandwidth = 2; break;
case 2 << 11: bandwidth = 3; break;
}
@@ -227,7 +227,7 @@ static char *usb_dump_endpoint_descriptor (
start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
desc->bmAttributes, type,
- (desc->wMaxPacketSize & 0x07ff) * bandwidth,
+ (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) * bandwidth,
interval, unit);
return start;
}
@@ -335,10 +335,13 @@ static char *usb_dump_config (
*/
static char *usb_dump_device_descriptor(char *start, char *end, const struct usb_device_descriptor *desc)
{
+ u16 bcdUSB = le16_to_cpu(desc->bcdUSB);
+ u16 bcdDevice = le16_to_cpu(desc->bcdDevice);
+
if (start > end)
return start;
start += sprintf (start, format_device1,
- desc->bcdUSB >> 8, desc->bcdUSB & 0xff,
+ bcdUSB >> 8, bcdUSB & 0xff,
desc->bDeviceClass,
class_decode (desc->bDeviceClass),
desc->bDeviceSubClass,
@@ -348,8 +351,9 @@ static char *usb_dump_device_descriptor(char *start, char *end, const struct usb
if (start > end)
return start;
start += sprintf(start, format_device2,
- desc->idVendor, desc->idProduct,
- desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
+ le16_to_cpu(desc->idVendor),
+ le16_to_cpu(desc->idProduct),
+ bcdDevice >> 8, bcdDevice & 0xff);
return start;
}
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index ff47c18a01e15f..5d31114dd85d89 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -148,7 +148,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
/* The descriptor may claim to be longer than it
* really is. Here is the actual allocated length. */
unsigned alloclen =
- dev->config[i].desc.wTotalLength;
+ le16_to_cpu(dev->config[i].desc.wTotalLength);
len = length - (*ppos - pos);
if (len > nbytes)
@@ -807,7 +807,7 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
{
struct usbdevfs_urb uurb;
struct usbdevfs_iso_packet_desc *isopkt = NULL;
- struct usb_endpoint_descriptor *ep_desc;
+ struct usb_host_endpoint *ep;
struct async *as;
struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
@@ -828,14 +828,17 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
if ((ret = checkintf(ps, ifnum)))
return ret;
}
+ if ((uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) != 0)
+ ep = ps->dev->ep_in [uurb.endpoint & USB_ENDPOINT_NUMBER_MASK];
+ else
+ ep = ps->dev->ep_out [uurb.endpoint & USB_ENDPOINT_NUMBER_MASK];
+ if (!ep)
+ return -ENOENT;
switch(uurb.type) {
case USBDEVFS_URB_TYPE_CONTROL:
- if ((uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) != 0) {
- if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
- return -ENOENT;
- if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_CONTROL)
- return -EINVAL;
- }
+ if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ != USB_ENDPOINT_XFER_CONTROL)
+ return -EINVAL;
/* min 8 byte setup packet, max arbitrary */
if (uurb.buffer_length < 8 || uurb.buffer_length > PAGE_SIZE)
return -EINVAL;
@@ -864,6 +867,12 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
break;
case USBDEVFS_URB_TYPE_BULK:
+ switch (ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ case USB_ENDPOINT_XFER_ISOC:
+ return -EINVAL;
+ /* allow single-shot interrupt transfers, at bogus rates */
+ }
uurb.number_of_packets = 0;
if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
return -EINVAL;
@@ -875,9 +884,10 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
/* arbitrary limit */
if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)
return -EINVAL;
- if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
- return -ENOENT;
- interval = 1 << min (15, ep_desc->bInterval - 1);
+ if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ != USB_ENDPOINT_XFER_ISOC)
+ return -EINVAL;
+ interval = 1 << min (15, ep->desc.bInterval - 1);
isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;
if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
return -ENOMEM;
@@ -901,12 +911,13 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
case USBDEVFS_URB_TYPE_INTERRUPT:
uurb.number_of_packets = 0;
- if (!(ep_desc = usb_epnum_to_ep_desc(ps->dev, uurb.endpoint)))
- return -ENOENT;
+ if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ != USB_ENDPOINT_XFER_INT)
+ return -EINVAL;
if (ps->dev->speed == USB_SPEED_HIGH)
- interval = 1 << min (15, ep_desc->bInterval - 1);
+ interval = 1 << min (15, ep->desc.bInterval - 1);
else
- interval = ep_desc->bInterval;
+ interval = ep->desc.bInterval;
if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
return -EINVAL;
if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
@@ -1110,6 +1121,7 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
int retval = 0;
struct usb_interface *intf = NULL;
struct usb_driver *driver = NULL;
+ int i;
/* get input parameters and alloc buffer */
if (copy_from_user(&ctrl, arg, sizeof (ctrl)))
@@ -1141,6 +1153,16 @@ static int proc_ioctl (struct dev_state *ps, void __user *arg)
/* disconnect kernel driver from interface */
case USBDEVFS_DISCONNECT:
+
+ /* don't allow the user to unbind the hub driver from
+ * a hub with children to manage */
+ for (i = 0; i < ps->dev->maxchild; ++i) {
+ if (ps->dev->children[i])
+ retval = -EBUSY;
+ }
+ if (retval)
+ break;
+
down_write(&usb_bus_type.subsys.rwsem);
if (intf->dev.driver) {
driver = to_usb_driver(intf->dev.driver);
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 0a273a8fe121e2..7b836ae195308e 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -124,7 +124,7 @@ clean_1:
// driver->reset(), later on, will transfer device from
// control by SMM/BIOS to control by Linux (if needed)
- hcd = driver->hcd_alloc ();
+ hcd = usb_create_hcd (driver);
if (hcd == NULL){
dev_dbg (&dev->dev, "hcd alloc fail\n");
retval = -ENOMEM;
@@ -144,20 +144,16 @@ clean_2:
hcd->region = region;
pci_set_drvdata (dev, hcd);
- hcd->driver = driver;
- hcd->description = driver->description;
hcd->self.bus_name = pci_name(dev);
#ifdef CONFIG_PCI_NAMES
hcd->product_desc = dev->pretty_name;
-#else
- if (hcd->product_desc == NULL)
- hcd->product_desc = "USB Host Controller";
#endif
hcd->self.controller = &dev->dev;
if ((retval = hcd_buffer_create (hcd)) != 0) {
clean_3:
- kfree (hcd);
+ pci_set_drvdata (dev, NULL);
+ usb_put_hcd (hcd);
goto clean_2;
}
@@ -168,7 +164,6 @@ clean_3:
dev_err (hcd->self.controller, "can't reset\n");
goto clean_3;
}
- hcd->state = USB_STATE_HALT;
pci_set_master (dev);
#ifndef __sparc__
@@ -177,7 +172,7 @@ clean_3:
bufp = __irq_itoa(dev->irq);
#endif
retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
- hcd->description, hcd);
+ hcd->driver->description, hcd);
if (retval != 0) {
dev_err (hcd->self.controller,
"request interrupt %s failed\n", bufp);
@@ -189,14 +184,6 @@ clean_3:
(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
resource);
- usb_bus_init (&hcd->self);
- hcd->self.op = &usb_hcd_operations;
- hcd->self.release = &usb_hcd_release;
- hcd->self.hcpriv = (void *) hcd;
- init_timer (&hcd->rh_timer);
-
- INIT_LIST_HEAD (&hcd->dev_list);
-
usb_register_bus (&hcd->self);
if ((retval = driver->start (hcd)) < 0) {
@@ -411,7 +398,7 @@ int usb_hcd_pci_resume (struct pci_dev *dev)
pci_set_power_state (dev, 0);
dev->dev.power.power_state = 0;
retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
- hcd->description, hcd);
+ hcd->driver->description, hcd);
if (retval < 0) {
dev_err (hcd->self.controller,
"can't restore IRQ after resume!\n");
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index dc67f3ddf42527..da38086b21f8fe 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -120,16 +120,16 @@ DECLARE_WAIT_QUEUE_HEAD(usb_kill_urb_queue);
static const u8 usb2_rh_dev_descriptor [18] = {
0x12, /* __u8 bLength; */
0x01, /* __u8 bDescriptorType; Device */
- 0x00, 0x02, /* __u16 bcdUSB; v2.0 */
+ 0x00, 0x02, /* __le16 bcdUSB; v2.0 */
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* __u8 bDeviceSubClass; */
0x01, /* __u8 bDeviceProtocol; [ usb 2.0 single TT ]*/
0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
- 0x00, 0x00, /* __u16 idVendor; */
- 0x00, 0x00, /* __u16 idProduct; */
- KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */
+ 0x00, 0x00, /* __le16 idVendor; */
+ 0x00, 0x00, /* __le16 idProduct; */
+ KERNEL_VER, KERNEL_REL, /* __le16 bcdDevice */
0x03, /* __u8 iManufacturer; */
0x02, /* __u8 iProduct; */
@@ -143,16 +143,16 @@ static const u8 usb2_rh_dev_descriptor [18] = {
static const u8 usb11_rh_dev_descriptor [18] = {
0x12, /* __u8 bLength; */
0x01, /* __u8 bDescriptorType; Device */
- 0x10, 0x01, /* __u16 bcdUSB; v1.1 */
+ 0x10, 0x01, /* __le16 bcdUSB; v1.1 */
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* __u8 bDeviceSubClass; */
0x00, /* __u8 bDeviceProtocol; [ low/full speeds only ] */
0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
- 0x00, 0x00, /* __u16 idVendor; */
- 0x00, 0x00, /* __u16 idProduct; */
- KERNEL_VER, KERNEL_REL, /* __u16 bcdDevice */
+ 0x00, 0x00, /* __le16 idVendor; */
+ 0x00, 0x00, /* __le16 idProduct; */
+ KERNEL_VER, KERNEL_REL, /* __le16 bcdDevice */
0x03, /* __u8 iManufacturer; */
0x02, /* __u8 iProduct; */
@@ -170,7 +170,7 @@ static const u8 fs_rh_config_descriptor [] = {
/* one configuration */
0x09, /* __u8 bLength; */
0x02, /* __u8 bDescriptorType; Configuration */
- 0x19, 0x00, /* __u16 wTotalLength; */
+ 0x19, 0x00, /* __le16 wTotalLength; */
0x01, /* __u8 bNumInterfaces; (1) */
0x01, /* __u8 bConfigurationValue; */
0x00, /* __u8 iConfiguration; */
@@ -208,7 +208,7 @@ static const u8 fs_rh_config_descriptor [] = {
0x05, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x02, 0x00, /* __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+ 0x02, 0x00, /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
0xff /* __u8 ep_bInterval; (255ms -- usb 2.0 spec) */
};
@@ -217,7 +217,7 @@ static const u8 hs_rh_config_descriptor [] = {
/* one configuration */
0x09, /* __u8 bLength; */
0x02, /* __u8 bDescriptorType; Configuration */
- 0x19, 0x00, /* __u16 wTotalLength; */
+ 0x19, 0x00, /* __le16 wTotalLength; */
0x01, /* __u8 bNumInterfaces; (1) */
0x01, /* __u8 bConfigurationValue; */
0x00, /* __u8 iConfiguration; */
@@ -255,7 +255,7 @@ static const u8 hs_rh_config_descriptor [] = {
0x05, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x02, 0x00, /* __u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
+ 0x02, 0x00, /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */
};
@@ -312,7 +312,7 @@ static int rh_string (
// id 3 == vendor description
} else if (id == 3) {
sprintf (buf, "%s %s %s", UTS_SYSNAME, UTS_RELEASE,
- hcd->description);
+ hcd->driver->description);
// unsupported IDs --> "protocol stall"
} else
@@ -676,6 +676,8 @@ void usb_bus_init (struct usb_bus *bus)
bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD (&bus->bus_list);
+
+ class_device_initialize(&bus->class_dev);
}
EXPORT_SYMBOL (usb_bus_init);
@@ -734,7 +736,7 @@ int usb_register_bus(struct usb_bus *bus)
snprintf(bus->class_dev.class_id, BUS_ID_SIZE, "usb%d", busnum);
bus->class_dev.class = &usb_host_class;
bus->class_dev.dev = bus->controller;
- retval = class_device_register(&bus->class_dev);
+ retval = class_device_add(&bus->class_dev);
if (retval) {
clear_bit(busnum, busmap.busmap);
up(&usb_bus_list_lock);
@@ -807,7 +809,7 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
down (&usb_bus_list_lock);
usb_dev->bus->root_hub = usb_dev;
- usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64;
+ usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
if (retval != sizeof usb_dev->descriptor) {
usb_dev->bus->root_hub = NULL;
@@ -1018,40 +1020,6 @@ EXPORT_SYMBOL (usb_release_bandwidth);
/*-------------------------------------------------------------------------*/
-/* called from khubd, or root hub init threads for hcd-private init */
-static int hcd_alloc_dev (struct usb_device *udev)
-{
- struct hcd_dev *dev;
- struct usb_hcd *hcd;
- unsigned long flags;
-
- if (!udev || udev->hcpriv)
- return -EINVAL;
- if (!udev->bus || !udev->bus->hcpriv)
- return -ENODEV;
- hcd = udev->bus->hcpriv;
- if (hcd->state == USB_STATE_QUIESCING)
- return -ENOLINK;
-
- dev = (struct hcd_dev *) kmalloc (sizeof *dev, GFP_KERNEL);
- if (dev == NULL)
- return -ENOMEM;
- memset (dev, 0, sizeof *dev);
-
- INIT_LIST_HEAD (&dev->dev_list);
- INIT_LIST_HEAD (&dev->urb_list);
-
- spin_lock_irqsave (&hcd_data_lock, flags);
- list_add (&dev->dev_list, &hcd->dev_list);
- // refcount is implicit
- udev->hcpriv = dev;
- spin_unlock_irqrestore (&hcd_data_lock, flags);
-
- return 0;
-}
-
-/*-------------------------------------------------------------------------*/
-
static void urb_unlink (struct urb *urb)
{
unsigned long flags;
@@ -1079,10 +1047,12 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
{
int status;
struct usb_hcd *hcd = urb->dev->bus->hcpriv;
- struct hcd_dev *dev = urb->dev->hcpriv;
+ struct usb_host_endpoint *ep;
unsigned long flags;
- if (!hcd || !dev)
+ ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
+ [usb_pipeendpoint(urb->pipe)];
+ if (!hcd || !ep)
return -ENODEV;
/*
@@ -1109,7 +1079,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
case USB_STATE_RUNNING:
case USB_STATE_RESUMING:
usb_get_dev (urb->dev);
- list_add_tail (&urb->urb_list, &dev->urb_list);
+ list_add_tail (&urb->urb_list, &ep->urb_list);
status = 0;
break;
default:
@@ -1163,7 +1133,7 @@ static int hcd_submit_urb (struct urb *urb, int mem_flags)
: DMA_TO_DEVICE);
}
- status = hcd->driver->urb_enqueue (hcd, urb, mem_flags);
+ status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags);
done:
if (unlikely (status)) {
urb_unlink (urb);
@@ -1222,7 +1192,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
*/
static int hcd_unlink_urb (struct urb *urb, int status)
{
- struct hcd_dev *dev;
+ struct usb_host_endpoint *ep;
struct usb_hcd *hcd = NULL;
struct device *sys = NULL;
unsigned long flags;
@@ -1231,6 +1201,12 @@ static int hcd_unlink_urb (struct urb *urb, int status)
if (!urb)
return -EINVAL;
+ if (!urb->dev || !urb->dev->bus)
+ return -ENODEV;
+ ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
+ [usb_pipeendpoint(urb->pipe)];
+ if (!ep)
+ return -ENODEV;
/*
* we contend for urb->status with the hcd core,
@@ -1246,15 +1222,9 @@ static int hcd_unlink_urb (struct urb *urb, int status)
spin_lock_irqsave (&urb->lock, flags);
spin_lock (&hcd_data_lock);
- if (!urb->dev || !urb->dev->bus) {
- retval = -ENODEV;
- goto done;
- }
-
- dev = urb->dev->hcpriv;
sys = &urb->dev->dev;
hcd = urb->dev->bus->hcpriv;
- if (!dev || !hcd) {
+ if (hcd == NULL) {
retval = -ENODEV;
goto done;
}
@@ -1266,7 +1236,7 @@ static int hcd_unlink_urb (struct urb *urb, int status)
WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
/* insist the urb is still queued */
- list_for_each(tmp, &dev->urb_list) {
+ list_for_each(tmp, &ep->urb_list) {
if (tmp == &urb->urb_list)
break;
}
@@ -1283,13 +1253,14 @@ static int hcd_unlink_urb (struct urb *urb, int status)
goto done;
}
- /* PCI IRQ setup can easily be broken so that USB controllers
+ /* IRQ setup can easily be broken so that USB controllers
* never get completion IRQs ... maybe even the ones we need to
- * finish unlinking the initial failed usb_set_address().
+ * finish unlinking the initial failed usb_set_address()
+ * or device descriptor fetch.
*/
if (!hcd->saw_irq && hcd->self.root_hub != urb->dev) {
dev_warn (hcd->self.controller, "Unlink after no-IRQ? "
- "Different ACPI or APIC settings may help."
+ "Controller is probably using the wrong IRQ."
"\n");
hcd->saw_irq = 1;
}
@@ -1318,46 +1289,36 @@ done:
* the hcd to make sure all endpoint state is gone from hardware. use for
* set_configuration, set_interface, driver removal, physical disconnect.
*
- * example: a qh stored in hcd_dev.ep[], holding state related to endpoint
+ * example: a qh stored in ep->hcpriv, holding state related to endpoint
* type, maxpacket size, toggle, halt status, and scheduling.
*/
-static void hcd_endpoint_disable (struct usb_device *udev, int endpoint)
+static void
+hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
{
- struct hcd_dev *dev;
- struct usb_hcd *hcd;
- struct urb *urb;
- unsigned epnum = endpoint & USB_ENDPOINT_NUMBER_MASK;
+ struct usb_hcd *hcd;
+ struct urb *urb;
- dev = udev->hcpriv;
hcd = udev->bus->hcpriv;
WARN_ON (!HCD_IS_RUNNING (hcd->state) && hcd->state != USB_STATE_HALT);
local_irq_disable ();
-rescan:
- /* (re)block new requests, as best we can */
- if (endpoint & USB_DIR_IN)
- udev->epmaxpacketin [epnum] = 0;
- else
- udev->epmaxpacketout [epnum] = 0;
+ /* FIXME move most of this into message.c as part of its
+ * endpoint disable logic
+ */
- /* then kill any current requests */
+ /* ep is already gone from udev->ep_{in,out}[]; no more submits */
+rescan:
spin_lock (&hcd_data_lock);
- list_for_each_entry (urb, &dev->urb_list, urb_list) {
- int tmp = urb->pipe;
-
- /* ignore urbs for other endpoints */
- if (usb_pipeendpoint (tmp) != epnum)
- continue;
- /* NOTE assumption that only ep0 is a control endpoint */
- if (epnum != 0 && ((tmp ^ endpoint) & USB_DIR_IN))
- continue;
+ list_for_each_entry (urb, &ep->urb_list, urb_list) {
+ int tmp;
/* another cpu may be in hcd, spinning on hcd_data_lock
* to giveback() this urb. the races here should be
* small, but a full fix needs a new "can't submit"
* urb state.
+ * FIXME urb->reject should allow that...
*/
if (urb->status != -EINPROGRESS)
continue;
@@ -1399,7 +1360,7 @@ rescan:
*/
might_sleep ();
if (hcd->driver->endpoint_disable)
- hcd->driver->endpoint_disable (hcd, dev, endpoint);
+ hcd->driver->endpoint_disable (hcd, ep);
}
/*-------------------------------------------------------------------------*/
@@ -1469,57 +1430,13 @@ EXPORT_SYMBOL (usb_bus_start_enum);
/*-------------------------------------------------------------------------*/
-/* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup.
- * we're guaranteed that the device is fully quiesced. also, that each
- * endpoint has been hcd_endpoint_disabled.
- */
-
-static int hcd_free_dev (struct usb_device *udev)
-{
- struct hcd_dev *dev;
- struct usb_hcd *hcd;
- unsigned long flags;
-
- if (!udev || !udev->hcpriv)
- return -EINVAL;
-
- if (!udev->bus || !udev->bus->hcpriv)
- return -ENODEV;
-
- // should udev->devnum == -1 ??
-
- dev = udev->hcpriv;
- hcd = udev->bus->hcpriv;
-
- /* device driver problem with refcounts? */
- if (!list_empty (&dev->urb_list)) {
- dev_dbg (hcd->self.controller, "free busy dev, %s devnum %d (bug!)\n",
- hcd->self.bus_name, udev->devnum);
- return -EINVAL;
- }
-
- spin_lock_irqsave (&hcd_data_lock, flags);
- list_del (&dev->dev_list);
- udev->hcpriv = NULL;
- spin_unlock_irqrestore (&hcd_data_lock, flags);
-
- kfree (dev);
- return 0;
-}
-
/*
* usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue)
- *
- * When registering a USB bus through the HCD framework code, use this
- * usb_operations vector. The PCI glue layer does so automatically; only
- * bus glue for non-PCI system busses will need to use this.
*/
-struct usb_operations usb_hcd_operations = {
- .allocate = hcd_alloc_dev,
+static struct usb_operations usb_hcd_operations = {
.get_frame_number = hcd_get_frame_number,
.submit_urb = hcd_submit_urb,
.unlink_urb = hcd_unlink_urb,
- .deallocate = hcd_free_dev,
.buffer_alloc = hcd_buffer_alloc,
.buffer_free = hcd_buffer_free,
.disable = hcd_endpoint_disable,
@@ -1528,7 +1445,6 @@ struct usb_operations usb_hcd_operations = {
.hub_resume = hcd_hub_resume,
#endif
};
-EXPORT_SYMBOL (usb_hcd_operations);
/*-------------------------------------------------------------------------*/
@@ -1630,11 +1546,51 @@ EXPORT_SYMBOL (usb_hc_died);
/*-------------------------------------------------------------------------*/
-void usb_hcd_release(struct usb_bus *bus)
+static void hcd_release (struct usb_bus *bus)
{
struct usb_hcd *hcd;
- hcd = container_of (bus, struct usb_hcd, self);
+ hcd = container_of(bus, struct usb_hcd, self);
kfree(hcd);
}
-EXPORT_SYMBOL (usb_hcd_release);
+
+/**
+ * usb_create_hcd - create and initialize an HCD structure
+ * @driver: HC driver that will use this hcd
+ * Context: !in_interrupt()
+ *
+ * Allocate a struct usb_hcd, with extra space at the end for the
+ * HC driver's private data. Initialize the generic members of the
+ * hcd structure.
+ *
+ * If memory is unavailable, returns NULL.
+ */
+struct usb_hcd *usb_create_hcd (const struct hc_driver *driver)
+{
+ struct usb_hcd *hcd;
+
+ hcd = kcalloc(1, sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
+ if (!hcd)
+ return NULL;
+
+ usb_bus_init(&hcd->self);
+ hcd->self.op = &usb_hcd_operations;
+ hcd->self.hcpriv = hcd;
+ hcd->self.release = &hcd_release;
+
+ init_timer(&hcd->rh_timer);
+
+ hcd->driver = driver;
+ hcd->product_desc = (driver->product_desc) ? driver->product_desc :
+ "USB Host Controller";
+ hcd->state = USB_STATE_HALT;
+
+ return hcd;
+}
+EXPORT_SYMBOL (usb_create_hcd);
+
+void usb_put_hcd (struct usb_hcd *hcd)
+{
+ usb_bus_put(&hcd->self);
+}
+EXPORT_SYMBOL (usb_put_hcd);
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 12a2b9f8032177..64884196cf21e5 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -63,15 +63,13 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
struct usb_bus self; /* hcd is-a bus */
const char *product_desc; /* product/vendor string */
- const char *description; /* "ehci-hcd" etc */
struct timer_list rh_timer; /* drives root hub */
- struct list_head dev_list; /* devices on this bus */
/*
* hardware info/state
*/
- struct hc_driver *driver; /* hw-specific hooks */
+ const struct hc_driver *driver; /* hw-specific hooks */
unsigned saw_irq : 1;
unsigned can_wakeup:1; /* hw supports wakeup? */
unsigned remote_wakeup:1;/* sw should use wakeup? */
@@ -104,6 +102,12 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
* input size of periodic table to an interrupt scheduler.
* (ohci 32, uhci 1024, ehci 256/512/1024).
*/
+
+ /* The HC driver's private data is stored at the end of
+ * this structure.
+ */
+ unsigned long hcd_priv[0]
+ __attribute__ ((aligned (sizeof(unsigned long))));
};
/* 2.4 does this a bit differently ... */
@@ -113,14 +117,6 @@ static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
}
-struct hcd_dev { /* usb_device.hcpriv points to this */
- struct list_head dev_list; /* on this hcd */
- struct list_head urb_list; /* pending on this dev */
-
- /* per-configuration HC/HCD state, such as QH or ED */
- void *ep[32];
-};
-
// urb.hcpriv is really hardware-specific
struct hcd_timeout { /* timeouts we allocate */
@@ -136,8 +132,6 @@ struct hcd_timeout { /* timeouts we allocate */
*/
struct usb_operations {
- int (*allocate)(struct usb_device *);
- int (*deallocate)(struct usb_device *);
int (*get_frame_number) (struct usb_device *usb_dev);
int (*submit_urb) (struct urb *urb, int mem_flags);
int (*unlink_urb) (struct urb *urb, int status);
@@ -149,7 +143,8 @@ struct usb_operations {
void (*buffer_free)(struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
- void (*disable)(struct usb_device *udev, int bEndpointAddress);
+ void (*disable)(struct usb_device *udev,
+ struct usb_host_endpoint *ep);
/* global suspend/resume of bus */
int (*hub_suspend)(struct usb_bus *);
@@ -162,6 +157,8 @@ struct pt_regs;
struct hc_driver {
const char *description; /* "ehci-hcd" etc */
+ const char *product_desc; /* product/vendor string */
+ size_t hcd_priv_size; /* size of private data */
/* irq handler */
irqreturn_t (*irq) (struct usb_hcd *hcd, struct pt_regs *regs);
@@ -190,23 +187,16 @@ struct hc_driver {
/* return current frame number */
int (*get_frame_number) (struct usb_hcd *hcd);
- /* memory lifecycle */
- /* Note: The absence of hcd_free reflects a temporary situation;
- * in the near future hcd_alloc will disappear as well and all
- * allocations/deallocations will be handled by usbcore. For the
- * moment, drivers are required to return a pointer that the core
- * can pass to kfree, i.e., the struct usb_hcd must be the _first_
- * member of a larger driver-specific structure. */
- struct usb_hcd *(*hcd_alloc) (void);
-
/* manage i/o requests, device state */
- int (*urb_enqueue) (struct usb_hcd *hcd, struct urb *urb,
+ int (*urb_enqueue) (struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep,
+ struct urb *urb,
int mem_flags);
int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb);
/* hw synch, freeing endpoint resources that urb_dequeue can't */
void (*endpoint_disable)(struct usb_hcd *hcd,
- struct hcd_dev *dev, int bEndpointAddress);
+ struct usb_host_endpoint *ep);
/* root hub support */
int (*hub_status_data) (struct usb_hcd *hcd, char *buf);
@@ -221,6 +211,10 @@ struct hc_driver {
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
extern void usb_bus_init (struct usb_bus *bus);
+extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver);
+extern void usb_put_hcd (struct usb_hcd *hcd);
+
+
#ifdef CONFIG_PCI
struct pci_dev;
struct pci_device_id;
@@ -245,7 +239,6 @@ void hcd_buffer_free (struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
/* generic bus glue, needed for host controllers that don't use PCI */
-extern struct usb_operations usb_hcd_operations;
extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r);
extern void usb_hc_died (struct usb_hcd *hcd);
@@ -365,8 +358,6 @@ static inline int hcd_register_root (struct usb_device *usb_dev,
return usb_register_root_hub (usb_dev, hcd->self.controller);
}
-extern void usb_hcd_release (struct usb_bus *);
-
extern void usb_set_device_state(struct usb_device *udev,
enum usb_device_state new_state);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 161c52f2e42ae8..4509d9ee0370de 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -94,10 +94,10 @@ static inline char *portspeed (int portstatus)
}
#endif
-/* for dev_info, dev_dbg, etc */
-static inline struct device *hubdev (struct usb_device *hdev)
+/* Note that hdev or one of its children must be locked! */
+static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev)
{
- return &hdev->actconfig->interface[0]->dev;
+ return usb_get_intfdata(hdev->actconfig->interface[0]);
}
/* USB 2.0 spec Section 11.24.4.5 */
@@ -128,19 +128,21 @@ static int clear_hub_feature(struct usb_device *hdev, int feature)
/*
* USB 2.0 spec Section 11.24.2.2
*/
-static int clear_port_feature(struct usb_device *hdev, int port, int feature)
+static int clear_port_feature(struct usb_device *hdev, int port1, int feature)
{
return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
- USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ);
+ USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1,
+ NULL, 0, HZ);
}
/*
* USB 2.0 spec Section 11.24.2.13
*/
-static int set_port_feature(struct usb_device *hdev, int port, int feature)
+static int set_port_feature(struct usb_device *hdev, int port1, int feature)
{
return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
- USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port, NULL, 0, HZ);
+ USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1,
+ NULL, 0, HZ);
}
/*
@@ -148,17 +150,17 @@ static int set_port_feature(struct usb_device *hdev, int port, int feature)
* for info about using port indicators
*/
static void set_port_led(
- struct usb_device *hdev,
- int port,
+ struct usb_hub *hub,
+ int port1,
int selector
)
{
- int status = set_port_feature(hdev, (selector << 8) | port,
+ int status = set_port_feature(hub->hdev, (selector << 8) | port1,
USB_PORT_FEAT_INDICATOR);
if (status < 0)
- dev_dbg (hubdev (hdev),
+ dev_dbg (hub->intfdev,
"port %d indicator %s status %d\n",
- port,
+ port1,
({ char *s; switch (selector) {
case HUB_LED_AMBER: s = "amber"; break;
case HUB_LED_GREEN: s = "green"; break;
@@ -226,13 +228,13 @@ static void led_work (void *__hub)
}
if (selector != HUB_LED_AUTO)
changed = 1;
- set_port_led(hdev, i + 1, selector);
+ set_port_led(hub, i + 1, selector);
hub->indicator[i] = mode;
}
if (!changed && blinkenlights) {
cursor++;
cursor %= hub->descriptor->bNbrPorts;
- set_port_led(hdev, cursor + 1, HUB_LED_GREEN);
+ set_port_led(hub, cursor + 1, HUB_LED_GREEN);
hub->indicator[cursor] = INDICATOR_CYCLE;
changed++;
}
@@ -240,26 +242,40 @@ static void led_work (void *__hub)
schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
}
+/* use a short timeout for hub/port status fetches */
+#define USB_STS_TIMEOUT 1
+#define USB_STS_RETRIES 5
+
/*
* USB 2.0 spec Section 11.24.2.6
*/
static int get_hub_status(struct usb_device *hdev,
struct usb_hub_status *data)
{
- return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
- data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT);
+ int i, status = -ETIMEDOUT;
+
+ for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
+ status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
+ data, sizeof(*data), HZ * USB_STS_TIMEOUT);
+ }
+ return status;
}
/*
* USB 2.0 spec Section 11.24.2.7
*/
-static int get_port_status(struct usb_device *hdev, int port,
+static int get_port_status(struct usb_device *hdev, int port1,
struct usb_port_status *data)
{
- return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
- USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port,
- data, sizeof(*data), HZ * USB_CTRL_GET_TIMEOUT);
+ int i, status = -ETIMEDOUT;
+
+ for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
+ status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1,
+ data, sizeof(*data), HZ * USB_STS_TIMEOUT);
+ }
+ return status;
}
static void kick_khubd(struct usb_hub *hub)
@@ -291,7 +307,7 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
default: /* presumably an error */
/* Cause a hub reset after 10 consecutive errors */
- dev_dbg (&hub->intf->dev, "transfer --> %d\n", urb->status);
+ dev_dbg (hub->intfdev, "transfer --> %d\n", urb->status);
if ((++hub->nerrors < 10) || hub->error)
goto resubmit;
hub->error = urb->status;
@@ -318,7 +334,7 @@ resubmit:
if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
&& status != -ENODEV && status != -EPERM)
- dev_err (&hub->intf->dev, "resubmit --> %d\n", status);
+ dev_err (hub->intfdev, "resubmit --> %d\n", status);
}
/* USB 2.0 spec Section 11.24.2.3 */
@@ -414,13 +430,13 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe)
static void hub_power_on(struct usb_hub *hub)
{
- int i;
+ int port1;
/* if hub supports power switching, enable power on each port */
if ((hub->descriptor->wHubCharacteristics & HUB_CHAR_LPSM) < 2) {
- dev_dbg(&hub->intf->dev, "enabling power on all ports\n");
- for (i = 0; i < hub->descriptor->bNbrPorts; i++)
- set_port_feature(hub->hdev, i + 1,
+ dev_dbg(hub->intfdev, "enabling power on all ports\n");
+ for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
+ set_port_feature(hub->hdev, port1,
USB_PORT_FEAT_POWER);
}
@@ -446,12 +462,12 @@ static void hub_activate(struct usb_hub *hub)
hub->quiescing = 0;
status = usb_submit_urb(hub->urb, GFP_NOIO);
if (status < 0)
- dev_err(&hub->intf->dev, "activate --> %d\n", status);
+ dev_err(hub->intfdev, "activate --> %d\n", status);
if (hub->has_indicators && blinkenlights)
schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
/* scan all ports ASAP */
- hub->event_bits[0] = ~0;
+ hub->event_bits[0] = (1UL << (hub->descriptor->bNbrPorts + 1)) - 1;
kick_khubd(hub);
}
@@ -462,7 +478,7 @@ static int hub_hub_status(struct usb_hub *hub,
ret = get_hub_status(hub->hdev, &hub->status->hub);
if (ret < 0)
- dev_err (&hub->intf->dev,
+ dev_err (hub->intfdev,
"%s failed (err = %d)\n", __FUNCTION__, ret);
else {
*status = le16_to_cpu(hub->status->hub.wHubStatus);
@@ -476,7 +492,7 @@ static int hub_configure(struct usb_hub *hub,
struct usb_endpoint_descriptor *endpoint)
{
struct usb_device *hdev = hub->hdev;
- struct device *hub_dev = &hub->intf->dev;
+ struct device *hub_dev = hub->intfdev;
u16 hubstatus, hubchange;
unsigned int pipe;
int maxp, ret;
@@ -674,7 +690,7 @@ static int hub_configure(struct usb_hub *hub,
hub->indicator [0] = INDICATOR_CYCLE;
hub_power_on(hub);
- hub->change_bits[0] = ~0;
+ hub->change_bits[0] = (1UL << (hub->descriptor->bNbrPorts + 1)) - 2;
hub_activate(hub);
return 0;
@@ -735,18 +751,16 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_endpoint_descriptor *endpoint;
struct usb_device *hdev;
struct usb_hub *hub;
- struct device *hub_dev;
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
- hub_dev = &intf->dev;
/* Some hubs have a subclass of 1, which AFAICT according to the */
/* specs is not defined, but it works */
if ((desc->desc.bInterfaceSubClass != 0) &&
(desc->desc.bInterfaceSubClass != 1)) {
descriptor_error:
- dev_err (hub_dev, "bad descriptor, ignoring hub\n");
+ dev_err (&intf->dev, "bad descriptor, ignoring hub\n");
return -EIO;
}
@@ -766,18 +780,18 @@ descriptor_error:
goto descriptor_error;
/* We found a hub */
- dev_info (hub_dev, "USB hub found\n");
+ dev_info (&intf->dev, "USB hub found\n");
hub = kmalloc(sizeof(*hub), GFP_KERNEL);
if (!hub) {
- dev_dbg (hub_dev, "couldn't kmalloc hub struct\n");
+ dev_dbg (&intf->dev, "couldn't kmalloc hub struct\n");
return -ENOMEM;
}
memset(hub, 0, sizeof(*hub));
INIT_LIST_HEAD(&hub->event_list);
- hub->intf = intf;
+ hub->intfdev = &intf->dev;
hub->hdev = hdev;
INIT_WORK(&hub->leds, led_work, hub);
@@ -802,10 +816,9 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
switch (code) {
case USBDEVFS_HUB_PORTINFO: {
struct usbdevfs_hub_portinfo *info = user_data;
- unsigned long flags;
int i;
- spin_lock_irqsave(&hub_event_lock, flags);
+ spin_lock_irq(&device_state_lock);
if (hdev->devnum <= 0)
info->nports = 0;
else {
@@ -818,7 +831,7 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
hdev->children[i]->devnum;
}
}
- spin_unlock_irqrestore(&hub_event_lock, flags);
+ spin_unlock_irq(&device_state_lock);
return info->nports + 1;
}
@@ -829,9 +842,9 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
}
/* caller has locked the hub device */
-static void hub_pre_reset(struct usb_device *hdev)
+static void hub_pre_reset(struct usb_hub *hub)
{
- struct usb_hub *hub = usb_get_intfdata(hdev->actconfig->interface[0]);
+ struct usb_device *hdev = hub->hdev;
int i;
for (i = 0; i < hdev->maxchild; ++i) {
@@ -842,10 +855,8 @@ static void hub_pre_reset(struct usb_device *hdev)
}
/* caller has locked the hub device */
-static void hub_post_reset(struct usb_device *hdev)
+static void hub_post_reset(struct usb_hub *hub)
{
- struct usb_hub *hub = usb_get_intfdata(hdev->actconfig->interface[0]);
-
hub_activate(hub);
hub_power_on(hub);
}
@@ -890,7 +901,7 @@ static int locktree(struct usb_device *udev)
*/
down(&udev->serialize);
up(&hdev->serialize);
- return t;
+ return t + 1;
}
}
usb_unlock_device(hdev);
@@ -1178,25 +1189,25 @@ int usb_new_device(struct usb_device *udev)
/* descriptor may appear anywhere in config */
if (__usb_get_extra_descriptor (udev->rawdescriptors[0],
- udev->config[0].desc.wTotalLength,
+ le16_to_cpu(udev->config[0].desc.wTotalLength),
USB_DT_OTG, (void **) &desc) == 0) {
if (desc->bmAttributes & USB_OTG_HNP) {
- unsigned port;
+ unsigned port1;
struct usb_device *root = udev->parent;
- for (port = 0; port < root->maxchild; port++) {
- if (root->children[port] == udev)
+ for (port1 = 1; port1 <= root->maxchild;
+ port1++) {
+ if (root->children[port1-1] == udev)
break;
}
- port++;
dev_info(&udev->dev,
"Dual-Role OTG device on %sHNP port\n",
- (port == bus->otg_port)
+ (port1 == bus->otg_port)
? "" : "non-");
/* enable HNP before suspend, it's simpler */
- if (port == bus->otg_port)
+ if (port1 == bus->otg_port)
bus->b_hnp_enable = 1;
err = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
@@ -1225,9 +1236,9 @@ int usb_new_device(struct usb_device *udev)
*/
if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
static int __usb_suspend_device (struct usb_device *,
- int port, u32 state);
+ int port1, u32 state);
err = __usb_suspend_device(udev,
- udev->bus->otg_port - 1,
+ udev->bus->otg_port,
PM_SUSPEND_MEM);
if (err < 0)
dev_dbg(&udev->dev, "HNP fail, %d\n", err);
@@ -1275,18 +1286,14 @@ fail:
}
-static int hub_port_status(struct usb_device *hdev, int port,
+static int hub_port_status(struct usb_hub *hub, int port1,
u16 *status, u16 *change)
{
- struct usb_hub *hub = usb_get_intfdata(hdev->actconfig->interface[0]);
int ret;
- if (!hub)
- return -ENODEV;
-
- ret = get_port_status(hdev, port + 1, &hub->status->port);
+ ret = get_port_status(hub->hdev, port1, &hub->status->port);
if (ret < 0)
- dev_err (&hub->intf->dev,
+ dev_err (hub->intfdev,
"%s failed (err = %d)\n", __FUNCTION__, ret);
else {
*status = le16_to_cpu(hub->status->port.wPortStatus);
@@ -1307,7 +1314,7 @@ static int hub_port_status(struct usb_device *hdev, int port,
#define HUB_LONG_RESET_TIME 200
#define HUB_RESET_TIMEOUT 500
-static int hub_port_wait_reset(struct usb_device *hdev, int port,
+static int hub_port_wait_reset(struct usb_hub *hub, int port1,
struct usb_device *udev, unsigned int delay)
{
int delay_time, ret;
@@ -1321,7 +1328,7 @@ static int hub_port_wait_reset(struct usb_device *hdev, int port,
msleep(delay);
/* read and decode port status */
- ret = hub_port_status(hdev, port, &portstatus, &portchange);
+ ret = hub_port_status(hub, port1, &portstatus, &portchange);
if (ret < 0)
return ret;
@@ -1349,36 +1356,37 @@ static int hub_port_wait_reset(struct usb_device *hdev, int port,
if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
delay = HUB_LONG_RESET_TIME;
- dev_dbg (hubdev (hdev),
+ dev_dbg (hub->intfdev,
"port %d not reset yet, waiting %dms\n",
- port + 1, delay);
+ port1, delay);
}
return -EBUSY;
}
-static int hub_port_reset(struct usb_device *hdev, int port,
+static int hub_port_reset(struct usb_hub *hub, int port1,
struct usb_device *udev, unsigned int delay)
{
int i, status;
- struct device *hub_dev = hubdev (hdev);
/* Reset the port */
for (i = 0; i < PORT_RESET_TRIES; i++) {
- status = set_port_feature(hdev, port + 1, USB_PORT_FEAT_RESET);
+ status = set_port_feature(hub->hdev,
+ port1, USB_PORT_FEAT_RESET);
if (status)
- dev_err(hub_dev, "cannot reset port %d (err = %d)\n",
- port + 1, status);
+ dev_err(hub->intfdev,
+ "cannot reset port %d (err = %d)\n",
+ port1, status);
else
- status = hub_port_wait_reset(hdev, port, udev, delay);
+ status = hub_port_wait_reset(hub, port1, udev, delay);
/* return on disconnect or reset */
switch (status) {
case 0:
case -ENOTCONN:
case -ENODEV:
- clear_port_feature(hdev,
- port + 1, USB_PORT_FEAT_C_RESET);
+ clear_port_feature(hub->hdev,
+ port1, USB_PORT_FEAT_C_RESET);
/* FIXME need disconnect() for NOTATTACHED device */
usb_set_device_state(udev, status
? USB_STATE_NOTATTACHED
@@ -1386,31 +1394,32 @@ static int hub_port_reset(struct usb_device *hdev, int port,
return status;
}
- dev_dbg (hub_dev,
+ dev_dbg (hub->intfdev,
"port %d not enabled, trying reset again...\n",
- port + 1);
+ port1);
delay = HUB_LONG_RESET_TIME;
}
- dev_err (hub_dev,
+ dev_err (hub->intfdev,
"Cannot enable port %i. Maybe the USB cable is bad?\n",
- port + 1);
+ port1);
return status;
}
-static int hub_port_disable(struct usb_device *hdev, int port)
+static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
{
+ struct usb_device *hdev = hub->hdev;
int ret;
- if (hdev->children[port]) {
- usb_set_device_state(hdev->children[port],
+ if (hdev->children[port1-1] && set_state) {
+ usb_set_device_state(hdev->children[port1-1],
USB_STATE_NOTATTACHED);
}
- ret = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_ENABLE);
+ ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
if (ret)
- dev_err(hubdev(hdev), "cannot disable port %d (err = %d)\n",
- port + 1, ret);
+ dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
+ port1, ret);
return ret;
}
@@ -1420,12 +1429,10 @@ static int hub_port_disable(struct usb_device *hdev, int port)
* time later khubd will disconnect() any existing usb_device on the port
* and will re-enumerate if there actually is a device attached.
*/
-static void hub_port_logical_disconnect(struct usb_device *hdev, int port)
+static void hub_port_logical_disconnect(struct usb_hub *hub, int port1)
{
- struct usb_hub *hub;
-
- dev_dbg(hubdev(hdev), "logical disconnect on port %d\n", port + 1);
- hub_port_disable(hdev, port);
+ dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1);
+ hub_port_disable(hub, port1, 1);
/* FIXME let caller ask to power down the port:
* - some devices won't enumerate without a VBUS power cycle
@@ -1436,8 +1443,7 @@ static void hub_port_logical_disconnect(struct usb_device *hdev, int port)
* Powerdown must be optional, because of reset/DFU.
*/
- hub = usb_get_intfdata(hdev->actconfig->interface[0]);
- set_bit(port, hub->change_bits);
+ set_bit(port1, hub->change_bits);
kick_khubd(hub);
}
@@ -1454,13 +1460,12 @@ static void hub_port_logical_disconnect(struct usb_device *hdev, int port)
* tree above them to deliver data, such as a keypress or packet. In
* some cases, this wakes the USB host.
*/
-static int hub_port_suspend(struct usb_device *hdev, int port)
+static int hub_port_suspend(struct usb_hub *hub, int port1,
+ struct usb_device *udev)
{
- int status;
- struct usb_device *udev;
+ int status;
- udev = hdev->children[port];
- // dev_dbg(hubdev(hdev), "suspend port %d\n", port + 1);
+ // dev_dbg(hub->intfdev, "suspend port %d\n", port1);
/* enable remote wakeup when appropriate; this lets the device
* wake up the upstream hub (including maybe the root hub).
@@ -1485,11 +1490,11 @@ static int hub_port_suspend(struct usb_device *hdev, int port)
}
/* see 7.1.7.6 */
- status = set_port_feature(hdev, port + 1, USB_PORT_FEAT_SUSPEND);
+ status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND);
if (status) {
- dev_dbg(hubdev(hdev),
+ dev_dbg(hub->intfdev,
"can't suspend port %d, status %d\n",
- port + 1, status);
+ port1, status);
/* paranoia: "should not happen" */
(void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE,
@@ -1499,7 +1504,7 @@ static int hub_port_suspend(struct usb_device *hdev, int port)
} else {
/* device has up to 10 msec to fully suspend */
dev_dbg(&udev->dev, "usb suspend\n");
- udev->state = USB_STATE_SUSPENDED;
+ usb_set_device_state(udev, USB_STATE_SUSPENDED);
msleep(10);
}
return status;
@@ -1519,13 +1524,13 @@ static int hub_port_suspend(struct usb_device *hdev, int port)
* Linux (2.6) currently has NO mechanisms to initiate that: no khubd
* timer, no SRP, no requests through sysfs.
*/
-int __usb_suspend_device (struct usb_device *udev, int port, u32 state)
+int __usb_suspend_device (struct usb_device *udev, int port1, u32 state)
{
int status;
/* caller owns the udev device lock */
- if (port < 0)
- return port;
+ if (port1 < 0)
+ return port1;
if (udev->state == USB_STATE_SUSPENDED
|| udev->state == USB_STATE_NOTATTACHED) {
@@ -1606,8 +1611,11 @@ int __usb_suspend_device (struct usb_device *udev, int port, u32 state)
} else
status = -EOPNOTSUPP;
} else
- status = hub_port_suspend(udev->parent, port);
+ status = hub_port_suspend(hdev_to_hub(udev->parent), port1,
+ udev);
+ if (status == 0)
+ udev->dev.power.power_state = state;
return status;
}
EXPORT_SYMBOL(__usb_suspend_device);
@@ -1632,13 +1640,13 @@ EXPORT_SYMBOL(__usb_suspend_device);
*/
int usb_suspend_device(struct usb_device *udev, u32 state)
{
- int port, status;
+ int port1, status;
- port = locktree(udev);
- if (port < 0)
- return port;
+ port1 = locktree(udev);
+ if (port1 < 0)
+ return port1;
- status = __usb_suspend_device(udev, port, state);
+ status = __usb_suspend_device(udev, port1, state);
usb_unlock_device(udev);
return status;
}
@@ -1661,9 +1669,10 @@ static int finish_port_resume(struct usb_device *udev)
* first two on the host side; they'd be inside hub_port_init()
* during many timeouts, but khubd can't suspend until later.
*/
- udev->state = udev->actconfig
- ? USB_STATE_CONFIGURED
- : USB_STATE_ADDRESS;
+ usb_set_device_state(udev, udev->actconfig
+ ? USB_STATE_CONFIGURED
+ : USB_STATE_ADDRESS);
+ udev->dev.power.power_state = PM_SUSPEND_ON;
/* 10.5.4.5 says be sure devices in the tree are still there.
* For now let's assume the device didn't go crazy on resume,
@@ -1731,26 +1740,26 @@ static int finish_port_resume(struct usb_device *udev)
}
static int
-hub_port_resume(struct usb_device *hdev, int port)
+hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
{
- int status;
- struct usb_device *udev;
+ int status;
- udev = hdev->children[port];
- // dev_dbg(hubdev(hdev), "resume port %d\n", port + 1);
+ // dev_dbg(hub->intfdev, "resume port %d\n", port1);
/* see 7.1.7.7; affects power usage, but not budgeting */
- status = clear_port_feature(hdev, port + 1, USB_PORT_FEAT_SUSPEND);
+ status = clear_port_feature(hub->hdev,
+ port1, USB_PORT_FEAT_SUSPEND);
if (status) {
- dev_dbg(&hdev->actconfig->interface[0]->dev,
+ dev_dbg(hub->intfdev,
"can't resume port %d, status %d\n",
- port + 1, status);
+ port1, status);
} else {
u16 devstatus;
u16 portchange;
/* drive resume for at least 20 msec */
- dev_dbg(&udev->dev, "RESUME\n");
+ if (udev)
+ dev_dbg(&udev->dev, "RESUME\n");
msleep(25);
#define LIVE_FLAGS ( USB_PORT_STAT_POWER \
@@ -1762,23 +1771,24 @@ hub_port_resume(struct usb_device *hdev, int port)
* sequence.
*/
devstatus = portchange = 0;
- status = hub_port_status(hdev, port,
+ status = hub_port_status(hub, port1,
&devstatus, &portchange);
if (status < 0
|| (devstatus & LIVE_FLAGS) != LIVE_FLAGS
|| (devstatus & USB_PORT_STAT_SUSPEND) != 0
) {
- dev_dbg(&hdev->actconfig->interface[0]->dev,
+ dev_dbg(hub->intfdev,
"port %d status %04x.%04x after resume, %d\n",
- port + 1, portchange, devstatus, status);
+ port1, portchange, devstatus, status);
} else {
/* TRSMRCY = 10 msec */
msleep(10);
- status = finish_port_resume(udev);
+ if (udev)
+ status = finish_port_resume(udev);
}
}
if (status < 0)
- hub_port_logical_disconnect(hdev, port);
+ hub_port_logical_disconnect(hub, port1);
return status;
}
@@ -1800,11 +1810,11 @@ static int hub_resume (struct usb_interface *intf);
*/
int usb_resume_device(struct usb_device *udev)
{
- int port, status;
+ int port1, status;
- port = locktree(udev);
- if (port < 0)
- return port;
+ port1 = locktree(udev);
+ if (port1 < 0)
+ return port1;
/* "global resume" of the HC-to-USB interface (root hub), or
* selective resume of one hub-to-device port
@@ -1824,7 +1834,8 @@ int usb_resume_device(struct usb_device *udev)
}
} else if (udev->state == USB_STATE_SUSPENDED) {
// NOTE this fails if parent is also suspended...
- status = hub_port_resume(udev->parent, port);
+ status = hub_port_resume(hdev_to_hub(udev->parent),
+ port1, udev);
} else {
status = 0;
}
@@ -1866,25 +1877,25 @@ static int hub_suspend(struct usb_interface *intf, u32 state)
{
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
- unsigned port;
+ unsigned port1;
int status;
/* stop khubd and related activity */
hub_quiesce(hub);
/* then suspend every port */
- for (port = 0; port < hdev->maxchild; port++) {
+ for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev;
- udev = hdev->children [port];
+ udev = hdev->children [port1-1];
if (!udev)
continue;
down(&udev->serialize);
- status = __usb_suspend_device(udev, port, state);
+ status = __usb_suspend_device(udev, port1, state);
up(&udev->serialize);
if (status < 0)
dev_dbg(&intf->dev, "suspend port %d --> %d\n",
- port, status);
+ port1, status);
}
intf->dev.power.power_state = state;
@@ -1895,21 +1906,21 @@ static int hub_resume(struct usb_interface *intf)
{
struct usb_device *hdev = interface_to_usbdev(intf);
struct usb_hub *hub = usb_get_intfdata (intf);
- unsigned port;
+ unsigned port1;
int status;
if (intf->dev.power.power_state == PM_SUSPEND_ON)
return 0;
- for (port = 0; port < hdev->maxchild; port++) {
+ for (port1 = 1; port1 <= hdev->maxchild; port1++) {
struct usb_device *udev;
u16 portstat, portchange;
- udev = hdev->children [port];
- status = hub_port_status(hdev, port, &portstat, &portchange);
+ udev = hdev->children [port1-1];
+ status = hub_port_status(hub, port1, &portstat, &portchange);
if (status == 0) {
if (portchange & USB_PORT_STAT_C_SUSPEND) {
- clear_port_feature(hdev, port + 1,
+ clear_port_feature(hdev, port1,
USB_PORT_FEAT_C_SUSPEND);
portchange &= ~USB_PORT_STAT_C_SUSPEND;
}
@@ -1923,13 +1934,13 @@ static int hub_resume(struct usb_interface *intf)
continue;
down (&udev->serialize);
if (portstat & USB_PORT_STAT_SUSPEND)
- status = hub_port_resume(hdev, port);
+ status = hub_port_resume(hub, port1, udev);
else {
status = finish_port_resume(udev);
if (status < 0) {
dev_dbg(&intf->dev, "resume port %d --> %d\n",
- port + 1, status);
- hub_port_logical_disconnect(hdev, port);
+ port1, status);
+ hub_port_logical_disconnect(hub, port1);
}
}
up(&udev->serialize);
@@ -1983,7 +1994,7 @@ EXPORT_SYMBOL(usb_resume_device);
#define HUB_DEBOUNCE_STEP 25
#define HUB_DEBOUNCE_STABLE 100
-static int hub_port_debounce(struct usb_device *hdev, int port)
+static int hub_port_debounce(struct usb_hub *hub, int port1)
{
int ret;
int total_time, stable_time = 0;
@@ -1991,7 +2002,7 @@ static int hub_port_debounce(struct usb_device *hdev, int port)
unsigned connection = 0xffff;
for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
- ret = hub_port_status(hdev, port, &portstatus, &portchange);
+ ret = hub_port_status(hub, port1, &portstatus, &portchange);
if (ret < 0)
return ret;
@@ -2006,7 +2017,7 @@ static int hub_port_debounce(struct usb_device *hdev, int port)
}
if (portchange & USB_PORT_STAT_C_CONNECTION) {
- clear_port_feature(hdev, port+1,
+ clear_port_feature(hub->hdev, port1,
USB_PORT_FEAT_C_CONNECTION);
}
@@ -2015,15 +2026,22 @@ static int hub_port_debounce(struct usb_device *hdev, int port)
msleep(HUB_DEBOUNCE_STEP);
}
- dev_dbg (hubdev (hdev),
+ dev_dbg (hub->intfdev,
"debounce: port %d: total %dms stable %dms status 0x%x\n",
- port + 1, total_time, stable_time, portstatus);
+ port1, total_time, stable_time, portstatus);
if (stable_time < HUB_DEBOUNCE_STABLE)
return -ETIMEDOUT;
return portstatus;
}
+static void ep0_reinit(struct usb_device *udev)
+{
+ usb_disable_endpoint(udev, 0 + USB_DIR_IN);
+ usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
+ udev->ep_in[0] = udev->ep_out[0] = &udev->ep0;
+}
+
#define usb_sndaddr0pipe() (PIPE_CONTROL << 30)
#define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN)
@@ -2041,12 +2059,8 @@ static int hub_set_address(struct usb_device *udev)
USB_REQ_SET_ADDRESS, 0, udev->devnum, 0,
NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
if (retval == 0) {
- int m = udev->epmaxpacketin[0];
-
usb_set_device_state(udev, USB_STATE_ADDRESS);
- usb_disable_endpoint(udev, 0 + USB_DIR_IN);
- usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
- udev->epmaxpacketin[0] = udev->epmaxpacketout[0] = m;
+ ep0_reinit(udev);
}
return retval;
}
@@ -2061,11 +2075,12 @@ static int hub_set_address(struct usb_device *udev)
* pointers, it's not necessary to lock the device.
*/
static int
-hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
+hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
int retry_counter)
{
static DECLARE_MUTEX(usb_address0_sem);
+ struct usb_device *hdev = hub->hdev;
int i, j, retval;
unsigned delay = HUB_SHORT_RESET_TIME;
enum usb_device_speed oldspeed = udev->speed;
@@ -2075,7 +2090,7 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
*/
if (!hdev->parent) {
delay = HUB_ROOT_RESET_TIME;
- if (port + 1 == hdev->bus->otg_port)
+ if (port1 == hdev->bus->otg_port)
hdev->bus->b_hnp_enable = 0;
}
@@ -2087,7 +2102,7 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
down(&usb_address0_sem);
/* Reset the device; full speed may morph to high speed */
- retval = hub_port_reset(hdev, port, udev, delay);
+ retval = hub_port_reset(hub, port1, udev, delay);
if (retval < 0) /* error or disconnect */
goto fail;
/* success, speed is known */
@@ -2104,22 +2119,21 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
*/
switch (udev->speed) {
case USB_SPEED_HIGH: /* fixed at 64 */
- i = 64;
+ udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
break;
case USB_SPEED_FULL: /* 8, 16, 32, or 64 */
/* to determine the ep0 maxpacket size, try to read
* the device descriptor to get bMaxPacketSize0 and
* then correct our initial guess.
*/
- i = 64;
+ udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64);
break;
case USB_SPEED_LOW: /* fixed at 8 */
- i = 8;
+ udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8);
break;
default:
goto fail;
}
- udev->epmaxpacketin[0] = udev->epmaxpacketout[0] = i;
dev_info (&udev->dev,
"%s %s speed USB device using %s and address %d\n",
@@ -2139,11 +2153,8 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
udev->ttport = hdev->ttport;
} else if (udev->speed != USB_SPEED_HIGH
&& hdev->speed == USB_SPEED_HIGH) {
- struct usb_hub *hub;
-
- hub = usb_get_intfdata(hdev->actconfig->interface[0]);
udev->tt = &hub->tt;
- udev->ttport = port + 1;
+ udev->ttport = port1;
}
/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
@@ -2161,6 +2172,7 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
if (USE_NEW_SCHEME(retry_counter)) {
struct usb_device_descriptor *buf;
+ int r = 0;
#define GET_DESCRIPTOR_BUFSIZE 64
buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
@@ -2174,18 +2186,25 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
* so that recalcitrant full-speed devices with
* 8- or 16-byte ep0-maxpackets won't slow things
* down tremendously by NAKing the unexpectedly
- * early status stage.
+ * early status stage. Also, retry on length 0
+ * or stall; some devices are flakey.
*/
- j = usb_control_msg(udev, usb_rcvaddr0pipe(),
+ for (j = 0; j < 3; ++j) {
+ r = usb_control_msg(udev, usb_rcvaddr0pipe(),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
USB_DT_DEVICE << 8, 0,
buf, GET_DESCRIPTOR_BUFSIZE,
(i ? HZ * USB_CTRL_GET_TIMEOUT : HZ));
+ if (r == 0 || r == -EPIPE)
+ continue;
+ if (r < 0)
+ break;
+ }
udev->descriptor.bMaxPacketSize0 =
buf->bMaxPacketSize0;
kfree(buf);
- retval = hub_port_reset(hdev, port, udev, delay);
+ retval = hub_port_reset(hub, port1, udev, delay);
if (retval < 0) /* error or disconnect */
goto fail;
if (oldspeed != udev->speed) {
@@ -2194,10 +2213,13 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
retval = -ENODEV;
goto fail;
}
- if (udev->descriptor.bMaxPacketSize0 == 0) {
+ switch (udev->descriptor.bMaxPacketSize0) {
+ case 64: case 32: case 16: case 8:
+ break;
+ default:
dev_err(&udev->dev, "device descriptor "
"read/%s, error %d\n",
- "64", j);
+ "64", r);
retval = -EMSGSIZE;
continue;
}
@@ -2240,13 +2262,17 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
if (retval)
goto fail;
- /* Should we verify that the value is valid? */
i = udev->descriptor.bMaxPacketSize0;
- if (udev->epmaxpacketin[0] != i) {
+ if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) {
+ if (udev->speed != USB_SPEED_FULL ||
+ !(i == 8 || i == 16 || i == 32 || i == 64)) {
+ dev_err(&udev->dev, "ep0 maxpacket = %d\n", i);
+ retval = -EMSGSIZE;
+ goto fail;
+ }
dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
- usb_disable_endpoint(udev, 0 + USB_DIR_IN);
- usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
- udev->epmaxpacketin[0] = udev->epmaxpacketout[0] = i;
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
+ ep0_reinit(udev);
}
retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
@@ -2261,12 +2287,14 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port,
retval = 0;
fail:
+ if (retval)
+ hub_port_disable(hub, port1, 0);
up(&usb_address0_sem);
return retval;
}
static void
-check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port)
+check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1)
{
struct usb_qualifier_descriptor *qual;
int status;
@@ -2282,7 +2310,7 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port)
"connect to a high speed hub\n");
/* hub LEDs are probably harder to miss than syslog */
if (hub->has_indicators) {
- hub->indicator[port] = INDICATOR_GREEN_BLINK;
+ hub->indicator[port1-1] = INDICATOR_GREEN_BLINK;
schedule_work (&hub->leds);
}
}
@@ -2324,7 +2352,7 @@ hub_power_remaining (struct usb_hub *hub)
remaining -= delta;
}
if (remaining < 0) {
- dev_warn(&hub->intf->dev,
+ dev_warn(hub->intfdev,
"%dmA over power budget!\n",
-2 * remaining);
remaining = 0;
@@ -2340,26 +2368,26 @@ hub_power_remaining (struct usb_hub *hub)
* a firmware download)
* caller already locked the hub
*/
-static void hub_port_connect_change(struct usb_hub *hub, int port,
+static void hub_port_connect_change(struct usb_hub *hub, int port1,
u16 portstatus, u16 portchange)
{
struct usb_device *hdev = hub->hdev;
- struct device *hub_dev = &hub->intf->dev;
+ struct device *hub_dev = hub->intfdev;
int status, i;
dev_dbg (hub_dev,
"port %d, status %04x, change %04x, %s\n",
- port + 1, portstatus, portchange, portspeed (portstatus));
+ port1, portstatus, portchange, portspeed (portstatus));
if (hub->has_indicators) {
- set_port_led(hdev, port + 1, HUB_LED_AUTO);
- hub->indicator[port] = INDICATOR_AUTO;
+ set_port_led(hub, port1, HUB_LED_AUTO);
+ hub->indicator[port1-1] = INDICATOR_AUTO;
}
/* Disconnect any existing devices under this port */
- if (hdev->children[port])
- usb_disconnect(&hdev->children[port]);
- clear_bit(port, hub->change_bits);
+ if (hdev->children[port1-1])
+ usb_disconnect(&hdev->children[port1-1]);
+ clear_bit(port1, hub->change_bits);
#ifdef CONFIG_USB_OTG
/* during HNP, don't repeat the debounce */
@@ -2368,11 +2396,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
#endif
if (portchange & USB_PORT_STAT_C_CONNECTION) {
- status = hub_port_debounce(hdev, port);
+ status = hub_port_debounce(hub, port1);
if (status < 0) {
dev_err (hub_dev,
"connect-debounce failed, port %d disabled\n",
- port+1);
+ port1);
goto done;
}
portstatus = status;
@@ -2385,7 +2413,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
if ((hub->descriptor->wHubCharacteristics
& HUB_CHAR_LPSM) < 2
&& !(portstatus & (1 << USB_PORT_FEAT_POWER)))
- set_port_feature(hdev, port + 1, USB_PORT_FEAT_POWER);
+ set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
if (portstatus & USB_PORT_STAT_ENABLE)
goto done;
@@ -2393,11 +2421,15 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
}
#ifdef CONFIG_USB_SUSPEND
- /* If something is connected, but the port is suspended, wake it up.. */
+ /* If something is connected, but the port is suspended, wake it up. */
if (portstatus & USB_PORT_STAT_SUSPEND) {
- status = hub_port_resume(hdev, port);
- if (status < 0)
- dev_dbg(hub_dev, "can't clear suspend on port %d; %d\n", port+1, status);
+ status = hub_port_resume(hub, port1, NULL);
+ if (status < 0) {
+ dev_dbg(hub_dev,
+ "can't clear suspend on port %d; %d\n",
+ port1, status);
+ goto done;
+ }
}
#endif
@@ -2407,10 +2439,11 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
/* reallocate for each attempt, since references
* to the previous one can escape in various ways
*/
- udev = usb_alloc_dev(hdev, hdev->bus, port);
+ udev = usb_alloc_dev(hdev, hdev->bus, port1);
if (!udev) {
dev_err (hub_dev,
- "couldn't allocate port %d usb_device\n", port+1);
+ "couldn't allocate port %d usb_device\n",
+ port1);
goto done;
}
@@ -2425,7 +2458,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
}
/* reset and get descriptor */
- status = hub_port_init(hdev, udev, port, i);
+ status = hub_port_init(hub, udev, port1, i);
if (status < 0)
goto loop;
@@ -2443,7 +2476,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
&devstat);
if (status < 0) {
dev_dbg(&udev->dev, "get status %d ?\n", status);
- goto loop;
+ goto loop_disable;
}
cpu_to_le16s(&devstat);
if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) {
@@ -2451,20 +2484,20 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
"can't connect bus-powered hub "
"to this port\n");
if (hub->has_indicators) {
- hub->indicator[port] =
+ hub->indicator[port1-1] =
INDICATOR_AMBER_BLINK;
schedule_work (&hub->leds);
}
status = -ENOTCONN; /* Don't retry */
- goto loop;
+ goto loop_disable;
}
}
/* check for devices running slower than they could */
- if (udev->descriptor.bcdUSB >= 0x0200
+ if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200
&& udev->speed == USB_SPEED_FULL
&& highspeed_hubs != 0)
- check_highspeed (hub, udev, port);
+ check_highspeed (hub, udev, port1);
/* Store the parent's children[] pointer. At this point
* udev becomes globally accessible, although presumably
@@ -2481,7 +2514,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
if (hdev->state == USB_STATE_NOTATTACHED)
status = -ENOTCONN;
else
- hdev->children[port] = udev;
+ hdev->children[port1-1] = udev;
spin_unlock_irq(&device_state_lock);
/* Run it through the hoops (find a driver, etc) */
@@ -2489,14 +2522,14 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
status = usb_new_device(udev);
if (status) {
spin_lock_irq(&device_state_lock);
- hdev->children[port] = NULL;
+ hdev->children[port1-1] = NULL;
spin_unlock_irq(&device_state_lock);
}
}
up (&udev->serialize);
if (status)
- goto loop;
+ goto loop_disable;
status = hub_power_remaining(hub);
if (status)
@@ -2506,10 +2539,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
return;
+loop_disable:
+ hub_port_disable(hub, port1, 1);
loop:
- hub_port_disable(hdev, port);
- usb_disable_endpoint(udev, 0 + USB_DIR_IN);
- usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
+ ep0_reinit(udev);
release_address(udev);
usb_put_dev(udev);
if (status == -ENOTCONN)
@@ -2517,13 +2550,14 @@ loop:
}
done:
- hub_port_disable(hdev, port);
+ hub_port_disable(hub, port1, 1);
}
static void hub_events(void)
{
struct list_head *tmp;
struct usb_device *hdev;
+ struct usb_interface *intf;
struct usb_hub *hub;
struct device *hub_dev;
u16 hubstatus;
@@ -2553,10 +2587,8 @@ static void hub_events(void)
hub = list_entry(tmp, struct usb_hub, event_list);
hdev = hub->hdev;
- hub_dev = &hub->intf->dev;
-
- usb_get_dev(hdev);
- spin_unlock_irq(&hub_event_lock);
+ intf = to_usb_interface(hub->intfdev);
+ hub_dev = &intf->dev;
dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
hdev->state, hub->descriptor
@@ -2566,14 +2598,16 @@ static void hub_events(void)
(u16) hub->change_bits[0],
(u16) hub->event_bits[0]);
+ usb_get_intf(intf);
+ spin_unlock_irq(&hub_event_lock);
+
/* Lock the device, then check to see if we were
* disconnected while waiting for the lock to succeed. */
- if (locktree(hdev) < 0)
- break;
- if (hdev->state != USB_STATE_CONFIGURED ||
- !hdev->actconfig ||
- hub != usb_get_intfdata(
- hdev->actconfig->interface[0]))
+ if (locktree(hdev) < 0) {
+ usb_put_intf(intf);
+ continue;
+ }
+ if (hub != usb_get_intfdata(intf) || hub->quiescing)
goto loop;
if (hub->error) {
@@ -2592,20 +2626,20 @@ static void hub_events(void)
}
/* deal with port status changes */
- for (i = 0; i < hub->descriptor->bNbrPorts; i++) {
+ for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
connect_change = test_bit(i, hub->change_bits);
- if (!test_and_clear_bit(i+1, hub->event_bits) &&
+ if (!test_and_clear_bit(i, hub->event_bits) &&
!connect_change)
continue;
- ret = hub_port_status(hdev, i,
+ ret = hub_port_status(hub, i,
&portstatus, &portchange);
if (ret < 0)
continue;
if (portchange & USB_PORT_STAT_C_CONNECTION) {
- clear_port_feature(hdev,
- i + 1, USB_PORT_FEAT_C_CONNECTION);
+ clear_port_feature(hdev, i,
+ USB_PORT_FEAT_C_CONNECTION);
connect_change = 1;
}
@@ -2614,9 +2648,9 @@ static void hub_events(void)
dev_dbg (hub_dev,
"port %d enable change, "
"status %08x\n",
- i + 1, portstatus);
- clear_port_feature(hdev,
- i + 1, USB_PORT_FEAT_C_ENABLE);
+ i, portstatus);
+ clear_port_feature(hdev, i,
+ USB_PORT_FEAT_C_ENABLE);
/*
* EM interference sometimes causes badly
@@ -2626,47 +2660,48 @@ static void hub_events(void)
*/
if (!(portstatus & USB_PORT_STAT_ENABLE)
&& !connect_change
- && hdev->children[i]) {
+ && hdev->children[i-1]) {
dev_err (hub_dev,
"port %i "
"disabled by hub (EMI?), "
"re-enabling...\n",
- i + 1);
+ i);
connect_change = 1;
}
}
if (portchange & USB_PORT_STAT_C_SUSPEND) {
- clear_port_feature(hdev, i + 1,
+ clear_port_feature(hdev, i,
USB_PORT_FEAT_C_SUSPEND);
- if (hdev->children[i]) {
- ret = remote_wakeup(hdev->children[i]);
+ if (hdev->children[i-1]) {
+ ret = remote_wakeup(hdev->
+ children[i-1]);
if (ret < 0)
connect_change = 1;
} else {
ret = -ENODEV;
- hub_port_disable(hdev, i);
+ hub_port_disable(hub, i, 1);
}
dev_dbg (hub_dev,
"resume on port %d, status %d\n",
- i + 1, ret);
+ i, ret);
}
if (portchange & USB_PORT_STAT_C_OVERCURRENT) {
dev_err (hub_dev,
"over-current change on port %d\n",
- i + 1);
- clear_port_feature(hdev,
- i + 1, USB_PORT_FEAT_C_OVER_CURRENT);
+ i);
+ clear_port_feature(hdev, i,
+ USB_PORT_FEAT_C_OVER_CURRENT);
hub_power_on(hub);
}
if (portchange & USB_PORT_STAT_C_RESET) {
dev_dbg (hub_dev,
"reset change on port %d\n",
- i + 1);
- clear_port_feature(hdev,
- i + 1, USB_PORT_FEAT_C_RESET);
+ i);
+ clear_port_feature(hdev, i,
+ USB_PORT_FEAT_C_RESET);
}
if (connect_change)
@@ -2694,7 +2729,7 @@ static void hub_events(void)
loop:
usb_unlock_device(hdev);
- usb_put_dev(hdev);
+ usb_put_intf(intf);
} /* end while (1) */
}
@@ -2793,8 +2828,8 @@ static int config_descriptors_changed(struct usb_device *udev)
struct usb_config_descriptor *buf;
for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
- if (len < udev->config[index].desc.wTotalLength)
- len = udev->config[index].desc.wTotalLength;
+ if (len < le16_to_cpu(udev->config[index].desc.wTotalLength))
+ len = le16_to_cpu(udev->config[index].desc.wTotalLength);
}
buf = kmalloc (len, SLAB_KERNEL);
if (buf == 0) {
@@ -2804,7 +2839,7 @@ static int config_descriptors_changed(struct usb_device *udev)
}
for (index = 0; index < udev->descriptor.bNumConfigurations; index++) {
int length;
- int old_length = udev->config[index].desc.wTotalLength;
+ int old_length = le16_to_cpu(udev->config[index].desc.wTotalLength);
length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf,
old_length);
@@ -2851,10 +2886,11 @@ static int config_descriptors_changed(struct usb_device *udev)
*/
int usb_reset_device(struct usb_device *udev)
{
- struct usb_device *parent = udev->parent;
- struct usb_device_descriptor descriptor = udev->descriptor;
- int i, ret = 0, port = -1;
- int udev_is_a_hub = 0;
+ struct usb_device *parent_hdev = udev->parent;
+ struct usb_hub *parent_hub;
+ struct usb_device_descriptor descriptor = udev->descriptor;
+ struct usb_hub *hub = NULL;
+ int i, ret = 0, port1 = -1;
if (udev->state == USB_STATE_NOTATTACHED ||
udev->state == USB_STATE_SUSPENDED) {
@@ -2863,39 +2899,39 @@ int usb_reset_device(struct usb_device *udev)
return -EINVAL;
}
- if (!parent) {
+ if (!parent_hdev) {
/* this requires hcd-specific logic; see OHCI hc_restart() */
dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__);
return -EISDIR;
}
- for (i = 0; i < parent->maxchild; i++)
- if (parent->children[i] == udev) {
- port = i;
+ for (i = 0; i < parent_hdev->maxchild; i++)
+ if (parent_hdev->children[i] == udev) {
+ port1 = i + 1;
break;
}
- if (port < 0) {
+ if (port1 < 0) {
/* If this ever happens, it's very bad */
dev_err(&udev->dev, "Can't locate device's port!\n");
return -ENOENT;
}
+ parent_hub = hdev_to_hub(parent_hdev);
/* If we're resetting an active hub, take some special actions */
if (udev->actconfig &&
udev->actconfig->interface[0]->dev.driver ==
- &hub_driver.driver) {
- udev_is_a_hub = 1;
- hub_pre_reset(udev);
+ &hub_driver.driver &&
+ (hub = hdev_to_hub(udev)) != NULL) {
+ hub_pre_reset(hub);
}
for (i = 0; i < SET_CONFIG_TRIES; ++i) {
/* ep0 maxpacket size may change; let the HCD know about it.
* Other endpoints will be handled by re-enumeration. */
- usb_disable_endpoint(udev, 0 + USB_DIR_IN);
- usb_disable_endpoint(udev, 0 + USB_DIR_OUT);
- ret = hub_port_init(parent, udev, port, i);
+ ep0_reinit(udev);
+ ret = hub_port_init(parent_hub, udev, port1, i);
if (ret >= 0)
break;
}
@@ -2946,11 +2982,11 @@ int usb_reset_device(struct usb_device *udev)
}
done:
- if (udev_is_a_hub)
- hub_post_reset(udev);
+ if (hub)
+ hub_post_reset(hub);
return 0;
re_enumerate:
- hub_port_logical_disconnect(parent, port);
+ hub_port_logical_disconnect(parent_hub, port1);
return -ENODEV;
}
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 7ace2d24dff176..b8f8a1159007df 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -186,7 +186,7 @@ struct usb_tt_clear {
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
struct usb_hub {
- struct usb_interface *intf; /* the "real" device */
+ struct device *intfdev; /* the "interface" device */
struct usb_device *hdev;
struct urb *urb; /* for interrupt polling pipe */
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index da1c5a86d2a9c3..d913407bcdc1e3 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -696,7 +696,7 @@ void usbfs_add_device(struct usb_device *dev)
for (i = 0; i < dev->descriptor.bNumConfigurations; ++i) {
struct usb_config_descriptor *config =
(struct usb_config_descriptor *)dev->rawdescriptors[i];
- i_size += le16_to_cpu ((__force __le16)config->wTotalLength);
+ i_size += le16_to_cpu(config->wTotalLength);
}
if (dev->usbfs_dentry->d_inode)
dev->usbfs_dentry->d_inode->i_size = i_size;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index d7d784e18c9b3d..caa9845661536d 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -796,13 +796,8 @@ int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
return -ENOMEM;
ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
- if (ret >= 0) {
- le16_to_cpus(&desc->bcdUSB);
- le16_to_cpus(&desc->idVendor);
- le16_to_cpus(&desc->idProduct);
- le16_to_cpus(&desc->bcdDevice);
+ if (ret >= 0)
memcpy(&dev->descriptor, desc, size);
- }
kfree(desc);
return ret;
}
@@ -918,16 +913,21 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
*/
void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
{
- if (dev && dev->bus && dev->bus->op && dev->bus->op->disable)
- dev->bus->op->disable(dev, epaddr);
- else {
- unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
+ unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
+ struct usb_host_endpoint *ep;
- if (usb_endpoint_out(epaddr))
- dev->epmaxpacketout[epnum] = 0;
- else
- dev->epmaxpacketin[epnum] = 0;
+ if (!dev)
+ return;
+
+ if (usb_endpoint_out(epaddr)) {
+ ep = dev->ep_out[epnum];
+ dev->ep_out[epnum] = NULL;
+ } else {
+ ep = dev->ep_in[epnum];
+ dev->ep_in[epnum] = NULL;
}
+ if (ep && dev->bus && dev->bus->op && dev->bus->op->disable)
+ dev->bus->op->disable(dev, ep);
}
/**
@@ -1002,27 +1002,27 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
/*
* usb_enable_endpoint - Enable an endpoint for USB communications
* @dev: the device whose interface is being enabled
- * @epd: pointer to the endpoint descriptor
+ * @ep: the endpoint
*
- * Resets the endpoint toggle and stores its maxpacket value.
+ * Resets the endpoint toggle, and sets dev->ep_{in,out} pointers.
* For control endpoints, both the input and output sides are handled.
*/
-void usb_enable_endpoint(struct usb_device *dev,
- struct usb_endpoint_descriptor *epd)
+static void
+usb_enable_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
{
- int maxsize = epd->wMaxPacketSize;
- unsigned int epaddr = epd->bEndpointAddress;
+ unsigned int epaddr = ep->desc.bEndpointAddress;
unsigned int epnum = epaddr & USB_ENDPOINT_NUMBER_MASK;
- int is_control = ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_CONTROL);
+ int is_control;
+ is_control = ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+ == USB_ENDPOINT_XFER_CONTROL);
if (usb_endpoint_out(epaddr) || is_control) {
usb_settoggle(dev, epnum, 1, 0);
- dev->epmaxpacketout[epnum] = maxsize;
+ dev->ep_out[epnum] = ep;
}
if (!usb_endpoint_out(epaddr) || is_control) {
usb_settoggle(dev, epnum, 0, 0);
- dev->epmaxpacketin[epnum] = maxsize;
+ dev->ep_in[epnum] = ep;
}
}
@@ -1040,7 +1040,7 @@ void usb_enable_interface(struct usb_device *dev,
int i;
for (i = 0; i < alt->desc.bNumEndpoints; ++i)
- usb_enable_endpoint(dev, &alt->endpoint[i].desc);
+ usb_enable_endpoint(dev, &alt->endpoint[i]);
}
/**
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index 8bf4e811112fed..627a5a2fc9cf34 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -55,8 +55,8 @@ static int is_targeted(struct usb_device *dev)
return 1;
/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
- if (dev->descriptor.idVendor == 0x1a0a
- && dev->descriptor.idProduct == 0xbadd)
+ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1a0a &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0xbadd))
return 0;
/* NOTE: can't use usb_match_id() since interface caches
@@ -64,21 +64,21 @@ static int is_targeted(struct usb_device *dev)
*/
for (id = whitelist_table; id->match_flags; id++) {
if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
- id->idVendor != dev->descriptor.idVendor)
+ id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
- id->idProduct != dev->descriptor.idProduct)
+ id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
continue;
/* No need to test id->bcdDevice_lo != 0, since 0 is never
greater than any unsigned number. */
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
- (id->bcdDevice_lo > dev->descriptor.bcdDevice))
+ (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
- (id->bcdDevice_hi < dev->descriptor.bcdDevice))
+ (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
@@ -101,8 +101,8 @@ static int is_targeted(struct usb_device *dev)
/* OTG MESSAGE: report errors here, customize to match your product */
dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
- dev->descriptor.idVendor,
- dev->descriptor.idProduct);
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
#ifdef CONFIG_USB_OTG_WHITELIST
return 0;
#else
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index bae974d587aedc..ce71f7af74784a 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -149,10 +149,11 @@ static ssize_t
show_version (struct device *dev, char *buf)
{
struct usb_device *udev;
+ u16 bcdUSB;
- udev = to_usb_device (dev);
- return sprintf (buf, "%2x.%02x\n", udev->descriptor.bcdUSB >> 8,
- udev->descriptor.bcdUSB & 0xff);
+ udev = to_usb_device(dev);
+ bcdUSB = le16_to_cpu(udev->descriptor.bcdUSB);
+ return sprintf(buf, "%2x.%02x\n", bcdUSB >> 8, bcdUSB & 0xff);
}
static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
@@ -167,6 +168,22 @@ show_maxchild (struct device *dev, char *buf)
static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
/* Descriptor fields */
+#define usb_descriptor_attr_le16(field, format_string) \
+static ssize_t \
+show_##field (struct device *dev, char *buf) \
+{ \
+ struct usb_device *udev; \
+ \
+ udev = to_usb_device (dev); \
+ return sprintf (buf, format_string, \
+ le16_to_cpu(udev->descriptor.field)); \
+} \
+static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
+
+usb_descriptor_attr_le16(idVendor, "%04x\n")
+usb_descriptor_attr_le16(idProduct, "%04x\n")
+usb_descriptor_attr_le16(bcdDevice, "%04x\n")
+
#define usb_descriptor_attr(field, format_string) \
static ssize_t \
show_##field (struct device *dev, char *buf) \
@@ -178,9 +195,6 @@ show_##field (struct device *dev, char *buf) \
} \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
-usb_descriptor_attr (idVendor, "%04x\n")
-usb_descriptor_attr (idProduct, "%04x\n")
-usb_descriptor_attr (bcdDevice, "%04x\n")
usb_descriptor_attr (bDeviceClass, "%02x\n")
usb_descriptor_attr (bDeviceSubClass, "%02x\n")
usb_descriptor_attr (bDeviceProtocol, "%02x\n")
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 29367e626d2721..dc838f81742cb1 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -265,7 +265,7 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
max = usb_maxpacket (dev, pipe, is_out);
if (max <= 0) {
dev_dbg(&dev->dev,
- "bogus endpoint ep%d%s in %s (bad maxpacket %d)",
+ "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n",
usb_pipeendpoint (pipe), is_out ? "out" : "in",
__FUNCTION__, max);
return -EMSGSIZE;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 00f6caf6d9839b..c0fb59274a4a18 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -267,44 +267,6 @@ struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,
}
/**
- * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number
- * @dev: the device whose current configuration+altsettings is considered
- * @epnum: the desired endpoint, masked with USB_DIR_IN as appropriate.
- *
- * This walks the device descriptor for the currently active configuration,
- * and returns a pointer to the endpoint with that particular endpoint
- * number, or null.
- *
- * Note that interface descriptors are not required to list endpoint
- * numbers in any standardized order, so that it would be wrong to
- * assume that ep2in precedes either ep5in, ep2out, or even ep1out.
- * This routine helps device drivers avoid such mistakes.
- */
-struct usb_endpoint_descriptor *
-usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum)
-{
- struct usb_host_config *config = dev->actconfig;
- int i, k;
-
- if (!config)
- return NULL;
- for (i = 0; i < config->desc.bNumInterfaces; i++) {
- struct usb_interface *intf;
- struct usb_host_interface *alt;
-
- /* only endpoints in current altsetting are active */
- intf = config->interface[i];
- alt = intf->cur_altsetting;
-
- for (k = 0; k < alt->desc.bNumEndpoints; k++)
- if (epnum == alt->endpoint[k].desc.bEndpointAddress)
- return &alt->endpoint[k].desc;
- }
-
- return NULL;
-}
-
-/**
* usb_driver_claim_interface - bind a driver to an interface
* @driver: the driver to be bound
* @iface: the interface to which it will be bound; must be in the
@@ -461,21 +423,21 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
id->driver_info; id++) {
if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
- id->idVendor != dev->descriptor.idVendor)
+ id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
- id->idProduct != dev->descriptor.idProduct)
+ id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
continue;
/* No need to test id->bcdDevice_lo != 0, since 0 is never
greater than any unsigned number. */
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
- (id->bcdDevice_lo > dev->descriptor.bcdDevice))
+ (id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
- (id->bcdDevice_hi < dev->descriptor.bcdDevice))
+ (id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
@@ -626,9 +588,9 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
if (add_hotplug_env_var(envp, num_envp, &i,
buffer, buffer_size, &length,
"PRODUCT=%x/%x/%x",
- usb_dev->descriptor.idVendor,
- usb_dev->descriptor.idProduct,
- usb_dev->descriptor.bcdDevice))
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ le16_to_cpu(usb_dev->descriptor.bcdDevice)))
return -ENOMEM;
/* class-based driver binding models */
@@ -684,8 +646,6 @@ static void usb_release_dev(struct device *dev)
udev = to_usb_device(dev);
- if (udev->bus && udev->bus->op && udev->bus->op->deallocate)
- udev->bus->op->deallocate(udev);
usb_destroy_configuration(udev);
usb_bus_put(udev->bus);
kfree (udev);
@@ -695,7 +655,7 @@ static void usb_release_dev(struct device *dev)
* usb_alloc_dev - usb device constructor (usbcore-internal)
* @parent: hub to which device is connected; null to allocate a root hub
* @bus: bus used to access the device
- * @port: zero based index of port; ignored for root hubs
+ * @port1: one-based index of port; ignored for root hubs
* Context: !in_interrupt ()
*
* Only hub drivers (including virtual root hub drivers for host
@@ -704,7 +664,7 @@ static void usb_release_dev(struct device *dev)
* This call may not be used in a non-sleeping context.
*/
struct usb_device *
-usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port)
+usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
{
struct usb_device *dev;
@@ -728,6 +688,12 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port)
dev->dev.release = usb_release_dev;
dev->state = USB_STATE_ATTACHED;
+ INIT_LIST_HEAD(&dev->ep0.urb_list);
+ dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
+ dev->ep0.desc.bDescriptorType = USB_DT_ENDPOINT;
+ /* ep0 maxpacket comes later, from device descriptor */
+ dev->ep_in[0] = dev->ep_out[0] = &dev->ep0;
+
/* Save readable and stable topology id, distinguishing devices
* by location for diagnostics, tools, driver model, etc. The
* string is a path along hub ports, from the root. Each device's
@@ -745,10 +711,10 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port)
/* match any labeling on the hubs; it's one-based */
if (parent->devpath [0] == '0')
snprintf (dev->devpath, sizeof dev->devpath,
- "%d", port + 1);
+ "%d", port1);
else
snprintf (dev->devpath, sizeof dev->devpath,
- "%s.%d", parent->devpath, port + 1);
+ "%s.%d", parent->devpath, port1);
dev->dev.parent = &parent->dev;
sprintf (&dev->dev.bus_id[0], "%d-%s",
@@ -763,13 +729,6 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port)
init_MUTEX(&dev->serialize);
- if (dev->bus->op->allocate)
- if (dev->bus->op->allocate(dev)) {
- usb_bus_put(bus);
- kfree(dev);
- return NULL;
- }
-
return dev;
}
@@ -1000,12 +959,12 @@ static struct usb_device *match_device(struct usb_device *dev,
int child;
dev_dbg(&dev->dev, "check for vendor %04x, product %04x ...\n",
- dev->descriptor.idVendor,
- dev->descriptor.idProduct);
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
/* see if this device matches */
- if ((dev->descriptor.idVendor == vendor_id) &&
- (dev->descriptor.idProduct == product_id)) {
+ if ((vendor_id == le16_to_cpu(dev->descriptor.idVendor)) &&
+ (product_id == le16_to_cpu(dev->descriptor.idProduct))) {
dev_dbg (&dev->dev, "matched this device!\n");
ret_dev = usb_get_dev(dev);
goto exit;
@@ -1533,7 +1492,6 @@ module_exit(usb_exit);
* These symbols are exported for device (or host controller)
* driver modules to use.
*/
-EXPORT_SYMBOL(usb_epnum_to_ep_desc);
EXPORT_SYMBOL(usb_register);
EXPORT_SYMBOL(usb_deregister);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 4035ff925c9953..5b95a53babdd4b 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -13,8 +13,6 @@ extern void usb_disable_interface (struct usb_device *dev,
extern void usb_release_interface_cache(struct kref *ref);
extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
-extern void usb_enable_endpoint (struct usb_device *dev,
- struct usb_endpoint_descriptor *epd);
extern void usb_enable_interface (struct usb_device *dev,
struct usb_interface *intf);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index c6e0693ed1d6b4..fa34e8a13b6146 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -39,6 +39,9 @@ config USB_GADGET
If in doubt, say "N" and don't enable these drivers; most people
don't have this kind of hardware (except maybe inside Linux PDAs).
+ For more information, see <http://www.linux-usb.org/gadget> and
+ the kernel DocBook documentation for this API.
+
config USB_GADGET_DEBUG_FILES
boolean "Debugging information files"
depends on USB_GADGET && PROC_FS
@@ -59,6 +62,8 @@ choice
help
A USB device uses a controller to talk to its host.
Systems should have only one such upstream link.
+ Many controller drivers are platform-specific; these
+ often need board-specific hooks.
config USB_GADGET_NET2280
boolean "NetChip 2280"
@@ -234,6 +239,21 @@ choice
tristate "USB Gadget Drivers"
depends on USB_GADGET
default USB_ETH
+ help
+ A Linux "Gadget Driver" talks to the USB Peripheral Controller
+ driver through the abstract "gadget" API. Some other operating
+ systems call these "client" drivers, of which "class drivers"
+ are a subset (implementing a USB device class specification).
+ A gadget driver implements one or more USB functions using
+ the peripheral hardware.
+
+ Gadget drivers are hardware-neutral, or "platform independent",
+ except that they sometimes must understand quirks or limitations
+ of the particular controllers they work with. For example, when
+ a controller doesn't support alternate configurations or provide
+ enough of the right types of endpoints, the gadget driver might
+ not be able work with that controller, or might need to implement
+ a less common variant of a device class protocol.
# this first set of drivers all depend on bulk-capable hardware.
@@ -273,7 +293,7 @@ config USB_ZERO_HNPTEST
one serve as the USB host instead (in the "B-Host" role).
config USB_ETH
- tristate "Ethernet Gadget"
+ tristate "Ethernet Gadget (with CDC Ethernet support)"
depends on NET
help
This driver implements Ethernet style communication, in either
@@ -314,6 +334,11 @@ config USB_ETH_RNDIS
If you say "y" here, the Ethernet gadget driver will try to provide
a second device configuration, supporting RNDIS to talk to such
Microsoft USB hosts.
+
+ To make MS-Windows work with this, use Documentation/usb/linux.inf
+ as the "driver info file". For versions of MS-Windows older than
+ XP, you'll need to download drivers from Microsoft's website; a URL
+ is given in comments found in that info file.
config USB_GADGETFS
tristate "Gadget Filesystem (EXPERIMENTAL)"
@@ -352,13 +377,19 @@ config USB_FILE_STORAGE_TEST
normal operation.
config USB_G_SERIAL
- tristate "Serial Gadget"
+ tristate "Serial Gadget (with CDC ACM support)"
help
The Serial Gadget talks to the Linux-USB generic serial driver.
+ This driver supports a CDC-ACM module option, which can be used
+ to interoperate with MS-Windows hosts or with the Linux-USB
+ "cdc-acm" driver.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_serial".
+ For more information, see Documentation/usb/gadget_serial.txt
+ which includes instructions and a "driver info file" needed to
+ make MS-Windows work with this driver.
# put drivers that need isochronous transfer support (for audio
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index c283dbf3e2e2ac..702de0302795f7 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -65,7 +65,7 @@
#define DRIVER_DESC "USB Host+Gadget Emulator"
-#define DRIVER_VERSION "29 Oct 2004"
+#define DRIVER_VERSION "17 Dec 2004"
static const char driver_name [] = "dummy_hcd";
static const char driver_desc [] = "USB Host+Gadget Emulator";
@@ -143,8 +143,12 @@ static const char *const ep_name [] = {
#define FIFO_SIZE 64
+struct urbp {
+ struct urb *urb;
+ struct list_head urbp_list;
+};
+
struct dummy {
- struct usb_hcd hcd; /* must come first! */
spinlock_t lock;
/*
@@ -168,16 +172,22 @@ struct dummy {
unsigned long re_timeout;
struct usb_device *udev;
+ struct list_head urbp_list;
};
static inline struct dummy *hcd_to_dummy (struct usb_hcd *hcd)
{
- return container_of(hcd, struct dummy, hcd);
+ return (struct dummy *) (hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *dummy_to_hcd (struct dummy *dum)
+{
+ return container_of((void *) dum, struct usb_hcd, hcd_priv);
}
static inline struct device *dummy_dev (struct dummy *dum)
{
- return dum->hcd.self.controller;
+ return dummy_to_hcd(dum)->self.controller;
}
static inline struct dummy *ep_to_dummy (struct dummy_ep *ep)
@@ -237,7 +247,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
dum = ep_to_dummy (ep);
if (!dum->driver || !is_enabled (dum))
return -ESHUTDOWN;
- max = desc->wMaxPacketSize & 0x3ff;
+ max = le16_to_cpu(desc->wMaxPacketSize) & 0x3ff;
/* drivers must not request bad settings, since lower levels
* (hardware or its drivers) may not check. some endpoints
@@ -365,7 +375,7 @@ static int dummy_disable (struct usb_ep *_ep)
dum = ep_to_dummy (ep);
spin_lock_irqsave (&dum->lock, flags);
- ep->desc = 0;
+ ep->desc = NULL;
retval = 0;
nuke (dum, ep);
spin_unlock_irqrestore (&dum->lock, flags);
@@ -381,12 +391,12 @@ dummy_alloc_request (struct usb_ep *_ep, int mem_flags)
struct dummy_request *req;
if (!_ep)
- return 0;
+ return NULL;
ep = usb_ep_to_dummy_ep (_ep);
req = kmalloc (sizeof *req, mem_flags);
if (!req)
- return 0;
+ return NULL;
memset (req, 0, sizeof *req);
INIT_LIST_HEAD (&req->queue);
return &req->req;
@@ -422,7 +432,7 @@ dummy_alloc_buffer (
dum = ep_to_dummy (ep);
if (!dum->driver)
- return 0;
+ return NULL;
retval = kmalloc (bytes, mem_flags);
*dma = (dma_addr_t) retval;
return retval;
@@ -506,7 +516,7 @@ static int dummy_dequeue (struct usb_ep *_ep, struct usb_request *_req)
struct dummy *dum;
int retval = -EINVAL;
unsigned long flags;
- struct dummy_request *req = 0;
+ struct dummy_request *req = NULL;
if (!_ep || !_req)
return retval;
@@ -720,7 +730,7 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
ep->ep.maxpacket = ~0;
ep->last_io = jiffies;
ep->gadget = &dum->gadget;
- ep->desc = 0;
+ ep->desc = NULL;
INIT_LIST_HEAD (&ep->queue);
}
@@ -734,8 +744,8 @@ usb_gadget_register_driver (struct usb_gadget_driver *driver)
dev_dbg (dummy_dev(dum), "binding gadget driver '%s'\n",
driver->driver.name);
if ((retval = driver->bind (&dum->gadget)) != 0) {
- dum->driver = 0;
- dum->gadget.dev.driver = 0;
+ dum->driver = NULL;
+ dum->gadget.dev.driver = NULL;
return retval;
}
@@ -797,7 +807,7 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
spin_unlock_irqrestore (&dum->lock, flags);
driver->unbind (&dum->gadget);
- dum->driver = 0;
+ dum->driver = NULL;
device_release_driver (&dum->gadget.dev);
@@ -830,16 +840,23 @@ EXPORT_SYMBOL (net2280_set_fifo_mode);
*/
static int dummy_urb_enqueue (
- struct usb_hcd *hcd,
- struct urb *urb,
- int mem_flags
+ struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep,
+ struct urb *urb,
+ int mem_flags
) {
struct dummy *dum;
+ struct urbp *urbp;
unsigned long flags;
if (!urb->transfer_buffer && urb->transfer_buffer_length)
return -EINVAL;
+ urbp = kmalloc (sizeof *urbp, mem_flags);
+ if (!urbp)
+ return -ENOMEM;
+ urbp->urb = urb;
+
dum = hcd_to_dummy (hcd);
spin_lock_irqsave (&dum->lock, flags);
@@ -849,7 +866,8 @@ static int dummy_urb_enqueue (
} else if (unlikely (dum->udev != urb->dev))
dev_err (dummy_dev(dum), "usb_device address has changed!\n");
- urb->hcpriv = dum;
+ list_add_tail (&urbp->urbp_list, &dum->urbp_list);
+ urb->hcpriv = urbp;
if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
urb->error_count = 1; /* mark as a new urb */
@@ -1007,7 +1025,7 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
int tmp;
/* high bandwidth mode */
- tmp = ep->desc->wMaxPacketSize;
+ tmp = le16_to_cpu(ep->desc->wMaxPacketSize);
tmp = le16_to_cpu (tmp);
tmp = (tmp >> 11) & 0x03;
tmp *= 8 /* applies to entire frame */;
@@ -1055,8 +1073,7 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
static void dummy_timer (unsigned long _dum)
{
struct dummy *dum = (struct dummy *) _dum;
- struct hcd_dev *hdev;
- struct list_head *entry, *tmp;
+ struct urbp *urbp, *tmp;
unsigned long flags;
int limit, total;
int i;
@@ -1088,7 +1105,6 @@ static void dummy_timer (unsigned long _dum)
spin_unlock_irqrestore (&dum->lock, flags);
return;
}
- hdev = dum->udev->hcpriv;
for (i = 0; i < DUMMY_ENDPOINTS; i++) {
if (!ep_name [i])
@@ -1097,14 +1113,14 @@ static void dummy_timer (unsigned long _dum)
}
restart:
- list_for_each_safe (entry, tmp, &hdev->urb_list) {
+ list_for_each_entry_safe (urbp, tmp, &dum->urbp_list, urbp_list) {
struct urb *urb;
struct dummy_request *req;
u8 address;
- struct dummy_ep *ep = 0;
+ struct dummy_ep *ep = NULL;
int type;
- urb = list_entry (entry, struct urb, urb_list);
+ urb = urbp->urb;
if (urb->status != -EINPROGRESS) {
/* likely it was just unlinked */
goto return_urb;
@@ -1349,19 +1365,21 @@ restart:
continue;
return_urb:
- urb->hcpriv = 0;
+ urb->hcpriv = NULL;
+ list_del (&urbp->urbp_list);
+ kfree (urbp);
if (ep)
ep->already_seen = ep->setup_stage = 0;
spin_unlock (&dum->lock);
- usb_hcd_giveback_urb (&dum->hcd, urb, 0);
+ usb_hcd_giveback_urb (dummy_to_hcd(dum), urb, NULL);
spin_lock (&dum->lock);
goto restart;
}
/* want a 1 msec delay here */
- if (!list_empty (&hdev->urb_list))
+ if (!list_empty (&dum->urbp_list))
mod_timer (&dum->timer, jiffies + msecs_to_jiffies(1));
else {
usb_put_dev (dum->udev);
@@ -1556,20 +1574,6 @@ static int dummy_hub_control (
/*-------------------------------------------------------------------------*/
-static struct usb_hcd *dummy_alloc (void)
-{
- struct dummy *dum;
-
- dum = kmalloc (sizeof *dum, SLAB_KERNEL);
- if (dum == NULL)
- return NULL;
- the_controller = dum;
- memset (dum, 0, sizeof *dum);
- return &dum->hcd;
-}
-
-/*-------------------------------------------------------------------------*/
-
static inline ssize_t
show_urb (char *buf, size_t size, struct urb *urb)
{
@@ -1601,21 +1605,17 @@ show_urbs (struct device *dev, char *buf)
{
struct usb_hcd *hcd = dev_get_drvdata (dev);
struct dummy *dum = hcd_to_dummy (hcd);
- struct urb *urb;
+ struct urbp *urbp;
size_t size = 0;
unsigned long flags;
- struct hcd_dev *hdev;
spin_lock_irqsave (&dum->lock, flags);
- if (dum->udev) {
- hdev = dum->udev->hcpriv;
- list_for_each_entry (urb, &hdev->urb_list, urb_list) {
- size_t temp;
-
- temp = show_urb (buf, PAGE_SIZE - size, urb);
- buf += temp;
- size += temp;
- }
+ list_for_each_entry (urbp, &dum->urbp_list, urbp_list) {
+ size_t temp;
+
+ temp = show_urb (buf, PAGE_SIZE - size, urbp->urb);
+ buf += temp;
+ size += temp;
}
spin_unlock_irqrestore (&dum->lock, flags);
@@ -1642,7 +1642,9 @@ static int dummy_start (struct usb_hcd *hcd)
dum->timer.function = dummy_timer;
dum->timer.data = (unsigned long) dum;
- root = usb_alloc_dev (0, &hcd->self, 0);
+ INIT_LIST_HEAD (&dum->urbp_list);
+
+ root = usb_alloc_dev (NULL, &hcd->self, 0);
if (!root)
return -ENOMEM;
@@ -1694,18 +1696,19 @@ static void dummy_stop (struct usb_hcd *hcd)
static int dummy_h_get_frame (struct usb_hcd *hcd)
{
- return dummy_g_get_frame (0);
+ return dummy_g_get_frame (NULL);
}
static const struct hc_driver dummy_hcd = {
.description = (char *) driver_name,
+ .product_desc = "Dummy host controller",
+ .hcd_priv_size = sizeof(struct dummy),
+
.flags = HCD_USB2,
.start = dummy_start,
.stop = dummy_stop,
- .hcd_alloc = dummy_alloc,
-
.urb_enqueue = dummy_urb_enqueue,
.urb_dequeue = dummy_urb_dequeue,
@@ -1725,7 +1728,7 @@ static int dummy_probe (struct device *dev)
dev_info (dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
- hcd = dummy_alloc ();
+ hcd = usb_create_hcd (&dummy_hcd);
if (hcd == NULL) {
dev_dbg (dev, "hcd_alloc failed\n");
return -ENOMEM;
@@ -1733,9 +1736,8 @@ static int dummy_probe (struct device *dev)
dev_set_drvdata (dev, hcd);
dum = hcd_to_dummy (hcd);
+ the_controller = dum;
- hcd->driver = (struct hc_driver *) &dummy_hcd;
- hcd->description = dummy_hcd.description;
hcd->self.controller = dev;
/* FIXME don't require the pci-based buffer/alloc impls;
@@ -1748,15 +1750,7 @@ static int dummy_probe (struct device *dev)
goto err1;
}
- usb_bus_init (&hcd->self);
- hcd->self.op = &usb_hcd_operations;
- hcd->self.release = &usb_hcd_release;
- hcd->self.hcpriv = hcd;
hcd->self.bus_name = dev->bus_id;
- hcd->product_desc = "Dummy host controller";
-
- INIT_LIST_HEAD (&hcd->dev_list);
-
usb_register_bus (&hcd->self);
if ((retval = dummy_start (hcd)) < 0)
@@ -1764,7 +1758,7 @@ static int dummy_probe (struct device *dev)
return retval;
err1:
- kfree (hcd);
+ usb_put_hcd (hcd);
dev_set_drvdata (dev, NULL);
return retval;
}
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 2d529f15bcd5dd..f7c6d758e1b00d 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -55,6 +55,9 @@ static __initdata unsigned in_epnum;
*
* Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
* Less common restrictions are implied by gadget_is_*().
+ *
+ * NOTE: each endpoint is unidirectional, as specified by its USB
+ * descriptor; and isn't specific to a configuration or altsetting.
*/
static int __init
ep_matches (
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 84d1f39cbcbdec..b339538ae3f2e3 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -3132,7 +3132,7 @@ reset:
if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0)
goto reset;
fsg->bulk_out_enabled = 1;
- fsg->bulk_out_maxpacket = d->wMaxPacketSize;
+ fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
if (transport_is_cbi()) {
d = ep_desc(fsg->gadget, &fs_intr_in_desc, &hs_intr_in_desc);
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
index 98dfa4c850d7f6..aeb821a5f2c384 100644
--- a/drivers/usb/gadget/omap_udc.c
+++ b/drivers/usb/gadget/omap_udc.c
@@ -1,5 +1,5 @@
/*
- * omap_udc.c -- for OMAP 1610 udc, with OTG support
+ * omap_udc.c -- for OMAP full speed udc; most chips support OTG.
*
* Copyright (C) 2004 Texas Instruments, Inc.
* Copyright (C) 2004 David Brownell
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index 15c2c02aa58870..0ae696317807c8 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -2322,11 +2322,11 @@ static void gs_free_ports(struct gs_dev *dev)
wake_up_interruptible(&port->port_tty->read_wait);
wake_up_interruptible(&port->port_tty->write_wait);
}
+ spin_unlock_irqrestore(&port->port_lock, flags);
} else {
kfree(port);
}
- spin_unlock_irqrestore(&port->port_lock, flags);
}
}
}
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index b83e753c4e3aa4..495e2a3ef6f1f9 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -19,13 +19,13 @@
/* this file is part of ehci-hcd.c */
#define ehci_dbg(ehci, fmt, args...) \
- dev_dbg ((ehci)->hcd.self.controller , fmt , ## args )
+ dev_dbg (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
#define ehci_err(ehci, fmt, args...) \
- dev_err ((ehci)->hcd.self.controller , fmt , ## args )
+ dev_err (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
#define ehci_info(ehci, fmt, args...) \
- dev_info ((ehci)->hcd.self.controller , fmt , ## args )
+ dev_info (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
#define ehci_warn(ehci, fmt, args...) \
- dev_warn ((ehci)->hcd.self.controller , fmt , ## args )
+ dev_warn (ehci_to_hcd(ehci)->self.controller , fmt , ## args )
#ifdef EHCI_VERBOSE_DEBUG
# define vdbg dbg
@@ -657,7 +657,7 @@ show_registers (struct class_device *class_dev, char *buf)
"EHCI %x.%02x, hcd state %d\n",
hcd->self.controller->bus->name,
hcd->self.controller->bus_id,
- i >> 8, i & 0x0ff, ehci->hcd.state);
+ i >> 8, i & 0x0ff, hcd->state);
size -= temp;
next += temp;
@@ -733,18 +733,22 @@ done:
}
static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
-static inline void create_debug_files (struct ehci_hcd *bus)
+static inline void create_debug_files (struct ehci_hcd *ehci)
{
- class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_async);
- class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
- class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
+ struct class_device *cldev = &ehci_to_hcd(ehci)->self.class_dev;
+
+ class_device_create_file(cldev, &class_device_attr_async);
+ class_device_create_file(cldev, &class_device_attr_periodic);
+ class_device_create_file(cldev, &class_device_attr_registers);
}
-static inline void remove_debug_files (struct ehci_hcd *bus)
+static inline void remove_debug_files (struct ehci_hcd *ehci)
{
- class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_async);
- class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
- class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
+ struct class_device *cldev = &ehci_to_hcd(ehci)->self.class_dev;
+
+ class_device_remove_file(cldev, &class_device_attr_async);
+ class_device_remove_file(cldev, &class_device_attr_periodic);
+ class_device_remove_file(cldev, &class_device_attr_registers);
}
#endif /* STUB_DEBUG_FILES */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 0b8d4dc2193abd..69255f45b55ac8 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -97,7 +97,7 @@
* 2001-June Works with usb-storage and NEC EHCI on 2.4
*/
-#define DRIVER_VERSION "26 Oct 2004"
+#define DRIVER_VERSION "10 Dec 2004"
#define DRIVER_AUTHOR "David Brownell"
#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver"
@@ -124,11 +124,16 @@ static const char hcd_name [] = "ehci_hcd";
#define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */
#define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */
-/* Initial IRQ latency: lower than default */
+/* Initial IRQ latency: faster than hw default */
static int log2_irq_thresh = 0; // 0 to 6
module_param (log2_irq_thresh, int, S_IRUGO);
MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes");
+/* initial park setting: slower than hw default */
+static unsigned park = 0;
+module_param (park, uint, S_IRUGO);
+MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
+
#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
/*-------------------------------------------------------------------------*/
@@ -194,7 +199,7 @@ static int ehci_reset (struct ehci_hcd *ehci)
command |= CMD_RESET;
dbg_cmd (ehci, "reset", command);
writel (command, &ehci->regs->command);
- ehci->hcd.state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = USB_STATE_HALT;
ehci->next_statechange = jiffies;
return handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
}
@@ -205,7 +210,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
u32 temp;
#ifdef DEBUG
- if (!HCD_IS_RUNNING (ehci->hcd.state))
+ if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
BUG ();
#endif
@@ -214,7 +219,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
temp &= STS_ASS | STS_PSS;
if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
temp, 16 * 125) != 0) {
- ehci->hcd.state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = USB_STATE_HALT;
return;
}
@@ -226,7 +231,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
/* hardware can take 16 microframes to turn off ... */
if (handshake (&ehci->regs->status, STS_ASS | STS_PSS,
0, 16 * 125) != 0) {
- ehci->hcd.state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = USB_STATE_HALT;
return;
}
}
@@ -280,7 +285,8 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
{
if (cap & (1 << 16)) {
int msec = 5000;
- struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller);
+ struct pci_dev *pdev =
+ to_pci_dev(ehci_to_hcd(ehci)->self.controller);
/* request handoff to OS */
cap |= 1 << 24;
@@ -338,7 +344,7 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
#ifdef CONFIG_PCI
/* EHCI 0.96 and later may have "extended capabilities" */
if (hcd->self.controller->bus == &pci_bus_type) {
- struct pci_dev *pdev = to_pci_dev(ehci->hcd.self.controller);
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
/* AMD8111 EHCI doesn't work, according to AMD errata */
if ((pdev->vendor == PCI_VENDOR_ID_AMD)
@@ -353,7 +359,7 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
while (temp && count--) {
u32 cap;
- pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller),
+ pci_read_config_dword (to_pci_dev(hcd->self.controller),
temp, &cap);
ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
switch (cap & 0xff) {
@@ -500,17 +506,30 @@ static int ehci_start (struct usb_hcd *hcd)
writel (0, &ehci->regs->segment);
#if 0
// this is deeply broken on almost all architectures
- if (!pci_set_dma_mask (to_pci_dev(ehci->hcd.self.controller), 0xffffffffffffffffULL))
+ if (!pci_set_dma_mask (to_pci_dev(hcd->self.controller), 0xffffffffffffffffULL))
ehci_info (ehci, "enabled 64bit PCI DMA\n");
#endif
}
/* clear interrupt enables, set irq latency */
- temp = readl (&ehci->regs->command) & 0x0fff;
if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
log2_irq_thresh = 0;
- temp |= 1 << (16 + log2_irq_thresh);
- // if hc can park (ehci >= 0.96), default is 3 packets per async QH
+ temp = 1 << (16 + log2_irq_thresh);
+ if (HCC_CANPARK(hcc_params)) {
+ /* HW default park == 3, on hardware that supports it (like
+ * NVidia and ALI silicon), maximizes throughput on the async
+ * schedule by avoiding QH fetches between transfers.
+ *
+ * With fast usb storage devices and NForce2, "park" seems to
+ * make problems: throughput reduction (!), data errors...
+ */
+ if (park) {
+ park = min (park, (unsigned) 3);
+ temp |= CMD_PARK;
+ temp |= park << 8;
+ }
+ ehci_info (ehci, "park %d\n", park);
+ }
if (HCC_PGM_FRAMELISTLEN (hcc_params)) {
/* periodic schedule size can be smaller than default */
temp &= ~(3 << 2);
@@ -522,7 +541,6 @@ static int ehci_start (struct usb_hcd *hcd)
default: BUG ();
}
}
- temp &= ~(CMD_IAAD | CMD_ASE | CMD_PSE),
// Philips, Intel, and maybe others need CMD_RUN before the
// root hub will detect new devices (why?); NEC doesn't
temp |= CMD_RUN;
@@ -553,7 +571,7 @@ done2:
register_reboot_notifier (&ehci->reboot_notifier);
}
- ehci->hcd.state = USB_STATE_RUNNING;
+ hcd->state = USB_STATE_RUNNING;
writel (FLAG_CF, &ehci->regs->configured_flag);
readl (&ehci->regs->command); /* unblock posted write */
@@ -610,7 +628,7 @@ static void ehci_stop (struct usb_hcd *hcd)
del_timer_sync (&ehci->watchdog);
spin_lock_irq(&ehci->lock);
- if (HCD_IS_RUNNING (ehci->hcd.state))
+ if (HCD_IS_RUNNING (hcd->state))
ehci_quiesce (ehci);
ehci_reset (ehci);
@@ -777,8 +795,9 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
* misplace IRQs, and should let us run completely without IRQs.
* such lossage has been observed on both VT6202 and VT8235.
*/
- if (HCD_IS_RUNNING (ehci->hcd.state) && (ehci->async->qh_next.ptr != 0
- || ehci->periodic_sched != 0))
+ if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) &&
+ (ehci->async->qh_next.ptr != 0 ||
+ ehci->periodic_sched != 0))
timer_action (ehci, TIMER_IO_WATCHDOG);
}
@@ -835,7 +854,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
}
/* remote wakeup [4.3.1] */
- if ((status & STS_PCD) && ehci->hcd.remote_wakeup) {
+ if ((status & STS_PCD) && hcd->remote_wakeup) {
unsigned i = HCS_N_PORTS (ehci->hcs_params);
/* resume root hub? */
@@ -856,7 +875,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
* stop that signaling.
*/
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
- mod_timer (&ehci->hcd.rh_timer,
+ mod_timer (&hcd->rh_timer,
ehci->reset_done [i] + 1);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
}
@@ -864,13 +883,20 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
/* PCI errors [4.15.2.4] */
if (unlikely ((status & STS_FATAL) != 0)) {
- ehci_err (ehci, "fatal error\n");
+ /* bogus "fatal" IRQs appear on some chips... why? */
+ status = readl (&ehci->regs->status);
+ dbg_cmd (ehci, "fatal", readl (&ehci->regs->command));
+ dbg_status (ehci, "fatal", status);
+ if (status & STS_HALT) {
+ ehci_err (ehci, "fatal error\n");
dead:
- ehci_reset (ehci);
- /* generic layer kills/unlinks all urbs, then
- * uses ehci_stop to clean up the rest
- */
- bh = 1;
+ ehci_reset (ehci);
+ writel (0, &ehci->regs->configured_flag);
+ /* generic layer kills/unlinks all urbs, then
+ * uses ehci_stop to clean up the rest
+ */
+ bh = 1;
+ }
}
if (bh)
@@ -895,6 +921,7 @@ dead:
*/
static int ehci_urb_enqueue (
struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep,
struct urb *urb,
int mem_flags
) {
@@ -909,12 +936,12 @@ static int ehci_urb_enqueue (
default:
if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
return -ENOMEM;
- return submit_async (ehci, urb, &qtd_list, mem_flags);
+ return submit_async (ehci, ep, urb, &qtd_list, mem_flags);
case PIPE_INTERRUPT:
if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags))
return -ENOMEM;
- return intr_submit (ehci, urb, &qtd_list, mem_flags);
+ return intr_submit (ehci, ep, urb, &qtd_list, mem_flags);
case PIPE_ISOCHRONOUS:
if (urb->dev->speed == USB_SPEED_HIGH)
@@ -929,7 +956,7 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* if we need to use IAA and it's busy, defer */
if (qh->qh_state == QH_STATE_LINKED
&& ehci->reclaim
- && HCD_IS_RUNNING (ehci->hcd.state)) {
+ && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
struct ehci_qh *last;
for (last = ehci->reclaim;
@@ -940,7 +967,7 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
last->reclaim = qh;
/* bypass IAA if the hc can't care */
- } else if (!HCD_IS_RUNNING (ehci->hcd.state) && ehci->reclaim)
+ } else if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
end_unlink_async (ehci, NULL);
/* something else might have unlinked the qh by now */
@@ -973,16 +1000,22 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
qh = (struct ehci_qh *) urb->hcpriv;
if (!qh)
break;
- if (qh->qh_state == QH_STATE_LINKED) {
- /* messy, can spin or block a microframe ... */
- intr_deschedule (ehci, qh, 1);
- /* qh_state == IDLE */
+ switch (qh->qh_state) {
+ case QH_STATE_LINKED:
+ intr_deschedule (ehci, qh);
+ /* FALL THROUGH */
+ case QH_STATE_IDLE:
+ qh_completions (ehci, qh, NULL);
+ break;
+ default:
+ ehci_dbg (ehci, "bogus qh %p state %d\n",
+ qh, qh->qh_state);
+ goto done;
}
- qh_completions (ehci, qh, NULL);
/* reschedule QH iff another request is queued */
if (!list_empty (&qh->qtd_list)
- && HCD_IS_RUNNING (ehci->hcd.state)) {
+ && HCD_IS_RUNNING (hcd->state)) {
int status;
status = qh_schedule (ehci, qh);
@@ -1005,6 +1038,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
// completion irqs can wait up to 1024 msec,
break;
}
+done:
spin_unlock_irqrestore (&ehci->lock, flags);
return 0;
}
@@ -1014,23 +1048,18 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
// bulk qh holds the data toggle
static void
-ehci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep)
+ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
- int epnum;
unsigned long flags;
struct ehci_qh *qh, *tmp;
/* ASSERT: any requests/urbs are being unlinked */
/* ASSERT: nobody can be submitting urbs for this any more */
- epnum = ep & USB_ENDPOINT_NUMBER_MASK;
- if (epnum != 0 && (ep & USB_DIR_IN))
- epnum |= 0x10;
-
rescan:
spin_lock_irqsave (&ehci->lock, flags);
- qh = (struct ehci_qh *) dev->ep [epnum];
+ qh = ep->hcpriv;
if (!qh)
goto done;
@@ -1042,7 +1071,7 @@ rescan:
goto idle_timeout;
}
- if (!HCD_IS_RUNNING (ehci->hcd.state))
+ if (!HCD_IS_RUNNING (hcd->state))
qh->qh_state = QH_STATE_IDLE;
switch (qh->qh_state) {
case QH_STATE_LINKED:
@@ -1072,12 +1101,12 @@ nogood:
/* caller was supposed to have unlinked any requests;
* that's not our job. just leak this memory.
*/
- ehci_err (ehci, "qh %p (#%d) state %d%s\n",
- qh, epnum, qh->qh_state,
+ ehci_err (ehci, "qh %p (#%02x) state %d%s\n",
+ qh, ep->desc.bEndpointAddress, qh->qh_state,
list_empty (&qh->qtd_list) ? "" : "(has tds)");
break;
}
- dev->ep[epnum] = NULL;
+ ep->hcpriv = NULL;
done:
spin_unlock_irqrestore (&ehci->lock, flags);
return;
@@ -1087,6 +1116,8 @@ done:
static const struct hc_driver ehci_driver = {
.description = hcd_name,
+ .product_desc = "EHCI Host Controller",
+ .hcd_priv_size = sizeof(struct ehci_hcd),
/*
* generic hardware linkage
@@ -1106,11 +1137,6 @@ static const struct hc_driver ehci_driver = {
.stop = ehci_stop,
/*
- * memory lifecycle (except per-request)
- */
- .hcd_alloc = ehci_hcd_alloc,
-
- /*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ehci_urb_enqueue,
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 6affe7d373edb3..8a1c130f944826 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -44,7 +44,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
/* stop schedules, clean any completed work */
if (HCD_IS_RUNNING(hcd->state)) {
ehci_quiesce (ehci);
- ehci->hcd.state = USB_STATE_QUIESCING;
+ hcd->state = USB_STATE_QUIESCING;
}
ehci->command = readl (&ehci->regs->command);
if (ehci->reclaim)
@@ -59,7 +59,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
if ((t1 & PORT_PE) && !(t1 & PORT_OWNER))
t2 |= PORT_SUSPEND;
- if (ehci->hcd.remote_wakeup)
+ if (hcd->remote_wakeup)
t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
else
t2 &= ~(PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E);
@@ -73,7 +73,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
/* turn off now-idle HC */
ehci_halt (ehci);
- ehci->hcd.state = HCD_STATE_SUSPENDED;
+ hcd->state = HCD_STATE_SUSPENDED;
ehci->next_statechange = jiffies + msecs_to_jiffies(10);
spin_unlock_irq (&ehci->lock);
@@ -145,7 +145,7 @@ static int ehci_hub_resume (struct usb_hcd *hcd)
}
ehci->next_statechange = jiffies + msecs_to_jiffies(5);
- ehci->hcd.state = USB_STATE_RUNNING;
+ hcd->state = USB_STATE_RUNNING;
/* Now we can safely re-enable irqs */
if (intr_enable)
@@ -212,7 +212,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
unsigned long flags;
/* if !USB_SUSPEND, root hub timers won't get shut down ... */
- if (!HCD_IS_RUNNING(ehci->hcd.state))
+ if (!HCD_IS_RUNNING(hcd->state))
return 0;
/* init status to no-changes */
@@ -499,7 +499,7 @@ static int ehci_hub_control (
if ((temp & PORT_PE) == 0
|| (temp & PORT_RESET) != 0)
goto error;
- if (ehci->hcd.remote_wakeup)
+ if (hcd->remote_wakeup)
temp |= PORT_WAKE_BITS;
writel (temp | PORT_SUSPEND,
&ehci->regs->port_status [wIndex]);
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c
index e81f61c05c84ca..dc693084da1a0b 100644
--- a/drivers/usb/host/ehci-mem.c
+++ b/drivers/usb/host/ehci-mem.c
@@ -32,25 +32,6 @@
*/
/*-------------------------------------------------------------------------*/
-/*
- * Allocator / cleanup for the per device structure
- * Called by hcd init / removal code
- */
-static struct usb_hcd *ehci_hcd_alloc (void)
-{
- struct ehci_hcd *ehci;
-
- ehci = (struct ehci_hcd *)
- kmalloc (sizeof (struct ehci_hcd), GFP_KERNEL);
- if (ehci != 0) {
- memset (ehci, 0, sizeof (struct ehci_hcd));
- ehci->hcd.product_desc = "EHCI Host Controller";
- return &ehci->hcd;
- }
- return NULL;
-}
-
-/*-------------------------------------------------------------------------*/
/* Allocate the key transfer structures from the previously allocated pool */
@@ -169,7 +150,7 @@ static void ehci_mem_cleanup (struct ehci_hcd *ehci)
ehci->sitd_pool = NULL;
if (ehci->periodic)
- dma_free_coherent (ehci->hcd.self.controller,
+ dma_free_coherent (ehci_to_hcd(ehci)->self.controller,
ehci->periodic_size * sizeof (u32),
ehci->periodic, ehci->periodic_dma);
ehci->periodic = NULL;
@@ -187,7 +168,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
/* QTDs for control/bulk/intr transfers */
ehci->qtd_pool = dma_pool_create ("ehci_qtd",
- ehci->hcd.self.controller,
+ ehci_to_hcd(ehci)->self.controller,
sizeof (struct ehci_qtd),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
@@ -197,7 +178,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
/* QHs for control/bulk/intr transfers */
ehci->qh_pool = dma_pool_create ("ehci_qh",
- ehci->hcd.self.controller,
+ ehci_to_hcd(ehci)->self.controller,
sizeof (struct ehci_qh),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
@@ -211,7 +192,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
/* ITD for high speed ISO transfers */
ehci->itd_pool = dma_pool_create ("ehci_itd",
- ehci->hcd.self.controller,
+ ehci_to_hcd(ehci)->self.controller,
sizeof (struct ehci_itd),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
@@ -221,7 +202,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
/* SITD for full/low speed split ISO transfers */
ehci->sitd_pool = dma_pool_create ("ehci_sitd",
- ehci->hcd.self.controller,
+ ehci_to_hcd(ehci)->self.controller,
sizeof (struct ehci_sitd),
32 /* byte alignment (for hw parts) */,
4096 /* can't cross 4K */);
@@ -231,7 +212,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, int flags)
/* Hardware periodic table */
ehci->periodic = (__le32 *)
- dma_alloc_coherent (ehci->hcd.self.controller,
+ dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller,
ehci->periodic_size * sizeof(__le32),
&ehci->periodic_dma, 0);
if (ehci->periodic == 0) {
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 69107cc87f1862..68f2771ba5c992 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -200,7 +200,7 @@ static void qtd_copy_status (
|| QTD_CERR(token) == 0)
&& (!ehci_is_ARC(ehci)
|| urb->dev->tt->hub !=
- ehci->hcd.self.root_hub)) {
+ ehci_to_hcd(ehci)->self.root_hub)) {
#ifdef DEBUG
struct usb_device *tt = urb->dev->tt->hub;
dev_dbg (&tt->dev,
@@ -225,7 +225,7 @@ __acquires(ehci->lock)
if ((qh->hw_info2 & __constant_cpu_to_le32 (0x00ff)) != 0) {
/* ... update hc-wide periodic stats (for usbfs) */
- hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs--;
+ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--;
}
qh_put (qh);
}
@@ -262,14 +262,13 @@ __acquires(ehci->lock)
/* complete() can reenter this HCD */
spin_unlock (&ehci->lock);
- usb_hcd_giveback_urb (&ehci->hcd, urb, regs);
+ usb_hcd_giveback_urb (ehci_to_hcd(ehci), urb, regs);
spin_lock (&ehci->lock);
}
static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh);
-static void intr_deschedule (struct ehci_hcd *ehci,
- struct ehci_qh *qh, int wait);
+static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh);
/*
@@ -348,13 +347,13 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
/* stop scanning when we reach qtds the hc is using */
} else if (likely (!stopped
- && HCD_IS_RUNNING (ehci->hcd.state))) {
+ && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))) {
break;
} else {
stopped = 1;
- if (unlikely (!HCD_IS_RUNNING (ehci->hcd.state)))
+ if (unlikely (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)))
urb->status = -ESHUTDOWN;
/* ignore active urbs unless some previous qtd
@@ -428,7 +427,7 @@ halt:
* except maybe high bandwidth ...
*/
if (qh->period) {
- intr_deschedule (ehci, qh, 1);
+ intr_deschedule (ehci, qh);
(void) qh_schedule (ehci, qh);
} else
start_unlink_async (ehci, qh);
@@ -664,9 +663,12 @@ qh_make (
qh->c_usecs = 0;
qh->gap_uf = 0;
- /* FIXME handle HS periods of less than 1 frame. */
qh->period = urb->interval >> 3;
- if (qh->period < 1) {
+ if (qh->period == 0 && urb->interval != 1) {
+ /* NOTE interval 2 or 4 uframes could work.
+ * But interval 1 scheduling is simpler, and
+ * includes high bandwidth.
+ */
dbg ("intr period %d uframes, NYET!",
urb->interval);
goto done;
@@ -715,7 +717,8 @@ qh_make (
* root hub tt, leave it zeroed.
*/
if (!ehci_is_ARC(ehci)
- || urb->dev->tt->hub != ehci->hcd.self.root_hub)
+ || urb->dev->tt->hub !=
+ ehci_to_hcd(ehci)->self.root_hub)
info2 |= urb->dev->tt->hub->devnum << 16;
/* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */
@@ -776,7 +779,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
(void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
cmd |= CMD_ASE | CMD_RUN;
writel (cmd, &ehci->regs->command);
- ehci->hcd.state = USB_STATE_RUNNING;
+ ehci_to_hcd(ehci)->state = USB_STATE_RUNNING;
/* posted write need not be known to HC yet ... */
}
}
@@ -832,26 +835,8 @@ static struct ehci_qh *qh_append_tds (
qtd = list_entry (qtd_list->next, struct ehci_qtd,
qtd_list);
- /* control qh may need patching after enumeration */
+ /* control qh may need patching ... */
if (unlikely (epnum == 0)) {
- /* set_address changes the address */
- if ((qh->hw_info1 & QH_ADDR_MASK) == 0)
- qh->hw_info1 |= cpu_to_le32 (
- usb_pipedevice (urb->pipe));
-
- /* for full speed, ep0 maxpacket can grow */
- else if (!(qh->hw_info1
- & __constant_cpu_to_le32 (0x3 << 12))) {
- u32 info, max;
-
- info = le32_to_cpu (qh->hw_info1);
- max = urb->dev->descriptor.bMaxPacketSize0;
- if (max > (0x07ff & (info >> 16))) {
- info &= ~(0x07ff << 16);
- info |= max << 16;
- qh->hw_info1 = cpu_to_le32 (info);
- }
- }
/* usb_reset_device() briefly reverts to address 0 */
if (usb_pipedevice (urb->pipe) == 0)
@@ -908,33 +893,30 @@ static struct ehci_qh *qh_append_tds (
static int
submit_async (
struct ehci_hcd *ehci,
+ struct usb_host_endpoint *ep,
struct urb *urb,
struct list_head *qtd_list,
int mem_flags
) {
struct ehci_qtd *qtd;
- struct hcd_dev *dev;
int epnum;
unsigned long flags;
struct ehci_qh *qh = NULL;
qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
- dev = (struct hcd_dev *)urb->dev->hcpriv;
- epnum = usb_pipeendpoint (urb->pipe);
- if (usb_pipein (urb->pipe) && !usb_pipecontrol (urb->pipe))
- epnum |= 0x10;
+ epnum = ep->desc.bEndpointAddress;
#ifdef EHCI_URB_TRACE
ehci_dbg (ehci,
"%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
__FUNCTION__, urb->dev->devpath, urb,
- epnum & 0x0f, usb_pipein (urb->pipe) ? "in" : "out",
+ epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
urb->transfer_buffer_length,
- qtd, dev ? dev->ep [epnum] : (void *)~0);
+ qtd, ep->hcpriv);
#endif
spin_lock_irqsave (&ehci->lock, flags);
- qh = qh_append_tds (ehci, urb, qtd_list, epnum, &dev->ep [epnum]);
+ qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv);
/* Control/bulk operations through TTs don't need scheduling,
* the HC and TT handle it when the TT has a buffer ready.
@@ -976,7 +958,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
qh_completions (ehci, qh, regs);
if (!list_empty (&qh->qtd_list)
- && HCD_IS_RUNNING (ehci->hcd.state))
+ && HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
qh_link_async (ehci, qh);
else {
qh_put (qh); // refcount from async list
@@ -984,7 +966,7 @@ static void end_unlink_async (struct ehci_hcd *ehci, struct pt_regs *regs)
/* it's not free to turn the async schedule on/off; leave it
* active but idle for a while once it empties.
*/
- if (HCD_IS_RUNNING (ehci->hcd.state)
+ if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state)
&& ehci->async->qh_next.qh == 0)
timer_action (ehci, TIMER_ASYNC_OFF);
}
@@ -1018,7 +1000,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
/* stop async schedule right now? */
if (unlikely (qh == ehci->async)) {
/* can't get here without STS_ASS set */
- if (ehci->hcd.state != USB_STATE_HALT) {
+ if (ehci_to_hcd(ehci)->state != USB_STATE_HALT) {
writel (cmd & ~CMD_ASE, &ehci->regs->command);
wmb ();
// handshake later, if we need to
@@ -1038,7 +1020,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
prev->qh_next = qh->qh_next;
wmb ();
- if (unlikely (ehci->hcd.state == USB_STATE_HALT)) {
+ if (unlikely (ehci_to_hcd(ehci)->state == USB_STATE_HALT)) {
/* if (unlikely (qh->reclaim != 0))
* this will recurse, probably not much
*/
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 74bdd5bfcc25c6..2cd8abbec414b1 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001-2003 by David Brownell
+ * Copyright (c) 2001-2004 by David Brownell
* Copyright (c) 2003 Michal Sojka, for high-speed iso transfers
*
* This program is free software; you can redistribute it and/or modify it
@@ -59,39 +59,28 @@ periodic_next_shadow (union ehci_shadow *periodic, __le32 tag)
}
}
-/* returns true after successful unlink */
/* caller must hold ehci->lock */
-static int periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
+static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr)
{
union ehci_shadow *prev_p = &ehci->pshadow [frame];
__le32 *hw_p = &ehci->periodic [frame];
union ehci_shadow here = *prev_p;
- union ehci_shadow *next_p;
/* find predecessor of "ptr"; hw and shadow lists are in sync */
while (here.ptr && here.ptr != ptr) {
prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p));
- hw_p = &here.qh->hw_next;
+ hw_p = here.hw_next;
here = *prev_p;
}
/* an interrupt entry (at list end) could have been shared */
- if (!here.ptr) {
- dbg ("entry %p no longer on frame [%d]", ptr, frame);
- return 0;
- }
- // vdbg ("periodic unlink %p from frame %d", ptr, frame);
+ if (!here.ptr)
+ return;
- /* update hardware list ... HC may still know the old structure, so
- * don't change hw_next until it'll have purged its cache
+ /* update shadow and hardware lists ... the old "next" pointers
+ * from ptr may still be in use, the caller updates them.
*/
- next_p = periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
- *hw_p = here.qh->hw_next;
-
- /* unlink from shadow list; HCD won't see old structure again */
- *prev_p = *next_p;
- next_p->ptr = NULL;
-
- return 1;
+ *prev_p = *periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p));
+ *hw_p = *here.hw_next;
}
/* how many of the uframe's 125 usecs are allocated? */
@@ -114,7 +103,8 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
hw_p = &q->qh->hw_next;
q = &q->qh->qh_next;
break;
- case Q_TYPE_FSTN:
+ // case Q_TYPE_FSTN:
+ default:
/* for "save place" FSTNs, count the relevant INTR
* bandwidth from the previous frame
*/
@@ -149,13 +139,11 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe)
hw_p = &q->sitd->hw_next;
q = &q->sitd->sitd_next;
break;
- default:
- BUG ();
}
}
#ifdef DEBUG
if (usecs > 100)
- err ("overallocated uframe %d, periodic is %d usecs",
+ ehci_err (ehci, "uframe %d sched overrun: %d usecs\n",
frame * 8 + uframe, usecs);
#endif
return usecs;
@@ -261,14 +249,14 @@ static int enable_periodic (struct ehci_hcd *ehci)
*/
status = handshake (&ehci->regs->status, STS_PSS, 0, 9 * 125);
if (status != 0) {
- ehci->hcd.state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = USB_STATE_HALT;
return status;
}
cmd = readl (&ehci->regs->command) | CMD_PSE;
writel (cmd, &ehci->regs->command);
/* posted write ... PSS happens later */
- ehci->hcd.state = USB_STATE_RUNNING;
+ ehci_to_hcd(ehci)->state = USB_STATE_RUNNING;
/* make sure ehci_work scans these */
ehci->next_uframe = readl (&ehci->regs->frame_index)
@@ -286,7 +274,7 @@ static int disable_periodic (struct ehci_hcd *ehci)
*/
status = handshake (&ehci->regs->status, STS_PSS, STS_PSS, 9 * 125);
if (status != 0) {
- ehci->hcd.state = USB_STATE_HALT;
+ ehci_to_hcd(ehci)->state = USB_STATE_HALT;
return status;
}
@@ -300,64 +288,143 @@ static int disable_periodic (struct ehci_hcd *ehci)
/*-------------------------------------------------------------------------*/
-// FIXME microframe periods not yet handled
+/* periodic schedule slots have iso tds (normal or split) first, then a
+ * sparse tree for active interrupt transfers.
+ *
+ * this just links in a qh; caller guarantees uframe masks are set right.
+ * no FSTN support (yet; ehci 0.96+)
+ */
+static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ unsigned i;
+ unsigned period = qh->period;
-static void intr_deschedule (
- struct ehci_hcd *ehci,
- struct ehci_qh *qh,
- int wait
-) {
- int status;
- unsigned frame = qh->start;
+ dev_dbg (&qh->dev->dev,
+ "link qh%d-%04x/%p start %d [%d/%d us]\n",
+ period, le32_to_cpup (&qh->hw_info2) & 0xffff,
+ qh, qh->start, qh->usecs, qh->c_usecs);
- do {
- periodic_unlink (ehci, frame, qh);
- qh_put (qh);
- frame += qh->period;
- } while (frame < ehci->periodic_size);
+ /* high bandwidth, or otherwise every microframe */
+ if (period == 0)
+ period = 1;
+
+ for (i = qh->start; i < ehci->periodic_size; i += period) {
+ union ehci_shadow *prev = &ehci->pshadow [i];
+ u32 *hw_p = &ehci->periodic [i];
+ union ehci_shadow here = *prev;
+ u32 type = 0;
+
+ /* skip the iso nodes at list head */
+ while (here.ptr) {
+ type = Q_NEXT_TYPE (*hw_p);
+ if (type == Q_TYPE_QH)
+ break;
+ prev = periodic_next_shadow (prev, type);
+ hw_p = &here.qh->hw_next;
+ here = *prev;
+ }
+
+ /* sorting each branch by period (slow-->fast)
+ * enables sharing interior tree nodes
+ */
+ while (here.ptr && qh != here.qh) {
+ if (qh->period > here.qh->period)
+ break;
+ prev = &here.qh->qh_next;
+ hw_p = &here.qh->hw_next;
+ here = *prev;
+ }
+ /* link in this qh, unless some earlier pass did that */
+ if (qh != here.qh) {
+ qh->qh_next = here;
+ if (here.qh)
+ qh->hw_next = *hw_p;
+ wmb ();
+ prev->qh = qh;
+ *hw_p = QH_NEXT (qh->qh_dma);
+ }
+ }
+ qh->qh_state = QH_STATE_LINKED;
+ qh_get (qh);
+
+ /* update per-qh bandwidth for usbfs */
+ ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period
+ ? ((qh->usecs + qh->c_usecs) / qh->period)
+ : (qh->usecs * 8);
+
+ /* maybe enable periodic schedule processing */
+ if (!ehci->periodic_sched++)
+ return enable_periodic (ehci);
+
+ return 0;
+}
+
+static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ unsigned i;
+ unsigned period;
+
+ // FIXME:
+ // IF this isn't high speed
+ // and this qh is active in the current uframe
+ // (and overlay token SplitXstate is false?)
+ // THEN
+ // qh->hw_info1 |= __constant_cpu_to_le32 (1 << 7 /* "ignore" */);
+
+ /* high bandwidth, or otherwise part of every microframe */
+ if ((period = qh->period) == 0)
+ period = 1;
+
+ for (i = qh->start; i < ehci->periodic_size; i += period)
+ periodic_unlink (ehci, i, qh);
+ /* update per-qh bandwidth for usbfs */
+ ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->period
+ ? ((qh->usecs + qh->c_usecs) / qh->period)
+ : (qh->usecs * 8);
+
+ dev_dbg (&qh->dev->dev,
+ "unlink qh%d-%04x/%p start %d [%d/%d us]\n",
+ qh->period, le32_to_cpup (&qh->hw_info2) & 0xffff,
+ qh, qh->start, qh->usecs, qh->c_usecs);
+
+ /* qh->qh_next still "live" to HC */
qh->qh_state = QH_STATE_UNLINK;
qh->qh_next.ptr = NULL;
- ehci->periodic_sched--;
+ qh_put (qh);
/* maybe turn off periodic schedule */
+ ehci->periodic_sched--;
if (!ehci->periodic_sched)
- status = disable_periodic (ehci);
- else {
- status = 0;
- ehci_vdbg (ehci, "periodic schedule still enabled\n");
- }
+ (void) disable_periodic (ehci);
+}
- /*
- * If the hc may be looking at this qh, then delay a uframe
- * (yeech!) to be sure it's done.
- * No other threads may be mucking with this qh.
- */
- if (((ehci_get_frame (&ehci->hcd) - frame) % qh->period) == 0) {
- if (wait) {
- udelay (125);
- qh->hw_next = EHCI_LIST_END;
- } else {
- /* we may not be IDLE yet, but if the qh is empty
- * the race is very short. then if qh also isn't
- * rescheduled soon, it won't matter. otherwise...
- */
- ehci_vdbg (ehci, "intr_deschedule...\n");
- }
- } else
- qh->hw_next = EHCI_LIST_END;
+static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
+{
+ unsigned wait;
- qh->qh_state = QH_STATE_IDLE;
+ qh_unlink_periodic (ehci, qh);
- /* update per-qh bandwidth utilization (for usbfs) */
- hcd_to_bus (&ehci->hcd)->bandwidth_allocated -=
- (qh->usecs + qh->c_usecs) / qh->period;
+ /* simple/paranoid: always delay, expecting the HC needs to read
+ * qh->hw_next or finish a writeback after SPLIT/CSPLIT ... and
+ * expect khubd to clean up after any CSPLITs we won't issue.
+ * active high speed queues may need bigger delays...
+ */
+ if (list_empty (&qh->qtd_list)
+ || (__constant_cpu_to_le32 (0x0ff << 8)
+ & qh->hw_info2) != 0)
+ wait = 2;
+ else
+ wait = 55; /* worst case: 3 * 1024 */
- ehci_dbg (ehci, "descheduled qh%d/%p frame=%d count=%d, urbs=%d\n",
- qh->period, qh, frame,
- atomic_read (&qh->kref.refcount), ehci->periodic_sched);
+ udelay (wait);
+ qh->qh_state = QH_STATE_IDLE;
+ qh->hw_next = EHCI_LIST_END;
+ wmb ();
}
+/*-------------------------------------------------------------------------*/
+
static int check_period (
struct ehci_hcd *ehci,
unsigned frame,
@@ -365,6 +432,8 @@ static int check_period (
unsigned period,
unsigned usecs
) {
+ int claimed;
+
/* complete split running into next frame?
* given FSTN support, we could sometimes check...
*/
@@ -377,22 +446,26 @@ static int check_period (
*/
usecs = 100 - usecs;
- do {
- int claimed;
-
-// FIXME delete when intr_submit handles non-empty queues
-// this gives us a one intr/frame limit (vs N/uframe)
-// ... and also lets us avoid tracking split transactions
-// that might collide at a given TT/hub.
- if (ehci->pshadow [frame].ptr)
- return 0;
-
- claimed = periodic_usecs (ehci, frame, uframe);
- if (claimed > usecs)
- return 0;
+ /* we "know" 2 and 4 uframe intervals were rejected; so
+ * for period 0, check _every_ microframe in the schedule.
+ */
+ if (unlikely (period == 0)) {
+ do {
+ for (uframe = 0; uframe < 7; uframe++) {
+ claimed = periodic_usecs (ehci, frame, uframe);
+ if (claimed > usecs)
+ return 0;
+ }
+ } while ((frame += 1) < ehci->periodic_size);
-// FIXME update to handle sub-frame periods
- } while ((frame += period) < ehci->periodic_size);
+ /* just check the specified uframe, at that period */
+ } else {
+ do {
+ claimed = periodic_usecs (ehci, frame, uframe);
+ if (claimed > usecs)
+ return 0;
+ } while ((frame += period) < ehci->periodic_size);
+ }
// success!
return 1;
@@ -407,6 +480,10 @@ static int check_intr_schedule (
)
{
int retval = -ENOSPC;
+ u8 mask;
+
+ if (qh->c_usecs && uframe >= 6) /* FSTN territory? */
+ goto done;
if (!check_period (ehci, frame, uframe, qh->period, qh->usecs))
goto done;
@@ -416,33 +493,33 @@ static int check_intr_schedule (
goto done;
}
- /* This is a split transaction; check the bandwidth available for
- * the completion too. Check both worst and best case gaps: worst
- * case is SPLIT near uframe end, and CSPLIT near start ... best is
- * vice versa. Difference can be almost two uframe times, but we
- * reserve unnecessary bandwidth (waste it) this way. (Actually
- * even better cases exist, like immediate device NAK.)
- *
- * FIXME don't even bother unless we know this TT is idle in that
- * range of uframes ... for now, check_period() allows only one
- * interrupt transfer per frame, so needn't check "TT busy" status
- * when scheduling a split (QH, SITD, or FSTN).
- *
- * FIXME ehci 0.96 and above can use FSTNs
+ /* Make sure this tt's buffer is also available for CSPLITs.
+ * We pessimize a bit; probably the typical full speed case
+ * doesn't need the second CSPLIT.
+ *
+ * NOTE: both SPLIT and CSPLIT could be checked in just
+ * one smart pass...
*/
- if (!check_period (ehci, frame, uframe + qh->gap_uf + 1,
- qh->period, qh->c_usecs))
- goto done;
- if (!check_period (ehci, frame, uframe + qh->gap_uf,
- qh->period, qh->c_usecs))
- goto done;
+ mask = 0x03 << (uframe + qh->gap_uf);
+ *c_maskp = cpu_to_le32 (mask << 8);
- *c_maskp = cpu_to_le32 (0x03 << (8 + uframe + qh->gap_uf));
- retval = 0;
+ mask |= 1 << uframe;
+ if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) {
+ if (!check_period (ehci, frame, uframe + qh->gap_uf + 1,
+ qh->period, qh->c_usecs))
+ goto done;
+ if (!check_period (ehci, frame, uframe + qh->gap_uf,
+ qh->period, qh->c_usecs))
+ goto done;
+ retval = 0;
+ }
done:
return retval;
}
+/* "first fit" scheduling policy used the first time through,
+ * or when the previous schedule slot can't be re-used.
+ */
static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
{
int status;
@@ -469,62 +546,46 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh)
* uframes have enough periodic bandwidth available.
*/
if (status) {
- frame = qh->period - 1;
- do {
- for (uframe = 0; uframe < 8; uframe++) {
- status = check_intr_schedule (ehci,
- frame, uframe, qh,
- &c_mask);
- if (status == 0)
- break;
- }
- } while (status && frame--);
+ /* "normal" case, uframing flexible except with splits */
+ if (qh->period) {
+ frame = qh->period - 1;
+ do {
+ for (uframe = 0; uframe < 8; uframe++) {
+ status = check_intr_schedule (ehci,
+ frame, uframe, qh,
+ &c_mask);
+ if (status == 0)
+ break;
+ }
+ } while (status && frame--);
+
+ /* qh->period == 0 means every uframe */
+ } else {
+ frame = 0;
+ status = check_intr_schedule (ehci, 0, 0, qh, &c_mask);
+ }
if (status)
goto done;
qh->start = frame;
/* reset S-frame and (maybe) C-frame masks */
- qh->hw_info2 &= ~__constant_cpu_to_le32(0xffff);
- qh->hw_info2 |= cpu_to_le32 (1 << uframe) | c_mask;
+ qh->hw_info2 &= __constant_cpu_to_le32 (~0xffff);
+ qh->hw_info2 |= qh->period
+ ? cpu_to_le32 (1 << uframe)
+ : __constant_cpu_to_le32 (0xff);
+ qh->hw_info2 |= c_mask;
} else
ehci_dbg (ehci, "reused qh %p schedule\n", qh);
/* stuff into the periodic schedule */
- qh->qh_state = QH_STATE_LINKED;
- ehci_dbg(ehci,
- "scheduled qh%d/%p usecs %d/%d starting %d.%d (gap %d)\n",
- qh->period, qh, qh->usecs, qh->c_usecs,
- frame, uframe, qh->gap_uf);
- do {
- if (unlikely (ehci->pshadow [frame].ptr != 0)) {
-
-// FIXME -- just link toward the end, before any qh with a shorter period,
-// AND accommodate it already having been linked here (after some other qh)
-// AS WELL AS updating the schedule checking logic
-
- BUG ();
- } else {
- ehci->pshadow [frame].qh = qh_get (qh);
- ehci->periodic [frame] =
- QH_NEXT (qh->qh_dma);
- }
- wmb ();
- frame += qh->period;
- } while (frame < ehci->periodic_size);
-
- /* update per-qh bandwidth for usbfs */
- hcd_to_bus (&ehci->hcd)->bandwidth_allocated +=
- (qh->usecs + qh->c_usecs) / qh->period;
-
- /* maybe enable periodic schedule processing */
- if (!ehci->periodic_sched++)
- status = enable_periodic (ehci);
+ status = qh_link_periodic (ehci, qh);
done:
return status;
}
static int intr_submit (
struct ehci_hcd *ehci,
+ struct usb_host_endpoint *ep,
struct urb *urb,
struct list_head *qtd_list,
int mem_flags
@@ -532,23 +593,17 @@ static int intr_submit (
unsigned epnum;
unsigned long flags;
struct ehci_qh *qh;
- struct hcd_dev *dev;
- int is_input;
int status = 0;
struct list_head empty;
/* get endpoint and transfer/schedule data */
- epnum = usb_pipeendpoint (urb->pipe);
- is_input = usb_pipein (urb->pipe);
- if (is_input)
- epnum |= 0x10;
+ epnum = ep->desc.bEndpointAddress;
spin_lock_irqsave (&ehci->lock, flags);
- dev = (struct hcd_dev *)urb->dev->hcpriv;
/* get qh and force any scheduling errors */
INIT_LIST_HEAD (&empty);
- qh = qh_append_tds (ehci, urb, &empty, epnum, &dev->ep [epnum]);
+ qh = qh_append_tds (ehci, urb, &empty, epnum, &ep->hcpriv);
if (qh == 0) {
status = -ENOMEM;
goto done;
@@ -559,11 +614,11 @@ static int intr_submit (
}
/* then queue the urb's tds to the qh */
- qh = qh_append_tds (ehci, urb, qtd_list, epnum, &dev->ep [epnum]);
+ qh = qh_append_tds (ehci, urb, qtd_list, epnum, &ep->hcpriv);
BUG_ON (qh == 0);
/* ... update usbfs periodic stats */
- hcd_to_bus (&ehci->hcd)->bandwidth_int_reqs++;
+ ehci_to_hcd(ehci)->self.bandwidth_int_reqs++;
done:
spin_unlock_irqrestore (&ehci->lock, flags);
@@ -614,11 +669,10 @@ iso_stream_init (
*/
epnum = usb_pipeendpoint (pipe);
is_input = usb_pipein (pipe) ? USB_DIR_IN : 0;
+ maxp = usb_maxpacket(dev, pipe, !is_input);
if (is_input) {
- maxp = dev->epmaxpacketin [epnum];
buf1 = (1 << 11);
} else {
- maxp = dev->epmaxpacketout [epnum];
buf1 = 0;
}
@@ -690,7 +744,6 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
*/
if (stream->refcount == 1) {
int is_in;
- struct hcd_dev *dev = stream->udev->hcpriv;
// BUG_ON (!list_empty(&stream->td_list));
@@ -720,7 +773,7 @@ iso_stream_put(struct ehci_hcd *ehci, struct ehci_iso_stream *stream)
is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0;
stream->bEndpointAddress &= 0x0f;
- dev->ep[is_in + stream->bEndpointAddress] = NULL;
+ stream->ep->hcpriv = NULL;
if (stream->rescheduled) {
ehci_info (ehci, "ep%d%s-iso rescheduled "
@@ -747,24 +800,25 @@ static struct ehci_iso_stream *
iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
{
unsigned epnum;
- struct hcd_dev *dev;
struct ehci_iso_stream *stream;
+ struct usb_host_endpoint *ep;
unsigned long flags;
epnum = usb_pipeendpoint (urb->pipe);
if (usb_pipein(urb->pipe))
- epnum += 0x10;
+ ep = urb->dev->ep_in[epnum];
+ else
+ ep = urb->dev->ep_out[epnum];
spin_lock_irqsave (&ehci->lock, flags);
-
- dev = (struct hcd_dev *)urb->dev->hcpriv;
- stream = dev->ep [epnum];
+ stream = ep->hcpriv;
if (unlikely (stream == 0)) {
stream = iso_stream_alloc(GFP_ATOMIC);
if (likely (stream != 0)) {
/* dev->ep owns the initial refcount */
- dev->ep[epnum] = stream;
+ ep->hcpriv = stream;
+ stream->ep = ep;
iso_stream_init(stream, urb->dev, urb->pipe,
urb->interval);
}
@@ -772,8 +826,8 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
/* if dev->ep [epnum] is a QH, info1.maxpacket is nonzero */
} else if (unlikely (stream->hw_info1 != 0)) {
ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n",
- urb->dev->devpath, epnum & 0x0f,
- (epnum & 0x10) ? "in" : "out");
+ urb->dev->devpath, epnum,
+ usb_pipein(urb->pipe) ? "in" : "out");
stream = NULL;
}
@@ -786,7 +840,7 @@ iso_stream_find (struct ehci_hcd *ehci, struct urb *urb)
/*-------------------------------------------------------------------------*/
-/* ehci_iso_sched ops can be shared, ITD-only, or SITD-only */
+/* ehci_iso_sched ops can be ITD-only or SITD-only */
static struct ehci_iso_sched *
iso_sched_alloc (unsigned packets, int mem_flags)
@@ -1204,7 +1258,7 @@ itd_link_urb (
next_uframe = stream->next_uframe % mod;
if (unlikely (list_empty(&stream->td_list))) {
- hcd_to_bus (&ehci->hcd)->bandwidth_allocated
+ ehci_to_hcd(ehci)->self.bandwidth_allocated
+= stream->bandwidth;
ehci_vdbg (ehci,
"schedule devp %s ep%d%s-iso period %d start %d.%d\n",
@@ -1214,7 +1268,7 @@ itd_link_urb (
next_uframe >> 3, next_uframe & 0x7);
stream->start = jiffies;
}
- hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs++;
+ ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
/* fill iTDs uframe by uframe */
for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) {
@@ -1336,10 +1390,10 @@ itd_complete (
ehci->periodic_sched--;
if (unlikely (!ehci->periodic_sched))
(void) disable_periodic (ehci);
- hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs--;
+ ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
if (unlikely (list_empty (&stream->td_list))) {
- hcd_to_bus (&ehci->hcd)->bandwidth_allocated
+ ehci_to_hcd(ehci)->self.bandwidth_allocated
-= stream->bandwidth;
ehci_vdbg (ehci,
"deschedule devp %s ep%d%s-iso\n",
@@ -1589,7 +1643,7 @@ sitd_link_urb (
if (list_empty(&stream->td_list)) {
/* usbfs ignores TT bandwidth */
- hcd_to_bus (&ehci->hcd)->bandwidth_allocated
+ ehci_to_hcd(ehci)->self.bandwidth_allocated
+= stream->bandwidth;
ehci_vdbg (ehci,
"sched dev%s ep%d%s-iso [%d] %dms/%04x\n",
@@ -1599,7 +1653,7 @@ sitd_link_urb (
stream->interval, le32_to_cpu (stream->splits));
stream->start = jiffies;
}
- hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs++;
+ ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++;
/* fill sITDs frame by frame */
for (packet = 0, sitd = NULL;
@@ -1699,10 +1753,10 @@ sitd_complete (
ehci->periodic_sched--;
if (!ehci->periodic_sched)
(void) disable_periodic (ehci);
- hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs--;
+ ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--;
if (list_empty (&stream->td_list)) {
- hcd_to_bus (&ehci->hcd)->bandwidth_allocated
+ ehci_to_hcd(ehci)->self.bandwidth_allocated
-= stream->bandwidth;
ehci_vdbg (ehci,
"deschedule devp %s ep%d%s-iso\n",
@@ -1806,7 +1860,7 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
* Touches as few pages as possible: cache-friendly.
*/
now_uframe = ehci->next_uframe;
- if (HCD_IS_RUNNING (ehci->hcd.state))
+ if (HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
clock = readl (&ehci->regs->frame_index);
else
clock = now_uframe + mod - 1;
@@ -1840,7 +1894,7 @@ restart:
union ehci_shadow temp;
int live;
- live = HCD_IS_RUNNING (ehci->hcd.state);
+ live = HCD_IS_RUNNING (ehci_to_hcd(ehci)->state);
switch (type) {
case Q_TYPE_QH:
/* handle any completions */
@@ -1849,7 +1903,7 @@ restart:
q = q.qh->qh_next;
modified = qh_completions (ehci, temp.qh, regs);
if (unlikely (list_empty (&temp.qh->qtd_list)))
- intr_deschedule (ehci, temp.qh, 0);
+ intr_deschedule (ehci, temp.qh);
qh_put (temp.qh);
break;
case Q_TYPE_FSTN:
@@ -1929,7 +1983,7 @@ restart:
if (now_uframe == clock) {
unsigned now;
- if (!HCD_IS_RUNNING (ehci->hcd.state))
+ if (!HCD_IS_RUNNING (ehci_to_hcd(ehci)->state))
break;
ehci->next_uframe = now_uframe;
now = readl (&ehci->regs->frame_index) % mod;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 2e2cb6eba1efcb..e28d19724f560b 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -36,7 +36,7 @@ struct ehci_stats {
/* ehci_hcd->lock guards shared data against other CPUs:
* ehci_hcd: async, reclaim, periodic (and shadow), ...
- * hcd_dev: ep[]
+ * usb_host_endpoint: hcpriv
* ehci_qh: qh_next, qtd_list
* ehci_qtd: qtd_list
*
@@ -47,13 +47,6 @@ struct ehci_stats {
#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */
struct ehci_hcd { /* one per controller */
-
- /* glue to PCI and HCD framework */
- struct usb_hcd hcd; /* must come first! */
- struct ehci_caps __iomem *caps;
- struct ehci_regs __iomem *regs;
- __u32 hcs_params; /* cached register copy */
-
spinlock_t lock;
/* async schedule support */
@@ -91,6 +84,11 @@ struct ehci_hcd { /* one per controller */
unsigned is_arc_rh_tt:1; /* ARC roothub with TT */
+ /* glue to PCI and HCD framework */
+ struct ehci_caps __iomem *caps;
+ struct ehci_regs __iomem *regs;
+ __u32 hcs_params; /* cached register copy */
+
/* irq statistics */
#ifdef EHCI_STATS
struct ehci_stats stats;
@@ -100,8 +98,15 @@ struct ehci_hcd { /* one per controller */
#endif
};
-/* unwrap an HCD pointer to get an EHCI_HCD pointer */
-#define hcd_to_ehci(hcd_ptr) container_of(hcd_ptr, struct ehci_hcd, hcd)
+/* convert between an HCD pointer and the corresponding EHCI_HCD */
+static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd)
+{
+ return (struct ehci_hcd *) (hcd->hcd_priv);
+}
+static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci)
+{
+ return container_of ((void *) ehci, struct usb_hcd, hcd_priv);
+}
enum ehci_timer_action {
@@ -259,6 +264,30 @@ struct ehci_regs {
#define PORT_CONNECT (1<<0) /* device connected */
} __attribute__ ((packed));
+/* Appendix C, Debug port ... intended for use with special "debug devices"
+ * that can help if there's no serial console. (nonstandard enumeration.)
+ */
+struct ehci_dbg_port {
+ u32 control;
+#define DBGP_OWNER (1<<30)
+#define DBGP_ENABLED (1<<28)
+#define DBGP_DONE (1<<16)
+#define DBGP_INUSE (1<<10)
+#define DBGP_ERRCODE(x) (((x)>>7)&0x0f)
+# define DBGP_ERR_BAD 1
+# define DBGP_ERR_SIGNAL 2
+#define DBGP_ERROR (1<<6)
+#define DBGP_GO (1<<5)
+#define DBGP_OUT (1<<4)
+#define DBGP_LEN(x) (((x)>>0)&0x0f)
+ u32 pids;
+#define DBGP_PID_GET(x) (((x)>>16)&0xff)
+#define DBGP_PID_SET(data,tok) (((data)<<8)|(tok));
+ u32 data03;
+ u32 data47;
+ u32 address;
+#define DBGP_EPADDR(dev,ep) (((dev)<<8)|(ep));
+} __attribute__ ((packed));
/*-------------------------------------------------------------------------*/
@@ -430,6 +459,7 @@ struct ehci_iso_stream {
struct list_head td_list; /* queued itds/sitds */
struct list_head free_list; /* list of unused itds/sitds */
struct usb_device *udev;
+ struct usb_host_endpoint *ep;
/* output of (re)scheduling */
unsigned long start; /* jiffies */
diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c
index 770c8709e6fabe..4b12be822bd4e4 100644
--- a/drivers/usb/host/hc_crisv10.c
+++ b/drivers/usb/host/hc_crisv10.c
@@ -113,17 +113,17 @@ static __u8 root_hub_dev_des[] =
{
0x12, /* __u8 bLength; */
0x01, /* __u8 bDescriptorType; Device */
- 0x00, /* __u16 bcdUSB; v1.0 */
+ 0x00, /* __le16 bcdUSB; v1.0 */
0x01,
0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
0x00, /* __u8 bDeviceSubClass; */
0x00, /* __u8 bDeviceProtocol; */
0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
- 0x00, /* __u16 idVendor; */
+ 0x00, /* __le16 idVendor; */
0x00,
- 0x00, /* __u16 idProduct; */
+ 0x00, /* __le16 idProduct; */
0x00,
- 0x00, /* __u16 bcdDevice; */
+ 0x00, /* __le16 bcdDevice; */
0x00,
0x00, /* __u8 iManufacturer; */
0x02, /* __u8 iProduct; */
@@ -136,7 +136,7 @@ static __u8 root_hub_config_des[] =
{
0x09, /* __u8 bLength; */
0x02, /* __u8 bDescriptorType; Configuration */
- 0x19, /* __u16 wTotalLength; */
+ 0x19, /* __le16 wTotalLength; */
0x00,
0x01, /* __u8 bNumInterfaces; */
0x01, /* __u8 bConfigurationValue; */
@@ -160,7 +160,7 @@ static __u8 root_hub_config_des[] =
0x05, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */
+ 0x08, /* __le16 ep_wMaxPacketSize; 8 Bytes */
0x00,
0xff /* __u8 ep_bInterval; 255 ms */
};
@@ -479,8 +479,6 @@ static int etrax_usb_submit_isoc_urb(struct urb *urb);
static int etrax_usb_submit_urb(struct urb *urb, int mem_flags);
static int etrax_usb_unlink_urb(struct urb *urb, int status);
static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
-static int etrax_usb_allocate_dev(struct usb_device *usb_dev);
-static int etrax_usb_deallocate_dev(struct usb_device *usb_dev);
static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs);
static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs);
@@ -512,8 +510,6 @@ static void etrax_usb_hc_cleanup(void);
static struct usb_operations etrax_usb_device_operations =
{
- .allocate = etrax_usb_allocate_dev,
- .deallocate = etrax_usb_deallocate_dev,
.get_frame_number = etrax_usb_get_frame_number,
.submit_urb = etrax_usb_submit_urb,
.unlink_urb = etrax_usb_unlink_urb,
@@ -1579,20 +1575,6 @@ static int etrax_usb_get_frame_number(struct usb_device *usb_dev)
return (*R_USB_FM_NUMBER & 0x7ff);
}
-static int etrax_usb_allocate_dev(struct usb_device *usb_dev)
-{
- DBFENTER;
- DBFEXIT;
- return 0;
-}
-
-static int etrax_usb_deallocate_dev(struct usb_device *usb_dev)
-{
- DBFENTER;
- DBFEXIT;
- return 0;
-}
-
static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc, struct pt_regs *regs)
{
DBFENTER;
@@ -4546,7 +4528,7 @@ static int __init etrax_usb_hc_init(void)
usb_rh->speed = USB_SPEED_FULL;
usb_rh->devnum = 1;
hc->bus->devnum_next = 2;
- usb_rh->epmaxpacketin[0] = usb_rh->epmaxpacketout[0] = 64;
+ usb_rh->ep0.desc.wMaxPacketSize = __const_cpu_to_le16(64);
usb_get_device_descriptor(usb_rh, USB_DT_DEVICE_SIZE);
usb_new_device(usb_rh);
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 653bfce0ceafb0..45053ca193cd7d 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -676,19 +676,23 @@ done:
static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
-static inline void create_debug_files (struct ohci_hcd *bus)
+static inline void create_debug_files (struct ohci_hcd *ohci)
{
- class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_async);
- class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
- class_device_create_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
- ohci_dbg (bus, "created debug files\n");
+ struct class_device *cldev = &ohci_to_hcd(ohci)->self.class_dev;
+
+ class_device_create_file(cldev, &class_device_attr_async);
+ class_device_create_file(cldev, &class_device_attr_periodic);
+ class_device_create_file(cldev, &class_device_attr_registers);
+ ohci_dbg (ohci, "created debug files\n");
}
-static inline void remove_debug_files (struct ohci_hcd *bus)
+static inline void remove_debug_files (struct ohci_hcd *ohci)
{
- class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_async);
- class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_periodic);
- class_device_remove_file(&bus->hcd.self.class_dev, &class_device_attr_registers);
+ struct class_device *cldev = &ohci_to_hcd(ohci)->self.class_dev;
+
+ class_device_remove_file(cldev, &class_device_attr_async);
+ class_device_remove_file(cldev, &class_device_attr_periodic);
+ class_device_remove_file(cldev, &class_device_attr_registers);
}
#endif
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index a4d99857062ac2..8ed782088b24c9 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -165,6 +165,7 @@ MODULE_PARM_DESC (no_handshake, "true (not default) disables BIOS handshake");
*/
static int ohci_urb_enqueue (
struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep,
struct urb *urb,
int mem_flags
) {
@@ -181,7 +182,7 @@ static int ohci_urb_enqueue (
#endif
/* every endpoint has a ed, locate and maybe (re)initialize it */
- if (! (ed = ed_get (ohci, urb->dev, pipe, urb->interval)))
+ if (! (ed = ed_get (ohci, ep, urb->dev, pipe, urb->interval)))
return -ENOMEM;
/* for the private part of the URB we need the number of TDs (size) */
@@ -239,7 +240,7 @@ static int ohci_urb_enqueue (
spin_lock_irqsave (&ohci->lock, flags);
/* don't submit to a dead HC */
- if (!HCD_IS_RUNNING(ohci->hcd.state)) {
+ if (!HCD_IS_RUNNING(hcd->state)) {
retval = -ENODEV;
goto fail;
}
@@ -307,7 +308,7 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
#endif
spin_lock_irqsave (&ohci->lock, flags);
- if (HCD_IS_RUNNING(ohci->hcd.state)) {
+ if (HCD_IS_RUNNING(hcd->state)) {
urb_priv_t *urb_priv;
/* Unless an IRQ completed the unlink while it was being
@@ -338,28 +339,23 @@ static int ohci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
*/
static void
-ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep)
+ohci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int epnum = ep & USB_ENDPOINT_NUMBER_MASK;
unsigned long flags;
- struct ed *ed;
+ struct ed *ed = ep->hcpriv;
unsigned limit = 1000;
/* ASSERT: any requests/urbs are being unlinked */
/* ASSERT: nobody can be submitting urbs for this any more */
- epnum <<= 1;
- if (epnum != 0 && !(ep & USB_DIR_IN))
- epnum |= 1;
+ if (!ed)
+ return;
rescan:
spin_lock_irqsave (&ohci->lock, flags);
- ed = dev->ep [epnum];
- if (!ed)
- goto done;
- if (!HCD_IS_RUNNING (ohci->hcd.state)) {
+ if (!HCD_IS_RUNNING (hcd->state)) {
sanitize:
ed->state = ED_IDLE;
finish_unlinks (ohci, 0, NULL);
@@ -387,14 +383,13 @@ sanitize:
/* caller was supposed to have unlinked any requests;
* that's not our job. can't recover; must leak ed.
*/
- ohci_err (ohci, "leak ed %p (#%d) state %d%s\n",
- ed, epnum, ed->state,
+ ohci_err (ohci, "leak ed %p (#%02x) state %d%s\n",
+ ed, ep->desc.bEndpointAddress, ed->state,
list_empty (&ed->td_list) ? "" : " (has tds)");
td_free (ohci, ed->dummy);
break;
}
- dev->ep [epnum] = NULL;
-done:
+ ep->hcpriv = NULL;
spin_unlock_irqrestore (&ohci->lock, flags);
return;
}
@@ -421,17 +416,18 @@ static void ohci_usb_reset (struct ohci_hcd *ohci)
static int ohci_init (struct ohci_hcd *ohci)
{
- u32 temp;
int ret;
disable (ohci);
- ohci->regs = ohci->hcd.regs;
+ ohci->regs = ohci_to_hcd(ohci)->regs;
ohci->next_statechange = jiffies;
#ifndef IR_DISABLE
/* SMM owns the HC? not for long! */
if (!no_handshake && ohci_readl (ohci,
&ohci->regs->control) & OHCI_CTRL_IR) {
+ u32 temp;
+
ohci_dbg (ohci, "USB HC TakeOver from BIOS/SMM\n");
/* this timeout is arbitrary. we make it long, so systems
@@ -445,7 +441,8 @@ static int ohci_init (struct ohci_hcd *ohci)
while (ohci_readl (ohci, &ohci->regs->control) & OHCI_CTRL_IR) {
msleep (10);
if (--temp == 0) {
- ohci_err (ohci, "USB HC TakeOver failed!\n");
+ ohci_err (ohci, "USB HC takeover failed!"
+ " (BIOS/SMM bug)\n");
return -EBUSY;
}
}
@@ -461,13 +458,13 @@ static int ohci_init (struct ohci_hcd *ohci)
if (ohci->hcca)
return 0;
- ohci->hcca = dma_alloc_coherent (ohci->hcd.self.controller,
+ ohci->hcca = dma_alloc_coherent (ohci_to_hcd(ohci)->self.controller,
sizeof *ohci->hcca, &ohci->hcca_dma, 0);
if (!ohci->hcca)
return -ENOMEM;
if ((ret = ohci_mem_init (ohci)) < 0)
- ohci_stop (&ohci->hcd);
+ ohci_stop (ohci_to_hcd(ohci));
return ret;
@@ -512,7 +509,7 @@ static int ohci_run (struct ohci_hcd *ohci)
if (ohci->hc_control & OHCI_CTRL_RWC
&& !(ohci->flags & OHCI_QUIRK_AMD756))
- ohci->hcd.can_wakeup = 1;
+ ohci_to_hcd(ohci)->can_wakeup = 1;
switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_OPER:
@@ -610,7 +607,7 @@ retry:
ohci->hc_control &= OHCI_CTRL_RWC;
ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
- ohci->hcd.state = USB_STATE_RUNNING;
+ ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
/* wake on ConnectStatusChange, matching external hubs */
ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);
@@ -650,12 +647,12 @@ retry:
// POTPGT delay is bits 24-31, in 2 ms units.
mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
- bus = hcd_to_bus (&ohci->hcd);
- ohci->hcd.state = USB_STATE_RUNNING;
+ bus = &ohci_to_hcd(ohci)->self;
+ ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
ohci_dump (ohci, 1);
- udev = hcd_to_bus (&ohci->hcd)->root_hub;
+ udev = bus->root_hub;
if (udev) {
return 0;
}
@@ -670,7 +667,7 @@ retry:
}
udev->speed = USB_SPEED_FULL;
- if (hcd_register_root (udev, &ohci->hcd) != 0) {
+ if (hcd_register_root (udev, ohci_to_hcd(ohci)) != 0) {
usb_put_dev (udev);
disable (ohci);
ohci->hc_control &= ~OHCI_CTRL_HCFS;
@@ -745,11 +742,11 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
if (ohci->ed_rm_list)
finish_unlinks (ohci, ohci_frame_no(ohci), ptregs);
if ((ints & OHCI_INTR_SF) != 0 && !ohci->ed_rm_list
- && HCD_IS_RUNNING(ohci->hcd.state))
+ && HCD_IS_RUNNING(hcd->state))
ohci_writel (ohci, OHCI_INTR_SF, &regs->intrdisable);
spin_unlock (&ohci->lock);
- if (HCD_IS_RUNNING(ohci->hcd.state)) {
+ if (HCD_IS_RUNNING(hcd->state)) {
ohci_writel (ohci, ints, &regs->intrstatus);
ohci_writel (ohci, OHCI_INTR_MIE, &regs->intrenable);
// flush those writes
@@ -767,7 +764,7 @@ static void ohci_stop (struct usb_hcd *hcd)
ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n",
hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
- ohci->hcd.state);
+ hcd->state);
ohci_dump (ohci, 1);
flush_scheduled_work();
@@ -778,7 +775,7 @@ static void ohci_stop (struct usb_hcd *hcd)
remove_debug_files (ohci);
ohci_mem_cleanup (ohci);
if (ohci->hcca) {
- dma_free_coherent (ohci->hcd.self.controller,
+ dma_free_coherent (hcd->self.controller,
sizeof *ohci->hcca,
ohci->hcca, ohci->hcca_dma);
ohci->hcca = NULL;
@@ -797,7 +794,7 @@ static int ohci_restart (struct ohci_hcd *ohci)
int temp;
int i;
struct urb_priv *priv;
- struct usb_device *root = ohci->hcd.self.root_hub;
+ struct usb_device *root = ohci_to_hcd(ohci)->self.root_hub;
/* mark any devices gone, so they do nothing till khubd disconnects.
* recycle any "live" eds/tds (and urbs) right away.
@@ -908,13 +905,3 @@ MODULE_LICENSE ("GPL");
)
#error "missing bus glue for ohci-hcd"
#endif
-
-#if !defined(HAVE_HNP) && defined(CONFIG_USB_OTG)
-
-#warning non-OTG configuration, too many HCDs
-
-static void start_hnp(struct ohci_hcd *ohci)
-{
- /* "can't happen" */
-}
-#endif
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c
index 8f40bfa42d763d..1c296c3adcbae6 100644
--- a/drivers/usb/host/ohci-hub.c
+++ b/drivers/usb/host/ohci-hub.c
@@ -73,7 +73,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
ohci_dbg (ohci, "suspend root hub\n");
/* First stop any processing */
- ohci->hcd.state = USB_STATE_QUIESCING;
+ hcd->state = USB_STATE_QUIESCING;
if (ohci->hc_control & OHCI_SCHED_ENABLES) {
int limit;
@@ -103,7 +103,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
&ohci->regs->intrstatus);
/* maybe resume can wake root hub */
- if (ohci->hcd.remote_wakeup)
+ if (hcd->remote_wakeup)
ohci->hc_control |= OHCI_CTRL_RWE;
else
ohci->hc_control &= ~OHCI_CTRL_RWE;
@@ -119,7 +119,7 @@ static int ohci_hub_suspend (struct usb_hcd *hcd)
done:
if (status == 0)
- ohci->hcd.state = HCD_STATE_SUSPENDED;
+ hcd->state = HCD_STATE_SUSPENDED;
spin_unlock_irqrestore (&ohci->lock, flags);
return status;
}
@@ -198,7 +198,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
}
/* Some controllers (lucent) need extra-long delays */
- ohci->hcd.state = USB_STATE_RESUMING;
+ hcd->state = USB_STATE_RESUMING;
mdelay (20 /* usb 11.5.1.10 */ + 15);
temp = ohci_readl (ohci, &ohci->regs->control);
@@ -231,7 +231,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
msleep (3);
temp = OHCI_CONTROL_INIT | OHCI_USB_OPER;
- if (ohci->hcd.can_wakeup)
+ if (hcd->can_wakeup)
temp |= OHCI_CTRL_RWC;
ohci->hc_control = temp;
ohci_writel (ohci, temp, &ohci->regs->control);
@@ -261,8 +261,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
temp |= OHCI_BLF;
}
}
- if (hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs
- || hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs)
+ if (hcd->self.bandwidth_isoc_reqs || hcd->self.bandwidth_int_reqs)
enables |= OHCI_CTRL_PLE|OHCI_CTRL_IE;
if (enables) {
ohci_dbg (ohci, "restarting schedules ... %08x\n", enables);
@@ -273,7 +272,7 @@ static int ohci_hub_resume (struct usb_hcd *hcd)
(void) ohci_readl (ohci, &ohci->regs->control);
}
- ohci->hcd.state = USB_STATE_RUNNING;
+ hcd->state = USB_STATE_RUNNING;
return 0;
}
@@ -314,7 +313,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
* letting khubd or root hub timer see state changes.
*/
if ((ohci->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_OPER
- || !HCD_IS_RUNNING(ohci->hcd.state)) {
+ || !HCD_IS_RUNNING(hcd->state)) {
can_suspend = 0;
goto done;
}
@@ -356,7 +355,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
*/
if (!(status & RH_PS_CCS))
continue;
- if ((status & RH_PS_PSS) && ohci->hcd.remote_wakeup)
+ if ((status & RH_PS_PSS) && hcd->remote_wakeup)
continue;
can_suspend = 0;
}
@@ -378,8 +377,8 @@ done:
&& usb_trylock_device (hcd->self.root_hub)
) {
ohci_vdbg (ohci, "autosuspend\n");
- (void) ohci_hub_suspend (&ohci->hcd);
- ohci->hcd.state = USB_STATE_RUNNING;
+ (void) ohci_hub_suspend (hcd);
+ hcd->state = USB_STATE_RUNNING;
usb_unlock_device (hcd->self.root_hub);
}
#endif
@@ -613,8 +612,8 @@ static int ohci_hub_control (
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
#ifdef CONFIG_USB_OTG
- if (ohci->hcd.self.otg_port == (wIndex + 1)
- && ohci->hcd.self.b_hnp_enable)
+ if (hcd->self.otg_port == (wIndex + 1)
+ && hcd->self.b_hnp_enable)
start_hnp(ohci);
else
#endif
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index a787c8f88349a4..c00324861050bb 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -106,23 +106,22 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
retval = -ENOMEM;
goto err1;
}
-
- hcd = driver->hcd_alloc ();
- if (hcd == NULL){
- pr_debug ("hcd_alloc failed");
+ if(dev->resource[1].flags != IORESOURCE_IRQ){
+ pr_debug ("resource[1] is not IORESOURCE_IRQ");
retval = -ENOMEM;
goto err1;
}
+
- if(dev->resource[1].flags != IORESOURCE_IRQ){
- pr_debug ("resource[1] is not IORESOURCE_IRQ");
+ hcd = usb_create_hcd (driver);
+ if (hcd == NULL){
+ pr_debug ("hcd_alloc failed");
retval = -ENOMEM;
goto err1;
}
+ ohci_hcd_init(hcd_to_ohci(hcd));
- hcd->driver = (struct hc_driver *) driver;
- hcd->description = driver->description;
hcd->irq = dev->resource[1].start;
hcd->regs = addr;
hcd->self.controller = &dev->dev;
@@ -130,29 +129,21 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
retval = hcd_buffer_create (hcd);
if (retval != 0) {
pr_debug ("pool alloc fail");
- goto err1;
+ goto err2;
}
retval = request_irq (hcd->irq, usb_hcd_lh7a404_hcim_irq, SA_INTERRUPT,
- hcd->description, hcd);
+ hcd->driver->description, hcd);
if (retval != 0) {
pr_debug("request_irq failed");
retval = -EBUSY;
- goto err2;
+ goto err3;
}
pr_debug ("%s (LH7A404) at 0x%p, irq %d",
- hcd->description, hcd->regs, hcd->irq);
+ hcd->driver->description, hcd->regs, hcd->irq);
- usb_bus_init (&hcd->self);
- hcd->self.op = &usb_hcd_operations;
- hcd->self.release = &usb_hcd_release;
- hcd->self.hcpriv = (void *) hcd;
hcd->self.bus_name = "lh7a404";
- hcd->product_desc = "LH7A404 OHCI";
-
- INIT_LIST_HEAD (&hcd->dev_list);
-
usb_register_bus (&hcd->self);
if ((retval = driver->start (hcd)) < 0)
@@ -164,10 +155,11 @@ int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
*hcd_out = hcd;
return 0;
- err2:
+ err3:
hcd_buffer_destroy (hcd);
+ err2:
+ usb_put_hcd(hcd);
err1:
- kfree(hcd);
lh7a404_stop_hc(dev);
release_mem_region(dev->resource[0].start,
dev->resource[0].end
@@ -228,7 +220,7 @@ ohci_lh7a404_start (struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run (ohci)) < 0) {
- err ("can't start %s", ohci->hcd.self.bus_name);
+ err ("can't start %s", hcd->self.bus_name);
ohci_stop (hcd);
return ret;
}
@@ -239,6 +231,8 @@ ohci_lh7a404_start (struct usb_hcd *hcd)
static const struct hc_driver ohci_lh7a404_hc_driver = {
.description = hcd_name,
+ .product_desc = "LH7A404 OHCI",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
/*
* generic hardware linkage
@@ -257,11 +251,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
.stop = ohci_stop,
/*
- * memory lifecycle (except per-request)
- */
- .hcd_alloc = ohci_hcd_alloc,
-
- /*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ohci_urb_enqueue,
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index 705825bff39ff7..e55682b4919d0b 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -23,34 +23,27 @@
/*-------------------------------------------------------------------------*/
-static struct usb_hcd *ohci_hcd_alloc (void)
+static void ohci_hcd_init (struct ohci_hcd *ohci)
{
- struct ohci_hcd *ohci;
-
- ohci = (struct ohci_hcd *) kmalloc (sizeof *ohci, GFP_KERNEL);
- if (ohci != 0) {
- memset (ohci, 0, sizeof (struct ohci_hcd));
- ohci->hcd.product_desc = "OHCI Host Controller";
- ohci->next_statechange = jiffies;
- spin_lock_init (&ohci->lock);
- INIT_LIST_HEAD (&ohci->pending);
- INIT_WORK (&ohci->rh_resume, ohci_rh_resume, &ohci->hcd);
- return &ohci->hcd;
- }
- return NULL;
+ ohci->next_statechange = jiffies;
+ spin_lock_init (&ohci->lock);
+ INIT_LIST_HEAD (&ohci->pending);
+ INIT_WORK (&ohci->rh_resume, ohci_rh_resume, ohci_to_hcd(ohci));
}
/*-------------------------------------------------------------------------*/
static int ohci_mem_init (struct ohci_hcd *ohci)
{
- ohci->td_cache = dma_pool_create ("ohci_td", ohci->hcd.self.controller,
+ ohci->td_cache = dma_pool_create ("ohci_td",
+ ohci_to_hcd(ohci)->self.controller,
sizeof (struct td),
32 /* byte alignment */,
0 /* no page-crossing issues */);
if (!ohci->td_cache)
return -ENOMEM;
- ohci->ed_cache = dma_pool_create ("ohci_ed", ohci->hcd.self.controller,
+ ohci->ed_cache = dma_pool_create ("ohci_ed",
+ ohci_to_hcd(ohci)->self.controller,
sizeof (struct ed),
16 /* byte alignment */,
0 /* no page-crossing issues */);
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index e3f2f2a3567166..2e9c5c07942dc9 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -157,7 +157,7 @@ static int omap_1510_local_bus_init(void)
static void start_hnp(struct ohci_hcd *ohci)
{
- const unsigned port = ohci->hcd.self.otg_port - 1;
+ const unsigned port = ohci_to_hcd(ohci)->self.otg_port - 1;
unsigned long flags;
otg_start_hnp(ohci->transceiver);
@@ -181,7 +181,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
dev_dbg(&pdev->dev, "starting USB Controller\n");
if (config->otg) {
- ohci->hcd.self.otg_port = config->otg;
+ ohci_to_hcd(ohci)->self.otg_port = config->otg;
/* default/minimum OTG power budget: 8 mA */
ohci->power_budget = 8;
}
@@ -198,7 +198,7 @@ static int omap_start_hc(struct ohci_hcd *ohci, struct platform_device *pdev)
ohci->transceiver = otg_get_transceiver();
if (ohci->transceiver) {
int status = otg_set_host(ohci->transceiver,
- &ohci->hcd.self);
+ &ohci_to_hcd(ohci)->self);
dev_dbg(&pdev->dev, "init %s transceiver, status %d\n",
ohci->transceiver->label, status);
if (status) {
@@ -293,7 +293,7 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
return -EBUSY;
}
- hcd = driver->hcd_alloc ();
+ hcd = usb_create_hcd (driver);
if (hcd == NULL){
dev_dbg(&pdev->dev, "hcd_alloc failed\n");
retval = -ENOMEM;
@@ -301,41 +301,33 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
}
dev_set_drvdata(&pdev->dev, hcd);
ohci = hcd_to_ohci(hcd);
+ ohci_hcd_init(ohci);
- hcd->driver = (struct hc_driver *) driver;
- hcd->description = driver->description;
hcd->irq = pdev->resource[1].start;
hcd->regs = (void *)pdev->resource[0].start;
hcd->self.controller = &pdev->dev;
retval = omap_start_hc(ohci, pdev);
if (retval < 0)
- goto err1;
+ goto err2;
retval = hcd_buffer_create (hcd);
if (retval != 0) {
dev_dbg(&pdev->dev, "pool alloc fail\n");
- goto err1;
+ goto err2;
}
retval = request_irq (hcd->irq, usb_hcd_irq,
- SA_INTERRUPT, hcd->description, hcd);
+ SA_INTERRUPT, hcd->driver->description, hcd);
if (retval != 0) {
dev_dbg(&pdev->dev, "request_irq failed\n");
retval = -EBUSY;
- goto err2;
+ goto err3;
}
dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
- usb_bus_init (&hcd->self);
- hcd->self.op = &usb_hcd_operations;
- hcd->self.release = &usb_hcd_release;
- hcd->self.hcpriv = (void *) hcd;
hcd->self.bus_name = pdev->dev.bus_id;
- hcd->product_desc = "OMAP OHCI";
-
- INIT_LIST_HEAD (&hcd->dev_list);
usb_register_bus (&hcd->self);
if ((retval = driver->start (hcd)) < 0)
@@ -346,16 +338,17 @@ int usb_hcd_omap_probe (const struct hc_driver *driver,
return 0;
- err2:
+ err3:
hcd_buffer_destroy (hcd);
+ err2:
+ dev_set_drvdata(&pdev->dev, NULL);
+ usb_put_hcd(hcd);
err1:
- kfree(hcd);
omap_stop_hc(pdev);
release_mem_region(pdev->resource[0].start,
pdev->resource[0].end - pdev->resource[0].start + 1);
- dev_set_drvdata(&pdev->dev, 0);
return retval;
}
@@ -419,7 +412,7 @@ ohci_omap_start (struct usb_hcd *hcd)
writel(OHCI_CTRL_RWC, &ohci->regs->control);
if ((ret = ohci_run (ohci)) < 0) {
- err ("can't start %s", ohci->hcd.self.bus_name);
+ err ("can't start %s", hcd->self.bus_name);
ohci_stop (hcd);
return ret;
}
@@ -430,6 +423,8 @@ ohci_omap_start (struct usb_hcd *hcd)
static const struct hc_driver ohci_omap_hc_driver = {
.description = hcd_name,
+ .product_desc = "OMAP OHCI",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
/*
* generic hardware linkage
@@ -444,11 +439,6 @@ static const struct hc_driver ohci_omap_hc_driver = {
.stop = ohci_stop,
/*
- * memory lifecycle (except per-request)
- */
- .hcd_alloc = ohci_hcd_alloc,
-
- /*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ohci_urb_enqueue,
@@ -513,19 +503,20 @@ static int ohci_omap_suspend(struct device *dev, u32 state, u32 level)
return 0;
dev_dbg(dev, "suspend to %d\n", state);
- down(&ohci->hcd.self.root_hub->serialize);
- status = ohci_hub_suspend(&ohci->hcd);
+ down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
+ status = ohci_hub_suspend(ohci_to_hcd(ohci));
if (status == 0) {
if (state >= 4) {
/* power off + reset */
OTG_SYSCON_2_REG &= ~UHOST_EN;
- ohci->hcd.self.root_hub->state = USB_STATE_SUSPENDED;
+ ohci_to_hcd(ohci)->self.root_hub->state =
+ USB_STATE_SUSPENDED;
state = 4;
}
- ohci->hcd.state = HCD_STATE_SUSPENDED;
+ ohci_to_hcd(ohci)->state = HCD_STATE_SUSPENDED;
dev->power.power_state = state;
}
- up(&ohci->hcd.self.root_hub->serialize);
+ up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
return status;
}
@@ -547,11 +538,11 @@ static int ohci_omap_resume(struct device *dev, u32 level)
dev_dbg(dev, "resume from %d\n", dev->power.power_state);
#ifdef CONFIG_USB_SUSPEND
/* get extra cleanup even if remote wakeup isn't in use */
- status = usb_resume_device(ohci->hcd.self.root_hub);
+ status = usb_resume_device(ohci_to_hcd(ohci)->self.root_hub);
#else
- down(&ohci->hcd.self.root_hub->serialize);
- status = ohci_hub_resume(&ohci->hcd);
- up(&ohci->hcd.self.root_hub->serialize);
+ down(&ohci_to_hcd(ohci)->self.root_hub->serialize);
+ status = ohci_hub_resume(ohci_to_hcd(ohci));
+ up(&ohci_to_hcd(ohci)->self.root_hub->serialize);
#endif
if (status == 0)
dev->power.power_state = 0;
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 89624afecd1ad8..b611582e6bcfb9 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -35,6 +35,7 @@ ohci_pci_reset (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ ohci_hcd_init (ohci);
return ohci_init (ohci);
}
@@ -172,6 +173,8 @@ static int ohci_pci_resume (struct usb_hcd *hcd)
static const struct hc_driver ohci_pci_hc_driver = {
.description = hcd_name,
+ .product_desc = "OHCI Host Controller",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
/*
* generic hardware linkage
@@ -191,11 +194,6 @@ static const struct hc_driver ohci_pci_hc_driver = {
.stop = ohci_stop,
/*
- * memory lifecycle (except per-request)
- */
- .hcd_alloc = ohci_hcd_alloc,
-
- /*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ohci_urb_enqueue,
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 44582d077c1e9f..8283c1aafcf9f6 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -206,21 +206,20 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
goto err1;
}
- hcd = driver->hcd_alloc ();
- if (hcd == NULL){
- pr_debug ("hcd_alloc failed");
+ if(dev->resource[1].flags != IORESOURCE_IRQ){
+ pr_debug ("resource[1] is not IORESOURCE_IRQ");
retval = -ENOMEM;
goto err1;
}
- if(dev->resource[1].flags != IORESOURCE_IRQ){
- pr_debug ("resource[1] is not IORESOURCE_IRQ");
+ hcd = usb_create_hcd (driver);
+ if (hcd == NULL){
+ pr_debug ("hcd_alloc failed");
retval = -ENOMEM;
goto err1;
}
+ ohci_hcd_init(hcd_to_ohci(hcd));
- hcd->driver = (struct hc_driver *) driver;
- hcd->description = driver->description;
hcd->irq = dev->resource[1].start;
hcd->regs = addr;
hcd->self.controller = &dev->dev;
@@ -228,29 +227,21 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
retval = hcd_buffer_create (hcd);
if (retval != 0) {
pr_debug ("pool alloc fail");
- goto err1;
+ goto err2;
}
retval = request_irq (hcd->irq, usb_hcd_irq, SA_INTERRUPT,
- hcd->description, hcd);
+ hcd->driver->description, hcd);
if (retval != 0) {
pr_debug("request_irq(%d) failed with retval %d\n",hcd->irq,retval);
retval = -EBUSY;
- goto err2;
+ goto err3;
}
pr_debug ("%s (pxa27x) at 0x%p, irq %d",
- hcd->description, hcd->regs, hcd->irq);
+ hcd->driver->description, hcd->regs, hcd->irq);
- usb_bus_init (&hcd->self);
- hcd->self.op = &usb_hcd_operations;
- hcd->self.release = &usb_hcd_release;
- hcd->self.hcpriv = (void *) hcd;
hcd->self.bus_name = "pxa27x";
- hcd->product_desc = "PXA27x OHCI";
-
- INIT_LIST_HEAD (&hcd->dev_list);
-
usb_register_bus (&hcd->self);
if ((retval = driver->start (hcd)) < 0) {
@@ -261,10 +252,11 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
*hcd_out = hcd;
return 0;
- err2:
+ err3:
hcd_buffer_destroy (hcd);
+ err2:
+ usb_put_hcd(hcd);
err1:
- kfree(hcd);
pxa27x_stop_hc(dev);
release_mem_region(dev->resource[0].start,
dev->resource[0].end
@@ -325,7 +317,7 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run (ohci)) < 0) {
- err ("can't start %s", ohci->hcd.self.bus_name);
+ err ("can't start %s", hcd->self.bus_name);
ohci_stop (hcd);
return ret;
}
@@ -337,6 +329,8 @@ ohci_pxa27x_start (struct usb_hcd *hcd)
static const struct hc_driver ohci_pxa27x_hc_driver = {
.description = hcd_name,
+ .product_desc = "PXA27x OHCI",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
/*
* generic hardware linkage
@@ -351,11 +345,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
.stop = ohci_stop,
/*
- * memory lifecycle (except per-request)
- */
- .hcd_alloc = ohci_hcd_alloc,
-
- /*
* managing i/o requests and associated device resources
*/
.urb_enqueue = ohci_urb_enqueue,
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 466184846350ff..c86815586886f0 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -60,10 +60,10 @@ __acquires(ohci->lock)
switch (usb_pipetype (urb->pipe)) {
case PIPE_ISOCHRONOUS:
- hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs--;
+ ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs--;
break;
case PIPE_INTERRUPT:
- hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs--;
+ ohci_to_hcd(ohci)->self.bandwidth_int_reqs--;
break;
}
@@ -73,12 +73,12 @@ __acquires(ohci->lock)
/* urb->complete() can reenter this HCD */
spin_unlock (&ohci->lock);
- usb_hcd_giveback_urb (&ohci->hcd, urb, regs);
+ usb_hcd_giveback_urb (ohci_to_hcd(ohci), urb, regs);
spin_lock (&ohci->lock);
/* stop periodic dma if it's not needed */
- if (hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs == 0
- && hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs == 0) {
+ if (ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0
+ && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0) {
ohci->hc_control &= ~(OHCI_CTRL_PLE|OHCI_CTRL_IE);
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
}
@@ -163,7 +163,7 @@ static void periodic_link (struct ohci_hcd *ohci, struct ed *ed)
}
ohci->load [i] += ed->load;
}
- hcd_to_bus (&ohci->hcd)->bandwidth_allocated += ed->load / ed->interval;
+ ohci_to_hcd(ohci)->self.bandwidth_allocated += ed->load / ed->interval;
}
/* link an ed into one of the HC chains */
@@ -172,7 +172,7 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed)
{
int branch;
- if (ohci->hcd.state == USB_STATE_QUIESCING)
+ if (ohci_to_hcd(ohci)->state == USB_STATE_QUIESCING)
return -EAGAIN;
ed->state = ED_OPER;
@@ -276,7 +276,7 @@ static void periodic_unlink (struct ohci_hcd *ohci, struct ed *ed)
}
ohci->load [i] -= ed->load;
}
- hcd_to_bus (&ohci->hcd)->bandwidth_allocated -= ed->load / ed->interval;
+ ohci_to_hcd(ohci)->self.bandwidth_allocated -= ed->load / ed->interval;
ohci_vdbg (ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
(ed->hwINFO & cpu_to_hc32 (ohci, ED_ISO)) ? "iso " : "",
@@ -386,37 +386,30 @@ static void ed_deschedule (struct ohci_hcd *ohci, struct ed *ed)
/*-------------------------------------------------------------------------*/
/* get and maybe (re)init an endpoint. init _should_ be done only as part
- * of usb_set_configuration() or usb_set_interface() ... but the USB stack
- * isn't very stateful, so we re-init whenever the HC isn't looking.
+ * of enumeration, usb_set_configuration() or usb_set_interface().
*/
static struct ed *ed_get (
struct ohci_hcd *ohci,
+ struct usb_host_endpoint *ep,
struct usb_device *udev,
unsigned int pipe,
int interval
) {
- int is_out = !usb_pipein (pipe);
- int type = usb_pipetype (pipe);
- struct hcd_dev *dev = (struct hcd_dev *) udev->hcpriv;
struct ed *ed;
- unsigned ep;
unsigned long flags;
- ep = usb_pipeendpoint (pipe) << 1;
- if (type != PIPE_CONTROL && is_out)
- ep |= 1;
-
spin_lock_irqsave (&ohci->lock, flags);
- if (!(ed = dev->ep [ep])) {
+ if (!(ed = ep->hcpriv)) {
struct td *td;
+ int is_out;
+ u32 info;
ed = ed_alloc (ohci, GFP_ATOMIC);
if (!ed) {
/* out of memory */
goto done;
}
- dev->ep [ep] = ed;
/* dummy td; end of td list for ed */
td = td_alloc (ohci, GFP_ATOMIC);
@@ -430,38 +423,39 @@ static struct ed *ed_get (
ed->hwTailP = cpu_to_hc32 (ohci, td->td_dma);
ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */
ed->state = ED_IDLE;
- ed->type = type;
- }
- /* NOTE: only ep0 currently needs this "re"init logic, during
- * enumeration (after set_address).
- */
- if (ed->state == ED_IDLE) {
- u32 info;
+ is_out = !(ep->desc.bEndpointAddress & USB_DIR_IN);
+ /* FIXME usbcore changes dev->devnum before SET_ADDRESS
+ * suceeds ... otherwise we wouldn't need "pipe".
+ */
info = usb_pipedevice (pipe);
- info |= (ep >> 1) << 7;
- info |= usb_maxpacket (udev, pipe, is_out) << 16;
+ ed->type = usb_pipetype(pipe);
+
+ info |= (ep->desc.bEndpointAddress & ~USB_DIR_IN) << 7;
+ info |= le16_to_cpu(ep->desc.wMaxPacketSize) << 16;
if (udev->speed == USB_SPEED_LOW)
info |= ED_LOWSPEED;
/* only control transfers store pids in tds */
- if (type != PIPE_CONTROL) {
+ if (ed->type != PIPE_CONTROL) {
info |= is_out ? ED_OUT : ED_IN;
- if (type != PIPE_BULK) {
+ if (ed->type != PIPE_BULK) {
/* periodic transfers... */
- if (type == PIPE_ISOCHRONOUS)
+ if (ed->type == PIPE_ISOCHRONOUS)
info |= ED_ISO;
else if (interval > 32) /* iso can be bigger */
interval = 32;
ed->interval = interval;
ed->load = usb_calc_bus_time (
udev->speed, !is_out,
- type == PIPE_ISOCHRONOUS,
- usb_maxpacket (udev, pipe, is_out))
+ ed->type == PIPE_ISOCHRONOUS,
+ le16_to_cpu(ep->desc.wMaxPacketSize))
/ 1000;
}
}
ed->hwINFO = cpu_to_hc32(ohci, info);
+
+ ep->hcpriv = ed;
}
done:
@@ -625,8 +619,8 @@ static void td_submit_urb (
*/
case PIPE_INTERRUPT:
/* ... and periodic urbs have extra accounting */
- periodic = hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs++ == 0
- && hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs == 0;
+ periodic = ohci_to_hcd(ohci)->self.bandwidth_int_reqs++ == 0
+ && ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs == 0;
/* FALLTHROUGH */
case PIPE_BULK:
info = is_out
@@ -694,8 +688,8 @@ static void td_submit_urb (
data + urb->iso_frame_desc [cnt].offset,
urb->iso_frame_desc [cnt].length, urb, cnt);
}
- periodic = hcd_to_bus (&ohci->hcd)->bandwidth_isoc_reqs++ == 0
- && hcd_to_bus (&ohci->hcd)->bandwidth_int_reqs == 0;
+ periodic = ohci_to_hcd(ohci)->self.bandwidth_isoc_reqs++ == 0
+ && ohci_to_hcd(ohci)->self.bandwidth_int_reqs == 0;
break;
}
@@ -926,7 +920,7 @@ rescan_all:
/* only take off EDs that the HC isn't using, accounting for
* frame counter wraps and EDs with partially retired TDs
*/
- if (likely (regs && HCD_IS_RUNNING(ohci->hcd.state))) {
+ if (likely (regs && HCD_IS_RUNNING(ohci_to_hcd(ohci)->state))) {
if (tick_before (tick, ed->tick)) {
skip_ed:
last = &ed->ed_next;
@@ -1008,7 +1002,7 @@ rescan_this:
/* but if there's work queued, reschedule */
if (!list_empty (&ed->td_list)) {
- if (HCD_IS_RUNNING(ohci->hcd.state))
+ if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state))
ed_schedule (ohci, ed);
}
@@ -1017,8 +1011,8 @@ rescan_this:
}
/* maybe reenable control and bulk lists */
- if (HCD_IS_RUNNING(ohci->hcd.state)
- && ohci->hcd.state != USB_STATE_QUIESCING
+ if (HCD_IS_RUNNING(ohci_to_hcd(ohci)->state)
+ && ohci_to_hcd(ohci)->state != USB_STATE_QUIESCING
&& !ohci->ed_rm_list) {
u32 command = 0, control = 0;
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index 5bb7fe44a422d2..eb656a73d2ecad 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -162,15 +162,14 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver,
sa1111_start_hc(dev);
- hcd = driver->hcd_alloc ();
+ hcd = usb_create_hcd (driver);
if (hcd == NULL){
dbg ("hcd_alloc failed");
retval = -ENOMEM;
goto err1;
}
+ ohci_hcd_init(hcd_to_ohci(hcd));
- hcd->driver = (struct hc_driver *) driver;
- hcd->description = driver->description;
hcd->irq = dev->irq[1];
hcd->regs = dev->mapbase;
hcd->self.controller = &dev->dev;
@@ -178,29 +177,21 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver,
retval = hcd_buffer_create (hcd);
if (retval != 0) {
dbg ("pool alloc fail");
- goto err1;
+ goto err2;
}
retval = request_irq (hcd->irq, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
- hcd->description, hcd);
+ hcd->driver->description, hcd);
if (retval != 0) {
dbg("request_irq failed");
retval = -EBUSY;
- goto err2;
+ goto err3;
}
info ("%s (SA-1111) at 0x%p, irq %d\n",
- hcd->description, hcd->regs, hcd->irq);
+ hcd->driver->description, hcd->regs, hcd->irq);
- usb_bus_init (&hcd->self);
- hcd->self.op = &usb_hcd_operations;
- hcd->self.release = &usb_hcd_release;
- hcd->self.hcpriv = (void *) hcd;
hcd->self.bus_name = "sa1111";
- hcd->product_desc = "SA-1111 OHCI";
-
- INIT_LIST_HEAD (&hcd->dev_list);
-
usb_register_bus (&hcd->self);
if ((retval = driver->start (hcd)) < 0)
@@ -212,10 +203,11 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver,
*hcd_out = hcd;
return 0;
- err2:
+ err3:
hcd_buffer_destroy (hcd);
+ err2:
+ usb_put_hcd(hcd);
err1:
- kfree(hcd);
sa1111_stop_hc(dev);
release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
return retval;
@@ -271,7 +263,7 @@ ohci_sa1111_start (struct usb_hcd *hcd)
return ret;
if ((ret = ohci_run (ohci)) < 0) {
- err ("can't start %s", ohci->hcd.self.bus_name);
+ err ("can't start %s", hcd->self.bus_name);
ohci_stop (hcd);
return ret;
}
@@ -282,6 +274,8 @@ ohci_sa1111_start (struct usb_hcd *hcd)
static const struct hc_driver ohci_sa1111_hc_driver = {
.description = hcd_name,
+ .product_desc = "SA-1111 OHCI",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
/*
* generic hardware linkage
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 9c384302523aa1..437e8b03ed93c7 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -345,11 +345,6 @@ typedef struct urb_priv {
*/
struct ohci_hcd {
- /*
- * framework state
- */
- struct usb_hcd hcd; /* must come first! */
-
spinlock_t lock;
/*
@@ -405,7 +400,15 @@ struct ohci_hcd {
};
-#define hcd_to_ohci(hcd_ptr) container_of(hcd_ptr, struct ohci_hcd, hcd)
+/* convert between an hcd pointer and the corresponding ohci_hcd */
+static inline struct ohci_hcd *hcd_to_ohci (struct usb_hcd *hcd)
+{
+ return (struct ohci_hcd *) (hcd->hcd_priv);
+}
+static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci)
+{
+ return container_of ((void *) ohci, struct usb_hcd, hcd_priv);
+}
/*-------------------------------------------------------------------------*/
@@ -414,13 +417,13 @@ struct ohci_hcd {
#endif /* DEBUG */
#define ohci_dbg(ohci, fmt, args...) \
- dev_dbg ((ohci)->hcd.self.controller , fmt , ## args )
+ dev_dbg (ohci_to_hcd(ohci)->self.controller , fmt , ## args )
#define ohci_err(ohci, fmt, args...) \
- dev_err ((ohci)->hcd.self.controller , fmt , ## args )
+ dev_err (ohci_to_hcd(ohci)->self.controller , fmt , ## args )
#define ohci_info(ohci, fmt, args...) \
- dev_info ((ohci)->hcd.self.controller , fmt , ## args )
+ dev_info (ohci_to_hcd(ohci)->self.controller , fmt , ## args )
#define ohci_warn(ohci, fmt, args...) \
- dev_warn ((ohci)->hcd.self.controller , fmt , ## args )
+ dev_warn (ohci_to_hcd(ohci)->self.controller , fmt , ## args )
#ifdef OHCI_VERBOSE_DEBUG
# define ohci_vdbg ohci_dbg
@@ -553,7 +556,7 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
static inline void disable (struct ohci_hcd *ohci)
{
- ohci->hcd.state = USB_STATE_HALT;
+ ohci_to_hcd(ohci)->state = USB_STATE_HALT;
}
#define FI 0x2edf /* 12000 bits per frame (-1) */
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index ac8f8990b42a14..d713d65b14ff25 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -67,7 +67,7 @@
MODULE_DESCRIPTION("SL811HS USB Host Controller Driver");
MODULE_LICENSE("GPL");
-#define DRIVER_VERSION "06 Dec 2004"
+#define DRIVER_VERSION "15 Dec 2004"
#ifndef DEBUG
@@ -90,10 +90,12 @@ static const char hcd_name[] = "sl811-hcd";
/*-------------------------------------------------------------------------*/
-static irqreturn_t sl811h_irq(int irq, void *_sl811, struct pt_regs *regs);
+static irqreturn_t sl811h_irq(int irq, void *_hcd, struct pt_regs *regs);
static void port_power(struct sl811 *sl811, int is_on)
{
+ struct usb_hcd *hcd = sl811_to_hcd(sl811);
+
/* hub is inactive unless the port is powered */
if (is_on) {
if (sl811->port1 & (1 << USB_PORT_FEAT_POWER))
@@ -101,12 +103,12 @@ static void port_power(struct sl811 *sl811, int is_on)
sl811->port1 = (1 << USB_PORT_FEAT_POWER);
sl811->irq_enable = SL11H_INTMASK_INSRMV;
- sl811->hcd.self.controller->power.power_state = PM_SUSPEND_ON;
+ hcd->self.controller->power.power_state = PM_SUSPEND_ON;
} else {
sl811->port1 = 0;
sl811->irq_enable = 0;
- sl811->hcd.state = USB_STATE_HALT;
- sl811->hcd.self.controller->power.power_state = PM_SUSPEND_DISK;
+ hcd->state = USB_STATE_HALT;
+ hcd->self.controller->power.power_state = PM_SUSPEND_DISK;
}
sl811->ctrl1 = 0;
sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
@@ -115,12 +117,12 @@ static void port_power(struct sl811 *sl811, int is_on)
if (sl811->board && sl811->board->port_power) {
/* switch VBUS, at 500mA unless hub power budget gets set */
DBG("power %s\n", is_on ? "on" : "off");
- sl811->board->port_power(sl811->hcd.self.controller, is_on);
+ sl811->board->port_power(hcd->self.controller, is_on);
}
/* reset as thoroughly as we can */
if (sl811->board && sl811->board->reset)
- sl811->board->reset(sl811->hcd.self.controller);
+ sl811->board->reset(hcd->self.controller);
sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
@@ -314,7 +316,6 @@ static inline void sofirq_off(struct sl811 *sl811)
static struct sl811h_ep *start(struct sl811 *sl811, u8 bank)
{
struct sl811h_ep *ep;
- struct sl811h_req *req;
struct urb *urb;
int fclock;
u8 control;
@@ -348,13 +349,12 @@ static struct sl811h_ep *start(struct sl811 *sl811, u8 bank)
struct sl811h_ep, schedule);
}
- if (unlikely(list_empty(&ep->queue))) {
+ if (unlikely(list_empty(&ep->hep->urb_list))) {
DBG("empty %p queue?\n", ep);
return NULL;
}
- req = container_of(ep->queue.next, struct sl811h_req, queue);
- urb = req->urb;
+ urb = container_of(ep->hep->urb_list.next, struct urb, urb_list);
control = ep->defctrl;
/* if this frame doesn't have enough time left to transfer this
@@ -432,17 +432,12 @@ static inline void start_transfer(struct sl811 *sl811)
static void finish_request(
struct sl811 *sl811,
struct sl811h_ep *ep,
- struct sl811h_req *req,
+ struct urb *urb,
struct pt_regs *regs,
int status
) __releases(sl811->lock) __acquires(sl811->lock)
{
unsigned i;
- struct urb *urb = req->urb;
-
- list_del(&req->queue);
- kfree(req);
- urb->hcpriv = NULL;
if (usb_pipecontrol(urb->pipe))
ep->nextpid = USB_PID_SETUP;
@@ -453,11 +448,11 @@ static void finish_request(
spin_unlock(&urb->lock);
spin_unlock(&sl811->lock);
- usb_hcd_giveback_urb(&sl811->hcd, urb, regs);
+ usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb, regs);
spin_lock(&sl811->lock);
/* leave active endpoints in the schedule */
- if (!list_empty(&ep->queue))
+ if (!list_empty(&ep->hep->urb_list))
return;
/* async deschedule? */
@@ -482,7 +477,7 @@ static void finish_request(
}
ep->branch = PERIODIC_SIZE;
sl811->periodic_count--;
- hcd_to_bus(&sl811->hcd)->bandwidth_allocated
+ sl811_to_hcd(sl811)->self.bandwidth_allocated
-= ep->load / ep->period;
if (ep == sl811->next_periodic)
sl811->next_periodic = ep->next;
@@ -496,7 +491,6 @@ static void
done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs)
{
u8 status;
- struct sl811h_req *req;
struct urb *urb;
int urbstat = -EINPROGRESS;
@@ -505,8 +499,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs)
status = sl811_read(sl811, bank + SL11H_PKTSTATREG);
- req = container_of(ep->queue.next, struct sl811h_req, queue);
- urb = req->urb;
+ urb = container_of(ep->hep->urb_list.next, struct urb, urb_list);
/* we can safely ignore NAKs */
if (status & SL11H_STATMASK_NAK) {
@@ -577,7 +570,7 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs)
urb->status = urbstat;
spin_unlock(&urb->lock);
- req = NULL;
+ urb = NULL;
ep->nextpid = USB_PID_ACK;
}
break;
@@ -618,9 +611,8 @@ done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs)
bank, status, ep, urbstat);
}
- if ((urbstat != -EINPROGRESS || urb->status != -EINPROGRESS)
- && req)
- finish_request(sl811, ep, req, regs, urbstat);
+ if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS))
+ finish_request(sl811, ep, urb, regs, urbstat);
}
static inline u8 checkdone(struct sl811 *sl811)
@@ -643,7 +635,7 @@ static inline u8 checkdone(struct sl811 *sl811)
ctl = sl811_read(sl811, SL811_EP_B(SL11H_HOSTCTLREG));
if (ctl & SL11H_HCTLMASK_ARM)
sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0);
- DBG("%s DONE_B: ctrl %02x sts %02x\n", ctl,
+ DBG("%s DONE_B: ctrl %02x sts %02x\n",
(ctl & SL11H_HCTLMASK_ARM) ? "timeout" : "lost",
ctl,
sl811_read(sl811, SL811_EP_B(SL11H_PKTSTATREG)));
@@ -653,9 +645,10 @@ static inline u8 checkdone(struct sl811 *sl811)
return irqstat;
}
-static irqreturn_t sl811h_irq(int irq, void *_sl811, struct pt_regs *regs)
+static irqreturn_t sl811h_irq(int irq, void *_hcd, struct pt_regs *regs)
{
- struct sl811 *sl811 = _sl811;
+ struct usb_hcd *hcd = _hcd;
+ struct sl811 *sl811 = hcd_to_sl811(hcd);
u8 irqstat;
irqreturn_t ret = IRQ_NONE;
unsigned retries = 5;
@@ -732,8 +725,8 @@ retry:
if (sl811->active_a) {
sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0);
finish_request(sl811, sl811->active_a,
- container_of(sl811->active_a->queue.next,
- struct sl811h_req, queue),
+ container_of(sl811->active_a->hep->urb_list.next,
+ struct urb, urb_list),
NULL, -ESHUTDOWN);
sl811->active_a = NULL;
}
@@ -741,8 +734,8 @@ retry:
if (sl811->active_b) {
sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0);
finish_request(sl811, sl811->active_b,
- container_of(sl811->active_b->queue.next,
- struct sl811h_req, queue),
+ container_of(sl811->active_b->hep->urb_list.next,
+ struct urb, urb_list),
NULL, -ESHUTDOWN);
sl811->active_b = NULL;
}
@@ -767,7 +760,7 @@ retry:
if (sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
start_transfer(sl811);
ret = IRQ_HANDLED;
- sl811->hcd.saw_irq = 1;
+ hcd->saw_irq = 1;
if (retries--)
goto retry;
}
@@ -816,19 +809,18 @@ static int balance(struct sl811 *sl811, u16 period, u16 load)
/*-------------------------------------------------------------------------*/
static int sl811h_urb_enqueue(
- struct usb_hcd *hcd,
- struct urb *urb,
- int mem_flags
+ struct usb_hcd *hcd,
+ struct usb_host_endpoint *hep,
+ struct urb *urb,
+ int mem_flags
) {
struct sl811 *sl811 = hcd_to_sl811(hcd);
struct usb_device *udev = urb->dev;
- struct hcd_dev *hdev = (struct hcd_dev *) udev->hcpriv;
unsigned int pipe = urb->pipe;
int is_out = !usb_pipein(pipe);
int type = usb_pipetype(pipe);
int epnum = usb_pipeendpoint(pipe);
struct sl811h_ep *ep = NULL;
- struct sl811h_req *req;
unsigned long flags;
int i;
int retval = 0;
@@ -838,36 +830,27 @@ static int sl811h_urb_enqueue(
return -ENOSPC;
#endif
- /* avoid all allocations within spinlocks: request or endpoint */
- urb->hcpriv = req = kmalloc(sizeof *req, mem_flags);
- if (!req)
- return -ENOMEM;
- req->urb = urb;
-
- i = epnum << 1;
- if (i && is_out)
- i |= 1;
- if (!hdev->ep[i])
+ /* avoid all allocations within spinlocks */
+ if (!hep->hcpriv)
ep = kcalloc(1, sizeof *ep, mem_flags);
spin_lock_irqsave(&sl811->lock, flags);
/* don't submit to a dead or disabled port */
if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
- || !HCD_IS_RUNNING(sl811->hcd.state)) {
+ || !HCD_IS_RUNNING(hcd->state)) {
retval = -ENODEV;
goto fail;
}
- if (hdev->ep[i]) {
+ if (hep->hcpriv) {
kfree(ep);
- ep = hdev->ep[i];
+ ep = hep->hcpriv;
} else if (!ep) {
retval = -ENOMEM;
goto fail;
} else {
- INIT_LIST_HEAD(&ep->queue);
INIT_LIST_HEAD(&ep->schedule);
ep->udev = usb_get_dev(udev);
ep->epnum = epnum;
@@ -911,7 +894,7 @@ static int sl811h_urb_enqueue(
break;
}
- hdev->ep[i] = ep;
+ hep->hcpriv = ep;
}
/* maybe put endpoint into schedule */
@@ -957,8 +940,7 @@ static int sl811h_urb_enqueue(
sl811->load[i] += ep->load;
}
sl811->periodic_count++;
- hcd_to_bus(&sl811->hcd)->bandwidth_allocated
- += ep->load / ep->period;
+ hcd->self.bandwidth_allocated += ep->load / ep->period;
sofirq_on(sl811);
}
@@ -966,47 +948,38 @@ static int sl811h_urb_enqueue(
spin_lock(&urb->lock);
if (urb->status != -EINPROGRESS) {
spin_unlock(&urb->lock);
- finish_request(sl811, ep, req, NULL, 0);
- req = NULL;
+ finish_request(sl811, ep, urb, NULL, 0);
retval = 0;
goto fail;
}
- list_add_tail(&req->queue, &ep->queue);
+ urb->hcpriv = hep;
spin_unlock(&urb->lock);
start_transfer(sl811);
sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable);
fail:
spin_unlock_irqrestore(&sl811->lock, flags);
- if (retval)
- kfree(req);
return retval;
}
static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
{
struct sl811 *sl811 = hcd_to_sl811(hcd);
- struct usb_device *udev = urb->dev;
- struct hcd_dev *hdev = (struct hcd_dev *) udev->hcpriv;
- unsigned int pipe = urb->pipe;
- int is_out = !usb_pipein(pipe);
+ struct usb_host_endpoint *hep = urb->hcpriv;
unsigned long flags;
- unsigned i;
struct sl811h_ep *ep;
- struct sl811h_req *req = urb->hcpriv;
int retval = 0;
- i = usb_pipeendpoint(pipe) << 1;
- if (i && is_out)
- i |= 1;
+ if (!hep)
+ return -EINVAL;
spin_lock_irqsave(&sl811->lock, flags);
- ep = hdev->ep[i];
+ ep = hep->hcpriv;
if (ep) {
/* finish right away if this urb can't be active ...
* note that some drivers wrongly expect delays
*/
- if (ep->queue.next != &req->queue) {
+ if (ep->hep->urb_list.next != &urb->urb_list) {
/* not front of queue? never active */
/* for active transfers, we expect an IRQ */
@@ -1022,7 +995,7 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
0);
sl811->active_a = NULL;
} else
- req = NULL;
+ urb = NULL;
#ifdef USE_B
} else if (sl811->active_b == ep) {
if (time_before_eq(sl811->jiffies_a, jiffies)) {
@@ -1036,14 +1009,14 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
0);
sl811->active_b = NULL;
} else
- req = NULL;
+ urb = NULL;
#endif
} else {
/* front of queue for inactive endpoint */
}
- if (req)
- finish_request(sl811, ep, req, NULL, 0);
+ if (urb)
+ finish_request(sl811, ep, urb, NULL, 0);
else
VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
(sl811->active_a == ep) ? "A" : "B");
@@ -1054,33 +1027,22 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
}
static void
-sl811h_endpoint_disable(struct usb_hcd *hcd, struct hcd_dev *hdev, int epnum)
+sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep)
{
- struct sl811 *sl811 = hcd_to_sl811(hcd);
- struct sl811h_ep *ep;
- unsigned long flags;
- int i;
+ struct sl811h_ep *ep = hep->hcpriv;
- i = (epnum & 0xf) << 1;
- if (epnum && !(epnum & USB_DIR_IN))
- i |= 1;
-
- spin_lock_irqsave(&sl811->lock, flags);
- ep = hdev->ep[i];
- hdev->ep[i] = NULL;
- spin_unlock_irqrestore(&sl811->lock, flags);
+ if (!ep)
+ return;
- if (ep) {
- /* assume we'd just wait for the irq */
- if (!list_empty(&ep->queue))
- msleep(3);
- if (!list_empty(&ep->queue))
- WARN("ep %p not empty?\n", ep);
+ /* assume we'd just wait for the irq */
+ if (!list_empty(&hep->urb_list))
+ msleep(3);
+ if (!list_empty(&hep->urb_list))
+ WARN("ep %p not empty?\n", ep);
- usb_put_dev(ep->udev);
- kfree(ep);
- }
- return;
+ usb_put_dev(ep->udev);
+ kfree(ep);
+ hep->hcpriv = 0;
}
static int
@@ -1436,7 +1398,7 @@ static int proc_sl811h_show(struct seq_file *s, void *unused)
unsigned i;
seq_printf(s, "%s\n%s version %s\nportstatus[1] = %08x\n",
- sl811->hcd.product_desc,
+ sl811_to_hcd(sl811)->product_desc,
hcd_name, DRIVER_VERSION,
sl811->port1);
@@ -1481,7 +1443,7 @@ static int proc_sl811h_show(struct seq_file *s, void *unused)
sl811_read(sl811, SL811_EP_B(SL11H_PKTSTATREG)));
seq_printf(s, "\n");
list_for_each_entry (ep, &sl811->async, schedule) {
- struct sl811h_req *req;
+ struct urb *urb;
seq_printf(s, "%s%sqh%p, ep%d%s, maxpacket %d"
" nak %d err %d\n",
@@ -1497,10 +1459,10 @@ static int proc_sl811h_show(struct seq_file *s, void *unused)
}; s;}),
ep->maxpacket,
ep->nak_count, ep->error_count);
- list_for_each_entry (req, &ep->queue, queue) {
- seq_printf(s, " urb%p, %d/%d\n", req->urb,
- req->urb->actual_length,
- req->urb->transfer_buffer_length);
+ list_for_each_entry (urb, &ep->hep->urb_list, urb_list) {
+ seq_printf(s, " urb%p, %d/%d\n", urb,
+ urb->actual_length,
+ urb->transfer_buffer_length);
}
}
if (!list_empty(&sl811->async))
@@ -1584,7 +1546,7 @@ sl811h_stop(struct usb_hcd *hcd)
struct sl811 *sl811 = hcd_to_sl811(hcd);
unsigned long flags;
- del_timer_sync(&sl811->hcd.rh_timer);
+ del_timer_sync(&hcd->rh_timer);
spin_lock_irqsave(&sl811->lock, flags);
port_power(sl811, 0);
@@ -1599,7 +1561,7 @@ sl811h_start(struct usb_hcd *hcd)
/* chip has been reset, VBUS power is off */
- udev = usb_alloc_dev(NULL, &sl811->hcd.self, 0);
+ udev = usb_alloc_dev(NULL, &hcd->self, 0);
if (!udev)
return -ENOMEM;
@@ -1607,9 +1569,9 @@ sl811h_start(struct usb_hcd *hcd)
hcd->state = USB_STATE_RUNNING;
if (sl811->board)
- sl811->hcd.can_wakeup = sl811->board->can_wakeup;
+ hcd->can_wakeup = sl811->board->can_wakeup;
- if (hcd_register_root(udev, &sl811->hcd) != 0) {
+ if (hcd_register_root(udev, hcd) != 0) {
usb_put_dev(udev);
sl811h_stop(hcd);
return -ENODEV;
@@ -1625,6 +1587,7 @@ sl811h_start(struct usb_hcd *hcd)
static struct hc_driver sl811h_hc_driver = {
.description = hcd_name,
+ .hcd_priv_size = sizeof(struct sl811),
/*
* generic hardware linkage
@@ -1658,35 +1621,32 @@ static int __init_or_module
sl811h_remove(struct device *dev)
{
struct sl811 *sl811 = dev_get_drvdata(dev);
+ struct usb_hcd *hcd = sl811_to_hcd(sl811);
struct platform_device *pdev;
struct resource *res;
pdev = container_of(dev, struct platform_device, dev);
- if (HCD_IS_RUNNING(sl811->hcd.state))
- sl811->hcd.state = USB_STATE_QUIESCING;
+ if (HCD_IS_RUNNING(hcd->state))
+ hcd->state = USB_STATE_QUIESCING;
- usb_disconnect(&sl811->hcd.self.root_hub);
+ usb_disconnect(&hcd->self.root_hub);
remove_debug_file(sl811);
- sl811h_stop(&sl811->hcd);
+ sl811h_stop(hcd);
- if (!list_empty(&sl811->hcd.self.bus_list))
- usb_deregister_bus(&sl811->hcd.self);
+ usb_deregister_bus(&hcd->self);
- if (sl811->hcd.irq >= 0)
- free_irq(sl811->hcd.irq, sl811);
+ free_irq(hcd->irq, hcd);
- if (sl811->data_reg)
- iounmap(sl811->data_reg);
+ iounmap(sl811->data_reg);
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
release_mem_region(res->start, 1);
- if (sl811->addr_reg)
- iounmap(sl811->addr_reg);
+ iounmap(sl811->addr_reg);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, 1);
- kfree(sl811);
+ usb_put_hcd(hcd);
return 0;
}
@@ -1695,13 +1655,15 @@ sl811h_remove(struct device *dev)
static int __init
sl811h_probe(struct device *dev)
{
+ struct usb_hcd *hcd;
struct sl811 *sl811;
struct platform_device *pdev;
struct resource *addr, *data;
int irq;
- int status;
+ void __iomem *addr_reg;
+ void __iomem *data_reg;
+ int retval;
u8 tmp;
- unsigned long flags;
/* basic sanity checks first. board-specific init logic should
* have initialized these three resources and probably board
@@ -1724,37 +1686,39 @@ sl811h_probe(struct device *dev)
return -EINVAL;
}
- if (!request_mem_region(addr->start, 1, hcd_name))
- return -EBUSY;
+ if (!request_mem_region(addr->start, 1, hcd_name)) {
+ retval = -EBUSY;
+ goto err1;
+ }
+ addr_reg = ioremap(addr->start, resource_len(addr));
+ if (addr_reg == NULL) {
+ retval = -ENOMEM;
+ goto err2;
+ }
+
if (!request_mem_region(data->start, 1, hcd_name)) {
- release_mem_region(addr->start, 1);
- return -EBUSY;
+ retval = -EBUSY;
+ goto err3;
+ }
+ data_reg = ioremap(data->start, resource_len(addr));
+ if (data_reg == NULL) {
+ retval = -ENOMEM;
+ goto err4;
}
/* allocate and initialize hcd */
- sl811 = kcalloc(1, sizeof *sl811, GFP_KERNEL);
- if (!sl811)
- return 0;
+ hcd = usb_create_hcd(&sl811h_hc_driver);
+ if (!hcd) {
+ retval = 0;
+ goto err5;
+ }
+ sl811 = hcd_to_sl811(hcd);
dev_set_drvdata(dev, sl811);
- usb_bus_init(&sl811->hcd.self);
- sl811->hcd.self.controller = dev;
- sl811->hcd.self.bus_name = dev->bus_id;
- sl811->hcd.self.op = &usb_hcd_operations;
- sl811->hcd.self.hcpriv = sl811;
-
- // NOTE: 2.6.11 starts to change the hcd glue layer some more,
- // eventually letting us eliminate struct sl811h_req and a
- // lot of the boilerplate code here
-
- INIT_LIST_HEAD(&sl811->hcd.dev_list);
- sl811->hcd.self.release = &usb_hcd_release;
-
- sl811->hcd.description = sl811h_hc_driver.description;
- init_timer(&sl811->hcd.rh_timer);
- sl811->hcd.driver = &sl811h_hc_driver;
- sl811->hcd.irq = -1;
- sl811->hcd.state = USB_STATE_HALT;
+ hcd->self.controller = dev;
+ hcd->self.bus_name = dev->bus_id;
+ hcd->irq = irq;
+ hcd->regs = addr_reg;
spin_lock_init(&sl811->lock);
INIT_LIST_HEAD(&sl811->async);
@@ -1762,36 +1726,27 @@ sl811h_probe(struct device *dev)
init_timer(&sl811->timer);
sl811->timer.function = sl811h_timer;
sl811->timer.data = (unsigned long) sl811;
+ sl811->addr_reg = addr_reg;
+ sl811->data_reg = data_reg;
- sl811->addr_reg = ioremap(addr->start, resource_len(addr));
- if (sl811->addr_reg == NULL) {
- status = -ENOMEM;
- goto fail;
- }
- sl811->data_reg = ioremap(data->start, resource_len(addr));
- if (sl811->data_reg == NULL) {
- status = -ENOMEM;
- goto fail;
- }
-
- spin_lock_irqsave(&sl811->lock, flags);
+ spin_lock_irq(&sl811->lock);
port_power(sl811, 0);
- spin_unlock_irqrestore(&sl811->lock, flags);
+ spin_unlock_irq(&sl811->lock);
msleep(200);
tmp = sl811_read(sl811, SL11H_HWREVREG);
switch (tmp >> 4) {
case 1:
- sl811->hcd.product_desc = "SL811HS v1.2";
+ hcd->product_desc = "SL811HS v1.2";
break;
case 2:
- sl811->hcd.product_desc = "SL811HS v1.5";
+ hcd->product_desc = "SL811HS v1.5";
break;
default:
/* reject case 0, SL11S is less functional */
DBG("chiprev %02x\n", tmp);
- status = -ENXIO;
- goto fail;
+ retval = -ENXIO;
+ goto err6;
}
/* sl811s would need a different handler for this irq */
@@ -1799,25 +1754,41 @@ sl811h_probe(struct device *dev)
/* Cypress docs say the IRQ is IRQT_HIGH ... */
set_irq_type(irq, IRQT_RISING);
#endif
- status = request_irq(irq, sl811h_irq, SA_INTERRUPT, hcd_name, sl811);
- if (status < 0)
- goto fail;
- sl811->hcd.irq = irq;
+ retval = request_irq(irq, sl811h_irq, SA_INTERRUPT,
+ hcd->driver->description, hcd);
+ if (retval != 0)
+ goto err6;
- INFO("%s, irq %d\n", sl811->hcd.product_desc, irq);
+ INFO("%s, irq %d\n", hcd->product_desc, irq);
- status = usb_register_bus(&sl811->hcd.self);
- if (status < 0)
- goto fail;
- status = sl811h_start(&sl811->hcd);
- if (status == 0) {
- create_debug_file(sl811);
- return 0;
- }
-fail:
- sl811h_remove(dev);
- DBG("init error, %d\n", status);
- return status;
+ retval = usb_register_bus(&hcd->self);
+ if (retval < 0)
+ goto err7;
+
+ retval = sl811h_start(hcd);
+ if (retval < 0)
+ goto err8;
+
+ create_debug_file(sl811);
+ return 0;
+
+ err8:
+ usb_deregister_bus(&hcd->self);
+ err7:
+ free_irq(hcd->irq, hcd);
+ err6:
+ usb_put_hcd(hcd);
+ err5:
+ iounmap(data_reg);
+ err4:
+ release_mem_region(data->start, 1);
+ err3:
+ iounmap(addr_reg);
+ err2:
+ release_mem_region(addr->start, 1);
+ err1:
+ DBG("init error, %d\n", retval);
+ return retval;
}
#ifdef CONFIG_PM
@@ -1837,7 +1808,7 @@ sl811h_suspend(struct device *dev, u32 state, u32 phase)
return retval;
if (state <= PM_SUSPEND_MEM)
- retval = sl811h_hub_suspend(&sl811->hcd);
+ retval = sl811h_hub_suspend(sl811_to_hcd(sl811));
else
port_power(sl811, 0);
if (retval == 0)
@@ -1857,14 +1828,14 @@ sl811h_resume(struct device *dev, u32 phase)
* let's assume it'd only be powered to enable remote wakeup.
*/
if (dev->power.power_state > PM_SUSPEND_MEM
- || !sl811->hcd.can_wakeup) {
+ || !sl811_to_hcd(sl811)->can_wakeup) {
sl811->port1 = 0;
port_power(sl811, 1);
return 0;
}
dev->power.power_state = PM_SUSPEND_ON;
- return sl811h_hub_resume(&sl811->hcd);
+ return sl811h_hub_resume(sl811_to_hcd(sl811));
}
#else
diff --git a/drivers/usb/host/sl811.h b/drivers/usb/host/sl811.h
index 1f5f0d48de85ea..7690d98e42a7b8 100644
--- a/drivers/usb/host/sl811.h
+++ b/drivers/usb/host/sl811.h
@@ -118,7 +118,6 @@
#define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE)
struct sl811 {
- struct usb_hcd hcd;
spinlock_t lock;
void __iomem *addr_reg;
void __iomem *data_reg;
@@ -158,11 +157,16 @@ struct sl811 {
static inline struct sl811 *hcd_to_sl811(struct usb_hcd *hcd)
{
- return container_of(hcd, struct sl811, hcd);
+ return (struct sl811 *) (hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *sl811_to_hcd(struct sl811 *sl811)
+{
+ return container_of((void *) sl811, struct usb_hcd, hcd_priv);
}
struct sl811h_ep {
- struct list_head queue;
+ struct usb_host_endpoint *hep;
struct usb_device *udev;
u8 defctrl;
@@ -184,14 +188,6 @@ struct sl811h_ep {
struct list_head schedule;
};
-struct sl811h_req {
- /* FIXME usbcore should maintain endpoints' urb queues
- * directly in 'struct usb_host_endpoint'
- */
- struct urb *urb;
- struct list_head queue;
-};
-
/*-------------------------------------------------------------------------*/
/* These register utilities should work for the SL811S register API too
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index baf7444411ea89..95c84be2d43474 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -11,7 +11,7 @@
#include <linux/config.h>
#include <linux/kernel.h>
-#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
#include <linux/smp_lock.h>
#include <asm/io.h>
@@ -496,19 +496,18 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
#define MAX_OUTPUT (64 * 1024)
-static struct proc_dir_entry *uhci_proc_root = NULL;
+static struct dentry *uhci_debugfs_root = NULL;
-struct uhci_proc {
+struct uhci_debug {
int size;
char *data;
struct uhci_hcd *uhci;
};
-static int uhci_proc_open(struct inode *inode, struct file *file)
+static int uhci_debug_open(struct inode *inode, struct file *file)
{
- const struct proc_dir_entry *dp = PDE(inode);
- struct uhci_hcd *uhci = dp->data;
- struct uhci_proc *up;
+ struct uhci_hcd *uhci = inode->u.generic_ip;
+ struct uhci_debug *up;
int ret = -ENOMEM;
lock_kernel();
@@ -532,9 +531,9 @@ out:
return ret;
}
-static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence)
+static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence)
{
- struct uhci_proc *up;
+ struct uhci_debug *up;
loff_t new = -1;
lock_kernel();
@@ -556,16 +555,16 @@ static loff_t uhci_proc_lseek(struct file *file, loff_t off, int whence)
return (file->f_pos = new);
}
-static ssize_t uhci_proc_read(struct file *file, char __user *buf,
+static ssize_t uhci_debug_read(struct file *file, char __user *buf,
size_t nbytes, loff_t *ppos)
{
- struct uhci_proc *up = file->private_data;
+ struct uhci_debug *up = file->private_data;
return simple_read_from_buffer(buf, nbytes, ppos, up->data, up->size);
}
-static int uhci_proc_release(struct inode *inode, struct file *file)
+static int uhci_debug_release(struct inode *inode, struct file *file)
{
- struct uhci_proc *up = file->private_data;
+ struct uhci_debug *up = file->private_data;
kfree(up->data);
kfree(up);
@@ -573,11 +572,10 @@ static int uhci_proc_release(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations uhci_proc_operations = {
- .open = uhci_proc_open,
- .llseek = uhci_proc_lseek,
- .read = uhci_proc_read,
-// write: uhci_proc_write,
- .release = uhci_proc_release,
+static struct file_operations uhci_debug_operations = {
+ .open = uhci_debug_open,
+ .llseek = uhci_debug_lseek,
+ .read = uhci_debug_read,
+ .release = uhci_debug_release,
};
#endif
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 614403bbfb180e..75cab955ed6140 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -46,7 +46,7 @@
#include <linux/unistd.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
#include <linux/pm.h>
#include <linux/dmapool.h>
#include <linux/dma-mapping.h>
@@ -74,7 +74,7 @@ Alan Stern"
* debug = 0, no debugging messages
* debug = 1, dump failed URB's except for stalls
* debug = 2, dump all failed URB's (including stalls)
- * show all queues in /proc/driver/uhci/[pci_addr]
+ * show all queues in /debug/uhci/[pci_addr]
* debug = 3, show all TD's in URB's when dumping
*/
#ifdef DEBUG
@@ -1255,7 +1255,9 @@ static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
return NULL;
}
-static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
+static int uhci_urb_enqueue(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep,
+ struct urb *urb, int mem_flags)
{
int ret;
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -1889,7 +1891,7 @@ static int start_hc(struct uhci_hcd *uhci)
uhci->state_end = jiffies + HZ;
outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
- uhci->hcd.state = USB_STATE_RUNNING;
+ uhci_to_hcd(uhci)->state = USB_STATE_RUNNING;
return 0;
}
@@ -1927,12 +1929,10 @@ static void release_uhci(struct uhci_hcd *uhci)
uhci->fl = NULL;
}
-#ifdef CONFIG_PROC_FS
- if (uhci->proc_entry) {
- remove_proc_entry(uhci->hcd.self.bus_name, uhci_proc_root);
- uhci->proc_entry = NULL;
+ if (uhci->dentry) {
+ debugfs_remove(uhci->dentry);
+ uhci->dentry = NULL;
}
-#endif
}
static int uhci_reset(struct usb_hcd *hcd)
@@ -1972,25 +1972,17 @@ static int uhci_start(struct usb_hcd *hcd)
unsigned io_size;
dma_addr_t dma_handle;
struct usb_device *udev;
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *ent;
-#endif
+ struct dentry *dentry;
io_size = pci_resource_len(to_pci_dev(uhci_dev(uhci)), hcd->region);
-#ifdef CONFIG_PROC_FS
- ent = create_proc_entry(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_proc_root);
- if (!ent) {
- dev_err(uhci_dev(uhci), "couldn't create uhci proc entry\n");
+ dentry = debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, &uhci_debug_operations);
+ if (!dentry) {
+ dev_err(uhci_dev(uhci), "couldn't create uhci debugfs entry\n");
retval = -ENOMEM;
- goto err_create_proc_entry;
+ goto err_create_debug_entry;
}
-
- ent->data = uhci;
- ent->proc_fops = &uhci_proc_operations;
- ent->size = 0;
- uhci->proc_entry = ent;
-#endif
+ uhci->dentry = dentry;
uhci->fsbr = 0;
uhci->fsbrtimeout = 0;
@@ -2149,7 +2141,7 @@ static int uhci_start(struct usb_hcd *hcd)
udev->speed = USB_SPEED_FULL;
- if (hcd_register_root(udev, &uhci->hcd) != 0) {
+ if (hcd_register_root(udev, hcd) != 0) {
dev_err(uhci_dev(uhci), "unable to start root hub\n");
retval = -ENOMEM;
goto err_start_root_hub;
@@ -2192,13 +2184,10 @@ err_create_td_pool:
uhci->fl = NULL;
err_alloc_fl:
-#ifdef CONFIG_PROC_FS
- remove_proc_entry(hcd->self.bus_name, uhci_proc_root);
- uhci->proc_entry = NULL;
-
-err_create_proc_entry:
-#endif
+ debugfs_remove(uhci->dentry);
+ uhci->dentry = NULL;
+err_create_debug_entry:
return retval;
}
@@ -2275,62 +2264,18 @@ static int uhci_resume(struct usb_hcd *hcd)
if ((rc = start_hc(uhci)) != 0)
return rc;
}
- uhci->hcd.state = USB_STATE_RUNNING;
+ hcd->state = USB_STATE_RUNNING;
return 0;
}
#endif
-static struct usb_hcd *uhci_hcd_alloc(void)
-{
- struct uhci_hcd *uhci;
-
- uhci = (struct uhci_hcd *)kmalloc(sizeof(*uhci), GFP_KERNEL);
- if (!uhci)
- return NULL;
-
- memset(uhci, 0, sizeof(*uhci));
- uhci->hcd.product_desc = "UHCI Host Controller";
- return &uhci->hcd;
-}
-
-/* Are there any URBs for a particular device/endpoint on a given list? */
-static int urbs_for_ep_list(struct list_head *head,
- struct hcd_dev *hdev, int ep)
-{
- struct urb_priv *urbp;
-
- list_for_each_entry(urbp, head, urb_list) {
- struct urb *urb = urbp->urb;
-
- if (hdev == urb->dev->hcpriv && ep ==
- (usb_pipeendpoint(urb->pipe) |
- usb_pipein(urb->pipe)))
- return 1;
- }
- return 0;
-}
-
-/* Are there any URBs for a particular device/endpoint? */
-static int urbs_for_ep(struct uhci_hcd *uhci, struct hcd_dev *hdev, int ep)
-{
- int rc;
-
- spin_lock_irq(&uhci->schedule_lock);
- rc = (urbs_for_ep_list(&uhci->urb_list, hdev, ep) ||
- urbs_for_ep_list(&uhci->complete_list, hdev, ep) ||
- urbs_for_ep_list(&uhci->urb_remove_list, hdev, ep));
- spin_unlock_irq(&uhci->schedule_lock);
- return rc;
-}
-
/* Wait until all the URBs for a particular device/endpoint are gone */
static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd,
- struct hcd_dev *hdev, int endpoint)
+ struct usb_host_endpoint *ep)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
- wait_event_interruptible(uhci->waitqh,
- !urbs_for_ep(uhci, hdev, endpoint));
+ wait_event_interruptible(uhci->waitqh, list_empty(&ep->urb_list));
}
static int uhci_hcd_get_frame_number(struct usb_hcd *hcd)
@@ -2342,6 +2287,8 @@ static const char hcd_name[] = "uhci_hcd";
static const struct hc_driver uhci_driver = {
.description = hcd_name,
+ .product_desc = "UHCI Host Controller",
+ .hcd_priv_size = sizeof(struct uhci_hcd),
/* Generic hardware linkage */
.irq = uhci_irq,
@@ -2356,8 +2303,6 @@ static const struct hc_driver uhci_driver = {
#endif
.stop = uhci_stop,
- .hcd_alloc = uhci_hcd_alloc,
-
.urb_enqueue = uhci_urb_enqueue,
.urb_dequeue = uhci_urb_dequeue,
@@ -2405,11 +2350,9 @@ static int __init uhci_hcd_init(void)
goto errbuf_failed;
}
-#ifdef CONFIG_PROC_FS
- uhci_proc_root = create_proc_entry("driver/uhci", S_IFDIR, NULL);
- if (!uhci_proc_root)
- goto proc_failed;
-#endif
+ uhci_debugfs_root = debugfs_create_dir("uhci", NULL);
+ if (!uhci_debugfs_root)
+ goto debug_failed;
uhci_up_cachep = kmem_cache_create("uhci_urb_priv",
sizeof(struct urb_priv), 0, 0, NULL, NULL);
@@ -2427,12 +2370,9 @@ init_failed:
warn("not all urb_priv's were freed!");
up_failed:
+ debugfs_remove(uhci_debugfs_root);
-#ifdef CONFIG_PROC_FS
- remove_proc_entry("driver/uhci", NULL);
-
-proc_failed:
-#endif
+debug_failed:
if (errbuf)
kfree(errbuf);
@@ -2448,9 +2388,7 @@ static void __exit uhci_hcd_cleanup(void)
if (kmem_cache_destroy(uhci_up_cachep))
warn("not all urb_priv's were freed!");
-#ifdef CONFIG_PROC_FS
- remove_proc_entry("driver/uhci", NULL);
-#endif
+ debugfs_remove(uhci_debugfs_root);
if (errbuf)
kfree(errbuf);
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index e8fc0d64efe7f2..45cb686d9b4fdd 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -314,9 +314,6 @@ enum uhci_state {
UHCI_RESUMING_2
};
-#define hcd_to_uhci(hcd_ptr) container_of(hcd_ptr, struct uhci_hcd, hcd)
-#define uhci_dev(u) ((u)->hcd.self.controller)
-
/*
* This describes the full uhci information.
*
@@ -324,12 +321,9 @@ enum uhci_state {
* a subset of what the full implementation needs.
*/
struct uhci_hcd {
- struct usb_hcd hcd; /* must come first! */
-#ifdef CONFIG_PROC_FS
- /* procfs */
- struct proc_dir_entry *proc_entry;
-#endif
+ /* debugfs */
+ struct dentry *dentry;
/* Grabbed from PCI */
unsigned long io_addr;
@@ -383,6 +377,18 @@ struct uhci_hcd {
wait_queue_head_t waitqh; /* endpoint_disable waiters */
};
+/* Convert between a usb_hcd pointer and the corresponding uhci_hcd */
+static inline struct uhci_hcd *hcd_to_uhci(struct usb_hcd *hcd)
+{
+ return (struct uhci_hcd *) (hcd->hcd_priv);
+}
+static inline struct usb_hcd *uhci_to_hcd(struct uhci_hcd *uhci)
+{
+ return container_of((void *) uhci, struct usb_hcd, hcd_priv);
+}
+
+#define uhci_dev(u) (uhci_to_hcd(u)->self.controller)
+
struct urb_priv {
struct list_head urb_list;
diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
index 66bb13307df5ce..9960af52dd07ea 100644
--- a/drivers/usb/image/mdc800.c
+++ b/drivers/usb/image/mdc800.c
@@ -182,13 +182,48 @@ struct mdc800_data
/* Specification of the Endpoints */
static struct usb_endpoint_descriptor mdc800_ed [4] =
{
- { 0,0, 0x01, 0x02, 8, 0,0,0 },
- { 0,0, 0x82, 0x03, 8, 0,0,0 },
- { 0,0, 0x03, 0x02, 64, 0,0,0 },
- { 0,0, 0x84, 0x02, 64, 0,0,0 }
+ {
+ .bLength = 0,
+ .bDescriptorType = 0,
+ .bEndpointAddress = 0x01,
+ .bmAttributes = 0x02,
+ .wMaxPacketSize = __constant_cpu_to_le16(8),
+ .bInterval = 0,
+ .bRefresh = 0,
+ .bSynchAddress = 0,
+ },
+ {
+ .bLength = 0,
+ .bDescriptorType = 0,
+ .bEndpointAddress = 0x82,
+ .bmAttributes = 0x03,
+ .wMaxPacketSize = __constant_cpu_to_le16(8),
+ .bInterval = 0,
+ .bRefresh = 0,
+ .bSynchAddress = 0,
+ },
+ {
+ .bLength = 0,
+ .bDescriptorType = 0,
+ .bEndpointAddress = 0x03,
+ .bmAttributes = 0x02,
+ .wMaxPacketSize = __constant_cpu_to_le16(64),
+ .bInterval = 0,
+ .bRefresh = 0,
+ .bSynchAddress = 0,
+ },
+ {
+ .bLength = 0,
+ .bDescriptorType = 0,
+ .bEndpointAddress = 0x84,
+ .bmAttributes = 0x02,
+ .wMaxPacketSize = __constant_cpu_to_le16(64),
+ .bInterval = 0,
+ .bRefresh = 0,
+ .bSynchAddress = 0,
+ },
};
-
/* The Variable used by the driver */
static struct mdc800_data* mdc800;
diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c
index 2a18c35629ebc9..fe32608b434716 100644
--- a/drivers/usb/image/microtek.c
+++ b/drivers/usb/image/microtek.c
@@ -715,8 +715,8 @@ static int mts_usb_probe(struct usb_interface *intf,
MTS_DEBUG( "usb-device descriptor at %x\n", (int)dev );
MTS_DEBUG( "product id = 0x%x, vendor id = 0x%x\n",
- (int)dev->descriptor.idProduct,
- (int)dev->descriptor.idVendor );
+ le16_to_cpu(dev->descriptor.idProduct),
+ le16_to_cpu(dev->descriptor.idVendor) );
MTS_DEBUG_GOT_HERE();
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index 67a5b70a6daf54..a2a037fe791f76 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -2137,9 +2137,9 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
aiptek->inputdev.name = "Aiptek";
aiptek->inputdev.phys = aiptek->features.usbPath;
aiptek->inputdev.id.bustype = BUS_USB;
- aiptek->inputdev.id.vendor = usbdev->descriptor.idVendor;
- aiptek->inputdev.id.product = usbdev->descriptor.idProduct;
- aiptek->inputdev.id.version = usbdev->descriptor.bcdDevice;
+ aiptek->inputdev.id.vendor = le16_to_cpu(usbdev->descriptor.idVendor);
+ aiptek->inputdev.id.product = le16_to_cpu(usbdev->descriptor.idProduct);
+ aiptek->inputdev.id.version = le16_to_cpu(usbdev->descriptor.bcdDevice);
aiptek->usbdev = usbdev;
aiptek->ifnum = intf->altsetting[0].desc.bInterfaceNumber;
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
index f491d76a8ff1e8..3f5414446485aa 100644
--- a/drivers/usb/input/ati_remote.c
+++ b/drivers/usb/input/ati_remote.c
@@ -672,9 +672,9 @@ static void ati_remote_input_init(struct ati_remote *ati_remote)
idev->phys = ati_remote->phys;
idev->id.bustype = BUS_USB;
- idev->id.vendor = ati_remote->udev->descriptor.idVendor;
- idev->id.product = ati_remote->udev->descriptor.idProduct;
- idev->id.version = ati_remote->udev->descriptor.bcdDevice;
+ idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor);
+ idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct);
+ idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice);
}
static int ati_remote_initialize(struct ati_remote *ati_remote)
@@ -729,13 +729,6 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
char path[64];
char *buf = NULL;
- /* See if the offered device matches what we can accept */
- if ((udev->descriptor.idVendor != ATI_REMOTE_VENDOR_ID) ||
- ( (udev->descriptor.idProduct != ATI_REMOTE_PRODUCT_ID) &&
- (udev->descriptor.idProduct != LOLA_REMOTE_PRODUCT_ID) &&
- (udev->descriptor.idProduct != MEDION_REMOTE_PRODUCT_ID) ))
- return -ENODEV;
-
/* Allocate and clear an ati_remote struct */
if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL)))
return -ENOMEM;
@@ -763,7 +756,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
retval = -ENODEV;
goto error;
}
- if (ati_remote->endpoint_in->wMaxPacketSize == 0) {
+ if (le16_to_cpu(ati_remote->endpoint_in->wMaxPacketSize) == 0) {
err("%s: endpoint_in message size==0? \n", __FUNCTION__);
retval = -ENODEV;
goto error;
@@ -803,8 +796,8 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de
if (!strlen(ati_remote->name))
sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)",
- ati_remote->udev->descriptor.idVendor,
- ati_remote->udev->descriptor.idProduct);
+ le16_to_cpu(ati_remote->udev->descriptor.idVendor),
+ le16_to_cpu(ati_remote->udev->descriptor.idProduct));
/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
retval = ati_remote_initialize(ati_remote);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 636cbd24de522f..e8a0f3ae1e5ae8 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1610,8 +1610,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
int n;
for (n = 0; hid_blacklist[n].idVendor; n++)
- if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) &&
- (hid_blacklist[n].idProduct == dev->descriptor.idProduct))
+ if ((hid_blacklist[n].idVendor == le16_to_cpu(dev->descriptor.idVendor)) &&
+ (hid_blacklist[n].idProduct == le16_to_cpu(dev->descriptor.idProduct)))
quirks = hid_blacklist[n].quirks;
if (quirks & HID_QUIRK_IGNORE)
@@ -1730,7 +1730,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
} else if (usb_string(dev, dev->descriptor.iProduct, buf, 128) > 0) {
snprintf(hid->name, 128, "%s", buf);
} else
- snprintf(hid->name, 128, "%04x:%04x", dev->descriptor.idVendor, dev->descriptor.idProduct);
+ snprintf(hid->name, 128, "%04x:%04x",
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
usb_make_path(dev, buf, 64);
snprintf(hid->phys, 64, "%s/input%d", buf,
diff --git a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
index b43463b4b0ff4a..f978680b9c0a28 100644
--- a/drivers/usb/input/hid-ff.c
+++ b/drivers/usb/input/hid-ff.c
@@ -82,8 +82,8 @@ int hid_ff_init(struct hid_device* hid)
{
struct hid_ff_initializer *init;
- init = hid_get_ff_init(hid->dev->descriptor.idVendor,
- hid->dev->descriptor.idProduct);
+ init = hid_get_ff_init(le16_to_cpu(hid->dev->descriptor.idVendor),
+ le16_to_cpu(hid->dev->descriptor.idProduct));
if (!init) {
dbg("hid_ff_init could not find initializer");
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
index 6fa35d6a613a9c..bc3ca7c50b38da 100644
--- a/drivers/usb/input/hid-input.c
+++ b/drivers/usb/input/hid-input.c
@@ -564,9 +564,9 @@ int hidinput_connect(struct hid_device *hid)
hidinput->input.phys = hid->phys;
hidinput->input.uniq = hid->uniq;
hidinput->input.id.bustype = BUS_USB;
- hidinput->input.id.vendor = dev->descriptor.idVendor;
- hidinput->input.id.product = dev->descriptor.idProduct;
- hidinput->input.id.version = dev->descriptor.bcdDevice;
+ hidinput->input.id.vendor = le16_to_cpu(dev->descriptor.idVendor);
+ hidinput->input.id.product = le16_to_cpu(dev->descriptor.idProduct);
+ hidinput->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
hidinput->input.dev = &hid->intf->dev;
}
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
index fa8be80dac0b18..b86f822e2968e2 100644
--- a/drivers/usb/input/hid-lgff.c
+++ b/drivers/usb/input/hid-lgff.c
@@ -251,8 +251,8 @@ static void hid_lgff_input_init(struct hid_device* hid)
{
struct device_type* dev = devices;
signed short* ff;
- u16 idVendor = hid->dev->descriptor.idVendor;
- u16 idProduct = hid->dev->descriptor.idProduct;
+ u16 idVendor = le16_to_cpu(hid->dev->descriptor.idVendor);
+ u16 idProduct = le16_to_cpu(hid->dev->descriptor.idProduct);
struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
while (dev->idVendor && (idVendor != dev->idVendor || idProduct != dev->idProduct))
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
index 44e466d196b44e..bf9a693a6f5a8e 100644
--- a/drivers/usb/input/hiddev.c
+++ b/drivers/usb/input/hiddev.c
@@ -423,9 +423,9 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
dinfo.busnum = dev->bus->busnum;
dinfo.devnum = dev->devnum;
dinfo.ifnum = hid->ifnum;
- dinfo.vendor = dev->descriptor.idVendor;
- dinfo.product = dev->descriptor.idProduct;
- dinfo.version = dev->descriptor.bcdDevice;
+ dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
+ dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
+ dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
dinfo.num_applications = hid->maxapplication;
if (copy_to_user(user_arg, &dinfo, sizeof(dinfo)))
return -EFAULT;
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c
index 2e4c0d2460305c..a68c5b4e7b3756 100644
--- a/drivers/usb/input/kbtab.c
+++ b/drivers/usb/input/kbtab.c
@@ -175,9 +175,9 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
kbtab->dev.name = "KB Gear Tablet";
kbtab->dev.phys = kbtab->phys;
kbtab->dev.id.bustype = BUS_USB;
- kbtab->dev.id.vendor = dev->descriptor.idVendor;
- kbtab->dev.id.product = dev->descriptor.idProduct;
- kbtab->dev.id.version = dev->descriptor.bcdDevice;
+ kbtab->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor);
+ kbtab->dev.id.product = le16_to_cpu(dev->descriptor.idProduct);
+ kbtab->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
kbtab->dev.dev = &intf->dev;
kbtab->usbdev = dev;
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
index 9dcfd7e2ffbf9a..f0e75c939a4871 100644
--- a/drivers/usb/input/mtouchusb.c
+++ b/drivers/usb/input/mtouchusb.c
@@ -223,9 +223,9 @@ static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_i
mtouch->input.name = mtouch->name;
mtouch->input.phys = mtouch->phys;
mtouch->input.id.bustype = BUS_USB;
- mtouch->input.id.vendor = udev->descriptor.idVendor;
- mtouch->input.id.product = udev->descriptor.idProduct;
- mtouch->input.id.version = udev->descriptor.bcdDevice;
+ mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor);
+ mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct);
+ mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice);
mtouch->input.dev = &intf->dev;
mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
index 01384f523e1542..6e77750b44a450 100644
--- a/drivers/usb/input/powermate.c
+++ b/drivers/usb/input/powermate.c
@@ -375,12 +375,13 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
return -EIO; /* failure */
}
- switch (udev->descriptor.idProduct) {
+ switch (le16_to_cpu(udev->descriptor.idProduct)) {
case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break;
case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break;
default:
- pm->input.name = pm_name_soundknob;
- printk(KERN_WARNING "powermate: unknown product id %04x\n", udev->descriptor.idProduct);
+ pm->input.name = pm_name_soundknob;
+ printk(KERN_WARNING "powermate: unknown product id %04x\n",
+ le16_to_cpu(udev->descriptor.idProduct));
}
pm->input.private = pm;
@@ -389,9 +390,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i
pm->input.relbit[LONG(REL_DIAL)] = BIT(REL_DIAL);
pm->input.mscbit[LONG(MSC_PULSELED)] = BIT(MSC_PULSELED);
pm->input.id.bustype = BUS_USB;
- pm->input.id.vendor = udev->descriptor.idVendor;
- pm->input.id.product = udev->descriptor.idProduct;
- pm->input.id.version = udev->descriptor.bcdDevice;
+ pm->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor);
+ pm->input.id.product = le16_to_cpu(udev->descriptor.idProduct);
+ pm->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice);
pm->input.event = powermate_input_event;
pm->input.dev = &intf->dev;
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
index 65dd5be4eb9999..734e1114aafba8 100644
--- a/drivers/usb/input/touchkitusb.c
+++ b/drivers/usb/input/touchkitusb.c
@@ -211,9 +211,9 @@ static int touchkit_probe(struct usb_interface *intf,
touchkit->input.name = touchkit->name;
touchkit->input.phys = touchkit->phys;
touchkit->input.id.bustype = BUS_USB;
- touchkit->input.id.vendor = udev->descriptor.idVendor;
- touchkit->input.id.product = udev->descriptor.idProduct;
- touchkit->input.id.version = udev->descriptor.bcdDevice;
+ touchkit->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor);
+ touchkit->input.id.product = le16_to_cpu(udev->descriptor.idProduct);
+ touchkit->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice);
touchkit->input.dev = &intf->dev;
touchkit->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
index 1700f405b00b04..148d81e0348031 100644
--- a/drivers/usb/input/usbkbd.c
+++ b/drivers/usb/input/usbkbd.c
@@ -296,9 +296,9 @@ static int usb_kbd_probe(struct usb_interface *iface,
kbd->dev.name = kbd->name;
kbd->dev.phys = kbd->phys;
kbd->dev.id.bustype = BUS_USB;
- kbd->dev.id.vendor = dev->descriptor.idVendor;
- kbd->dev.id.product = dev->descriptor.idProduct;
- kbd->dev.id.version = dev->descriptor.bcdDevice;
+ kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor);
+ kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct);
+ kbd->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
kbd->dev.dev = &iface->dev;
if (!(buf = kmalloc(63, GFP_KERNEL))) {
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
index 8c7381b74499b2..54b247cfd31276 100644
--- a/drivers/usb/input/usbmouse.c
+++ b/drivers/usb/input/usbmouse.c
@@ -180,9 +180,9 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
mouse->dev.name = mouse->name;
mouse->dev.phys = mouse->phys;
mouse->dev.id.bustype = BUS_USB;
- mouse->dev.id.vendor = dev->descriptor.idVendor;
- mouse->dev.id.product = dev->descriptor.idProduct;
- mouse->dev.id.version = dev->descriptor.bcdDevice;
+ mouse->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor);
+ mouse->dev.id.product = le16_to_cpu(dev->descriptor.idProduct);
+ mouse->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
mouse->dev.dev = &intf->dev;
if (!(buf = kmalloc(63, GFP_KERNEL))) {
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
index 471d1bf68bf049..f2f34392f8556d 100644
--- a/drivers/usb/input/wacom.c
+++ b/drivers/usb/input/wacom.c
@@ -692,9 +692,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
wacom->dev.name = wacom->features->name;
wacom->dev.phys = wacom->phys;
wacom->dev.id.bustype = BUS_USB;
- wacom->dev.id.vendor = dev->descriptor.idVendor;
- wacom->dev.id.product = dev->descriptor.idProduct;
- wacom->dev.id.version = dev->descriptor.bcdDevice;
+ wacom->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor);
+ wacom->dev.id.product = le16_to_cpu(dev->descriptor.idProduct);
+ wacom->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
wacom->dev.dev = &intf->dev;
wacom->usbdev = dev;
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c
index c5fa87edb66749..d65edb22e5459a 100644
--- a/drivers/usb/input/xpad.c
+++ b/drivers/usb/input/xpad.c
@@ -226,8 +226,8 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
int i;
for (i = 0; xpad_device[i].idVendor; i++) {
- if ((udev->descriptor.idVendor == xpad_device[i].idVendor) &&
- (udev->descriptor.idProduct == xpad_device[i].idProduct))
+ if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) &&
+ (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct))
break;
}
@@ -264,9 +264,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id
xpad->udev = udev;
xpad->dev.id.bustype = BUS_USB;
- xpad->dev.id.vendor = udev->descriptor.idVendor;
- xpad->dev.id.product = udev->descriptor.idProduct;
- xpad->dev.id.version = udev->descriptor.bcdDevice;
+ xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor);
+ xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct);
+ xpad->dev.id.version = le16_to_cpu(udev->descriptor.bcdDevice);
xpad->dev.dev = &intf->dev;
xpad->dev.private = xpad;
xpad->dev.name = xpad_device[i].name;
diff --git a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
index 9f0a31eb671d36..425d67f1b17a26 100644
--- a/drivers/usb/media/Makefile
+++ b/drivers/usb/media/Makefile
@@ -2,7 +2,7 @@
# Makefile for USB Media drivers
#
-sn9c102-objs := sn9c102_core.o sn9c102_pas106b.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o sn9c102_pas202bcb.o
+sn9c102-objs := sn9c102_core.o sn9c102_hv7131d.o sn9c102_mi0343.o sn9c102_pas106b.o sn9c102_pas202bcb.o sn9c102_tas5110c1b.o sn9c102_tas5130d1b.o
obj-$(CONFIG_USB_DABUSB) += dabusb.o
obj-$(CONFIG_USB_DSBR) += dsbr100.o
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c
index 73f826d7d3d1e6..8823297d219165 100644
--- a/drivers/usb/media/dabusb.c
+++ b/drivers/usb/media/dabusb.c
@@ -724,13 +724,16 @@ static int dabusb_probe (struct usb_interface *intf,
pdabusb_t s;
dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
- usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, intf->altsetting->desc.bInterfaceNumber);
+ le16_to_cpu(usbdev->descriptor.idVendor),
+ le16_to_cpu(usbdev->descriptor.idProduct),
+ intf->altsetting->desc.bInterfaceNumber);
/* We don't handle multiple configurations */
if (usbdev->descriptor.bNumConfigurations != 1)
return -ENODEV;
- if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && usbdev->descriptor.idProduct == 0x9999)
+ if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF &&
+ le16_to_cpu(usbdev->descriptor.idProduct) == 0x9999)
return -ENODEV;
@@ -746,7 +749,7 @@ static int dabusb_probe (struct usb_interface *intf,
err("reset_configuration failed");
goto reject;
}
- if (usbdev->descriptor.idProduct == 0x2131) {
+ if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) {
dabusb_loadmem (s, NULL);
goto reject;
}
diff --git a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
index 277d65b383f0b8..64eb7ca72836ce 100644
--- a/drivers/usb/media/ibmcam.c
+++ b/drivers/usb/media/ibmcam.c
@@ -3659,17 +3659,8 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
if (dev->descriptor.bNumConfigurations != 1)
return -ENODEV;
- /* Is it an IBM camera? */
- if (dev->descriptor.idVendor != IBMCAM_VENDOR_ID)
- return -ENODEV;
- if ((dev->descriptor.idProduct != IBMCAM_PRODUCT_ID) &&
- (dev->descriptor.idProduct != VEO_800C_PRODUCT_ID) &&
- (dev->descriptor.idProduct != VEO_800D_PRODUCT_ID) &&
- (dev->descriptor.idProduct != NETCAM_PRODUCT_ID))
- return -ENODEV;
-
/* Check the version/revision */
- switch (dev->descriptor.bcdDevice) {
+ switch (le16_to_cpu(dev->descriptor.bcdDevice)) {
case 0x0002:
if (ifnum != 2)
return -ENODEV;
@@ -3678,8 +3669,8 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
case 0x030A:
if (ifnum != 0)
return -ENODEV;
- if ((dev->descriptor.idProduct == NETCAM_PRODUCT_ID) ||
- (dev->descriptor.idProduct == VEO_800D_PRODUCT_ID))
+ if ((le16_to_cpu(dev->descriptor.idProduct) == NETCAM_PRODUCT_ID) ||
+ (le16_to_cpu(dev->descriptor.idProduct) == VEO_800D_PRODUCT_ID))
model = IBMCAM_MODEL_4;
else
model = IBMCAM_MODEL_2;
@@ -3691,14 +3682,14 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
break;
default:
err("IBM camera with revision 0x%04x is not supported.",
- dev->descriptor.bcdDevice);
+ le16_to_cpu(dev->descriptor.bcdDevice));
return -ENODEV;
}
/* Print detailed info on what we found so far */
do {
char *brand = NULL;
- switch (dev->descriptor.idProduct) {
+ switch (le16_to_cpu(dev->descriptor.idProduct)) {
case NETCAM_PRODUCT_ID:
brand = "IBM NetCamera";
break;
@@ -3714,7 +3705,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
break;
}
info("%s USB camera found (model %d, rev. 0x%04x)",
- brand, model, dev->descriptor.bcdDevice);
+ brand, model, le16_to_cpu(dev->descriptor.bcdDevice));
} while (0);
/* Validate found interface: must have one ISO endpoint */
@@ -3752,7 +3743,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
err("Interface %d. has ISO OUT endpoint!", ifnum);
return -ENODEV;
}
- if (endpoint->wMaxPacketSize == 0) {
+ if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
if (inactInterface < 0)
inactInterface = i;
else {
@@ -3762,7 +3753,7 @@ static int ibmcam_probe(struct usb_interface *intf, const struct usb_device_id *
} else {
if (actInterface < 0) {
actInterface = i;
- maxPS = endpoint->wMaxPacketSize;
+ maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
if (debug > 0)
info("Active setting=%d. maxPS=%d.", i, maxPS);
} else
diff --git a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
index aca3093c2b8765..7ff1468f597700 100644
--- a/drivers/usb/media/konicawc.c
+++ b/drivers/usb/media/konicawc.c
@@ -390,7 +390,7 @@ static int konicawc_start_data(struct uvd *uvd)
spd_to_iface[cam->speed]);
if (!interface)
return -ENXIO;
- pktsz = interface->endpoint[1].desc.wMaxPacketSize;
+ pktsz = le16_to_cpu(interface->endpoint[1].desc.wMaxPacketSize);
DEBUG(1, "pktsz = %d", pktsz);
if (!CAMERA_IS_OPERATIONAL(uvd)) {
err("Camera is not operational");
@@ -732,7 +732,7 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
if (dev->descriptor.bNumConfigurations != 1)
return -ENODEV;
- info("Konica Webcam (rev. 0x%04x)", dev->descriptor.bcdDevice);
+ info("Konica Webcam (rev. 0x%04x)", le16_to_cpu(dev->descriptor.bcdDevice));
RESTRICT_TO_RANGE(speed, 0, MAX_SPEED);
/* Validate found interface: must have one ISO endpoint */
@@ -756,7 +756,7 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
}
endpoint = &interface->endpoint[1].desc;
DEBUG(1, "found endpoint: addr: 0x%2.2x maxps = 0x%4.4x",
- endpoint->bEndpointAddress, endpoint->wMaxPacketSize);
+ endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize));
if (video_ep == 0)
video_ep = endpoint->bEndpointAddress;
else if (video_ep != endpoint->bEndpointAddress) {
@@ -773,7 +773,7 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
interface->desc.bInterfaceNumber);
return -ENODEV;
}
- if (endpoint->wMaxPacketSize == 0) {
+ if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
if (inactInterface < 0)
inactInterface = i;
else {
@@ -786,8 +786,8 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
actInterface = i;
}
}
- if(endpoint->wMaxPacketSize > maxPS)
- maxPS = endpoint->wMaxPacketSize;
+ if (le16_to_cpu(endpoint->wMaxPacketSize) > maxPS)
+ maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
}
if(actInterface == -1) {
err("Cant find required endpoint");
@@ -846,9 +846,9 @@ static int konicawc_probe(struct usb_interface *intf, const struct usb_device_id
cam->input.evbit[0] = BIT(EV_KEY);
cam->input.keybit[LONG(BTN_0)] = BIT(BTN_0);
cam->input.id.bustype = BUS_USB;
- cam->input.id.vendor = dev->descriptor.idVendor;
- cam->input.id.product = dev->descriptor.idProduct;
- cam->input.id.version = dev->descriptor.bcdDevice;
+ cam->input.id.vendor = le16_to_cpu(dev->descriptor.idVendor);
+ cam->input.id.product = le16_to_cpu(dev->descriptor.idProduct);
+ cam->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
input_register_device(&cam->input);
usb_make_path(dev, cam->input_physname, 56);
diff --git a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
index 8bd791d1df3ecb..88c3628dc2f515 100644
--- a/drivers/usb/media/ov511.c
+++ b/drivers/usb/media/ov511.c
@@ -3908,15 +3908,11 @@ ov51x_do_dealloc(struct usb_ov511 *ov)
ov->fbuf = NULL;
}
- if (ov->rawfbuf) {
- vfree(ov->rawfbuf);
- ov->rawfbuf = NULL;
- }
+ vfree(ov->rawfbuf);
+ ov->rawfbuf = NULL;
- if (ov->tempfbuf) {
- vfree(ov->tempfbuf);
- ov->tempfbuf = NULL;
- }
+ vfree(ov->tempfbuf);
+ ov->tempfbuf = NULL;
for (i = 0; i < OV511_NUMSBUF; i++) {
if (ov->sbuf[i].data) {
@@ -5596,7 +5592,7 @@ ov518_configure(struct usb_ov511 *ov)
if (ifp) {
alt = usb_altnum_to_altsetting(ifp, 7);
if (alt)
- mxps = alt->endpoint[0].desc.wMaxPacketSize;
+ mxps = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
}
/* Some OV518s have packet numbering by default, some don't */
@@ -5825,7 +5821,7 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
ov->auto_gain = autogain;
ov->auto_exp = autoexp;
- switch (dev->descriptor.idProduct) {
+ switch (le16_to_cpu(dev->descriptor.idProduct)) {
case PROD_OV511:
ov->bridge = BRG_OV511;
ov->bclass = BCL_OV511;
@@ -5843,13 +5839,13 @@ ov51x_probe(struct usb_interface *intf, const struct usb_device_id *id)
ov->bclass = BCL_OV518;
break;
case PROD_ME2CAM:
- if (dev->descriptor.idVendor != VEND_MATTEL)
+ if (le16_to_cpu(dev->descriptor.idVendor) != VEND_MATTEL)
goto error;
ov->bridge = BRG_OV511PLUS;
ov->bclass = BCL_OV511;
break;
default:
- err("Unknown product ID 0x%04x", dev->descriptor.idProduct);
+ err("Unknown product ID 0x%04x", le16_to_cpu(dev->descriptor.idProduct));
goto error;
}
diff --git a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
index ae4b3576ea323f..6761806bc86f24 100644
--- a/drivers/usb/media/se401.c
+++ b/drivers/usb/media/se401.c
@@ -1315,20 +1315,20 @@ static int se401_probe(struct usb_interface *intf,
interface = &intf->cur_altsetting->desc;
/* Is it an se401? */
- if (dev->descriptor.idVendor == 0x03e8 &&
- dev->descriptor.idProduct == 0x0004) {
+ if (le16_to_cpu(dev->descriptor.idVendor) == 0x03e8 &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x0004) {
camera_name="Endpoints/Aox SE401";
- } else if (dev->descriptor.idVendor == 0x0471 &&
- dev->descriptor.idProduct == 0x030b) {
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x0471 &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x030b) {
camera_name="Philips PCVC665K";
- } else if (dev->descriptor.idVendor == 0x047d &&
- dev->descriptor.idProduct == 0x5001) {
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x5001) {
camera_name="Kensington VideoCAM 67014";
- } else if (dev->descriptor.idVendor == 0x047d &&
- dev->descriptor.idProduct == 0x5002) {
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x5002) {
camera_name="Kensington VideoCAM 6701(5/7)";
- } else if (dev->descriptor.idVendor == 0x047d &&
- dev->descriptor.idProduct == 0x5003) {
+ } else if (le16_to_cpu(dev->descriptor.idVendor) == 0x047d &&
+ le16_to_cpu(dev->descriptor.idProduct) == 0x5003) {
camera_name="Kensington VideoCAM 67016";
button=0;
} else
@@ -1354,7 +1354,7 @@ static int se401_probe(struct usb_interface *intf,
se401->iface = interface->bInterfaceNumber;
se401->camera_name = camera_name;
- info("firmware version: %02x", dev->descriptor.bcdDevice & 255);
+ info("firmware version: %02x", le16_to_cpu(dev->descriptor.bcdDevice) & 255);
if (se401_init(se401, button)) {
kfree(se401);
diff --git a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
index a58ff2e9efa327..9c4585bc39e142 100644
--- a/drivers/usb/media/sn9c102.h
+++ b/drivers/usb/media/sn9c102.h
@@ -46,8 +46,8 @@
#define SN9C102_URBS 2
#define SN9C102_ISO_PACKETS 7
#define SN9C102_ALTERNATE_SETTING 8
-#define SN9C102_URB_TIMEOUT msecs_to_jiffies(3)
-#define SN9C102_CTRL_TIMEOUT msecs_to_jiffies(100)
+#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
+#define SN9C102_CTRL_TIMEOUT msecs_to_jiffies(300)
/*****************************************************************************/
@@ -55,8 +55,8 @@
#define SN9C102_MODULE_AUTHOR "(C) 2004 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define SN9C102_MODULE_LICENSE "GPL"
-#define SN9C102_MODULE_VERSION "1:1.19"
-#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 19)
+#define SN9C102_MODULE_VERSION "1:1.20"
+#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 20)
enum sn9c102_bridge {
BRIDGE_SN9C101 = 0x01,
@@ -101,8 +101,12 @@ enum sn9c102_stream_state {
STREAM_ON,
};
+typedef char sn9c102_sof_header_t[12];
+typedef char sn9c102_eof_header_t[4];
+
struct sn9c102_sysfs_attr {
u8 reg, i2c_reg;
+ sn9c102_sof_header_t frame_header;
};
static DECLARE_MUTEX(sn9c102_sysfs_lock);
@@ -131,6 +135,7 @@ struct sn9c102_device {
struct v4l2_jpegcompression compression;
struct sn9c102_sysfs_attr sysfs;
+ sn9c102_sof_header_t sof_header;
u16 reg[32];
enum sn9c102_dev_state state;
diff --git a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
index e4c44fa873f4ce..0da1baa0ea094a 100644
--- a/drivers/usb/media/sn9c102_core.c
+++ b/drivers/usb/media/sn9c102_core.c
@@ -82,9 +82,6 @@ MODULE_PARM_DESC(debug,
/*****************************************************************************/
-typedef char sn9c102_sof_header_t[12];
-typedef char sn9c102_eof_header_t[4];
-
static sn9c102_sof_header_t sn9c102_sof_header[] = {
{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x00},
{0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96, 0x01},
@@ -277,9 +274,9 @@ sn9c102_i2c_wait(struct sn9c102_device* cam, struct sn9c102_sensor* sensor)
if (r & 0x04)
return 0;
if (sensor->frequency & SN9C102_I2C_400KHZ)
- udelay(5*8);
+ udelay(5*16);
else
- udelay(16*8);
+ udelay(16*16);
}
return -EBUSY;
}
@@ -306,18 +303,19 @@ sn9c102_i2c_detect_write_error(struct sn9c102_device* cam,
int
-sn9c102_i2c_try_read(struct sn9c102_device* cam,
- struct sn9c102_sensor* sensor, u8 address)
+sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
+ struct sn9c102_sensor* sensor, u8 data0, u8 data1,
+ u8 n, u8 buffer[])
{
struct usb_device* udev = cam->usbdev;
u8* data = cam->control_buffer;
int err = 0, res;
- /* Write cycle - address */
+ /* Write cycle */
data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
- data[1] = sensor->slave_write_id;
- data[2] = address;
+ data[1] = data0; /* I2C slave id */
+ data[2] = data1; /* address */
data[7] = 0x10;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
@@ -326,11 +324,11 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
err += sn9c102_i2c_wait(cam, sensor);
- /* Read cycle - 1 byte */
+ /* Read cycle - n bytes */
data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
- 0x10 | 0x02;
- data[1] = sensor->slave_read_id;
+ (n << 4) | 0x02;
+ data[1] = data0;
data[7] = 0x10;
res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
@@ -339,7 +337,7 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
err += sn9c102_i2c_wait(cam, sensor);
- /* The read byte will be placed in data[4] */
+ /* The first read byte will be placed in data[4] */
res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
if (res < 0)
@@ -347,12 +345,18 @@ sn9c102_i2c_try_read(struct sn9c102_device* cam,
err += sn9c102_i2c_detect_read_error(cam, sensor);
- if (err)
+ PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
+ data[4])
+
+ if (err) {
DBG(3, "I2C read failed for %s image sensor", sensor->name)
+ return -1;
+ }
- PDBGG("I2C read: address 0x%02X, value: 0x%02X", address, data[4])
+ if (buffer)
+ memcpy(buffer, data, sizeof(buffer));
- return err ? -1 : (int)data[4];
+ return (int)data[4];
}
@@ -395,12 +399,21 @@ sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
}
+int
+sn9c102_i2c_try_read(struct sn9c102_device* cam,
+ struct sn9c102_sensor* sensor, u8 address)
+{
+ return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
+ address, 1, NULL);
+}
+
+
int
sn9c102_i2c_try_write(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor, u8 address, u8 value)
{
return sn9c102_i2c_try_raw_write(cam, sensor, 3,
- sensor->slave_write_id, address,
+ sensor->i2c_slave_id, address,
value, 0, 0, 0);
}
@@ -433,9 +446,11 @@ sn9c102_find_sof_header(struct sn9c102_device* cam, void* mem, size_t len)
for (i = 0; (len >= soflen) && (i <= len - soflen); i++)
for (j = 0; j < n; j++)
/* It's enough to compare 7 bytes */
- if (!memcmp(mem + i, sn9c102_sof_header[j], 7))
- /* Skips the header */
+ if (!memcmp(mem + i, sn9c102_sof_header[j], 7)) {
+ memcpy(cam->sof_header, mem + i, soflen);
+ /* Skip the header */
return mem + i + soflen;
+ }
return NULL;
}
@@ -563,6 +578,9 @@ end_of_frame:
(*f) = NULL;
spin_unlock_irqrestore(&cam->queue_lock
, lock_flags);
+ memcpy(cam->sysfs.frame_header,
+ cam->sof_header,
+ sizeof(sn9c102_sof_header_t));
DBG(3, "Video frame captured: "
"%lu bytes", (unsigned long)(b))
@@ -746,15 +764,14 @@ int sn9c102_stream_interrupt(struct sn9c102_device* cam)
(cam->stream == STREAM_OFF) ||
(cam->state & DEV_DISCONNECTED),
SN9C102_URB_TIMEOUT);
- if (err) {
+ if (cam->state & DEV_DISCONNECTED)
+ return -ENODEV;
+ else if (err) {
cam->state |= DEV_MISCONFIGURED;
- DBG(1, "The camera is misconfigured. To use "
- "it, close and open /dev/video%d "
- "again.", cam->v4ldev->minor)
+ DBG(1, "The camera is misconfigured. To use it, close and "
+ "open /dev/video%d again.", cam->v4ldev->minor)
return err;
}
- if (cam->state & DEV_DISCONNECTED)
- return -ENODEV;
return 0;
}
@@ -894,6 +911,11 @@ sn9c102_store_val(struct class_device* cd, const char* buf, size_t len)
return -ENODEV;
}
+ if (!(cam->sensor->sysfs_ops & SN9C102_I2C_WRITE)) {
+ up(&sn9c102_sysfs_lock);
+ return -ENOSYS;
+ }
+
value = sn9c102_strtou8(buf, len, &count);
if (!count) {
up(&sn9c102_sysfs_lock);
@@ -937,7 +959,7 @@ static ssize_t sn9c102_show_i2c_reg(struct class_device* cd, char* buf)
up(&sn9c102_sysfs_lock);
return count;
-}
+}
static ssize_t
@@ -988,7 +1010,7 @@ static ssize_t sn9c102_show_i2c_val(struct class_device* cd, char* buf)
return -ENODEV;
}
- if (cam->sensor->slave_read_id == SN9C102_I2C_SLAVEID_UNAVAILABLE) {
+ if (!(cam->sensor->sysfs_ops & SN9C102_I2C_READ)) {
up(&sn9c102_sysfs_lock);
return -ENOSYS;
}
@@ -1129,6 +1151,24 @@ sn9c102_store_red(struct class_device* cd, const char* buf, size_t len)
}
+static ssize_t sn9c102_show_frame_header(struct class_device* cd, char* buf)
+{
+ struct sn9c102_device* cam;
+ ssize_t count;
+
+ cam = video_get_drvdata(to_video_device(cd));
+ if (!cam)
+ return -ENODEV;
+
+ count = sizeof(cam->sysfs.frame_header);
+ memcpy(buf, cam->sysfs.frame_header, count);
+
+ DBG(3, "Frame header, read bytes: %zd", count)
+
+ return count;
+}
+
+
static CLASS_DEVICE_ATTR(reg, S_IRUGO | S_IWUSR,
sn9c102_show_reg, sn9c102_store_reg);
static CLASS_DEVICE_ATTR(val, S_IRUGO | S_IWUSR,
@@ -1140,6 +1180,8 @@ static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
static CLASS_DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
static CLASS_DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
static CLASS_DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
+static CLASS_DEVICE_ATTR(frame_header, S_IRUGO,
+ sn9c102_show_frame_header, NULL);
static void sn9c102_create_sysfs(struct sn9c102_device* cam)
@@ -1148,14 +1190,14 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam)
video_device_create_file(v4ldev, &class_device_attr_reg);
video_device_create_file(v4ldev, &class_device_attr_val);
+ video_device_create_file(v4ldev, &class_device_attr_frame_header);
if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
video_device_create_file(v4ldev, &class_device_attr_green);
else if (cam->bridge == BRIDGE_SN9C103) {
video_device_create_file(v4ldev, &class_device_attr_blue);
video_device_create_file(v4ldev, &class_device_attr_red);
}
- if (cam->sensor->slave_write_id != SN9C102_I2C_SLAVEID_UNAVAILABLE ||
- cam->sensor->slave_read_id != SN9C102_I2C_SLAVEID_UNAVAILABLE) {
+ if (cam->sensor->sysfs_ops) {
video_device_create_file(v4ldev, &class_device_attr_i2c_reg);
video_device_create_file(v4ldev, &class_device_attr_i2c_val);
}
@@ -1164,11 +1206,11 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam)
/*****************************************************************************/
static int
-sn9c102_set_format(struct sn9c102_device* cam, struct v4l2_pix_format* fmt)
+sn9c102_set_pix_format(struct sn9c102_device* cam, struct v4l2_pix_format* pix)
{
int err = 0;
- if (fmt->pixelformat == V4L2_PIX_FMT_SN9C10X)
+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80, 0x18);
else
err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f, 0x18);
@@ -1273,7 +1315,9 @@ static int sn9c102_init(struct sn9c102_device* cam)
cam->compression.quality = cam->reg[0x17] & 0x01 ? 0 : 1;
else
err += sn9c102_set_compression(cam, &cam->compression);
- err += sn9c102_set_format(cam, &s->pix_format);
+ err += sn9c102_set_pix_format(cam, &s->pix_format);
+ if (s->set_pix_format)
+ err += s->set_pix_format(cam, &s->pix_format);
if (err)
return err;
@@ -2077,8 +2121,10 @@ static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
sn9c102_release_buffers(cam);
- err += sn9c102_set_format(cam, pix);
+ err += sn9c102_set_pix_format(cam, pix);
err += sn9c102_set_crop(cam, &rect);
+ if (s->set_pix_format)
+ err += s->set_pix_format(cam, pix);
if (s->set_crop)
err += s->set_crop(cam, &rect);
err += sn9c102_set_scale(cam, scale);
@@ -2450,8 +2496,8 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
n = sizeof(sn9c102_id_table)/sizeof(sn9c102_id_table[0]);
for (i = 0; i < n-1; i++)
- if (udev->descriptor.idVendor==sn9c102_id_table[i].idVendor &&
- udev->descriptor.idProduct==sn9c102_id_table[i].idProduct)
+ if (le16_to_cpu(udev->descriptor.idVendor) == sn9c102_id_table[i].idVendor &&
+ le16_to_cpu(udev->descriptor.idProduct) == sn9c102_id_table[i].idProduct)
break;
if (i == n-1)
return -ENODEV;
@@ -2551,6 +2597,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
DBG(2, "V4L2 device registered as /dev/video%d", cam->v4ldev->minor)
sn9c102_create_sysfs(cam);
+ DBG(2, "Optional device control through 'sysfs' interface ready")
usb_set_intfdata(intf, cam);
diff --git a/drivers/usb/media/sn9c102_hv7131d.c b/drivers/usb/media/sn9c102_hv7131d.c
new file mode 100644
index 00000000000000..b33860323aafa3
--- /dev/null
+++ b/drivers/usb/media/sn9c102_hv7131d.c
@@ -0,0 +1,271 @@
+/***************************************************************************
+ * Plug-in for HV7131D image sensor connected to the SN9C10x PC Camera *
+ * Controllers *
+ * *
+ * Copyright (C) 2004 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
+#include "sn9c102_sensor.h"
+
+
+static struct sn9c102_sensor hv7131d;
+
+
+static int hv7131d_init(struct sn9c102_device* cam)
+{
+ int err = 0;
+
+ err += sn9c102_write_reg(cam, 0x00, 0x10);
+ err += sn9c102_write_reg(cam, 0x00, 0x11);
+ err += sn9c102_write_reg(cam, 0x00, 0x14);
+ err += sn9c102_write_reg(cam, 0x60, 0x17);
+ err += sn9c102_write_reg(cam, 0x0e, 0x18);
+ err += sn9c102_write_reg(cam, 0xf2, 0x19);
+
+ err += sn9c102_i2c_write(cam, 0x01, 0x04);
+ err += sn9c102_i2c_write(cam, 0x02, 0x00);
+ err += sn9c102_i2c_write(cam, 0x28, 0x00);
+
+ return err;
+}
+
+
+static int hv7131d_get_ctrl(struct sn9c102_device* cam,
+ struct v4l2_control* ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ {
+ int r1 = sn9c102_i2c_read(cam, 0x26),
+ r2 = sn9c102_i2c_read(cam, 0x27);
+ if (r1 < 0 || r2 < 0)
+ return -EIO;
+ ctrl->value = (r1 << 8) | (r2 & 0xff);
+ }
+ return 0;
+ case V4L2_CID_RED_BALANCE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x31)) < 0)
+ return -EIO;
+ ctrl->value = 0x3f - (ctrl->value & 0x3f);
+ return 0;
+ case V4L2_CID_BLUE_BALANCE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x33)) < 0)
+ return -EIO;
+ ctrl->value = 0x3f - (ctrl->value & 0x3f);
+ return 0;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x32)) < 0)
+ return -EIO;
+ ctrl->value = 0x3f - (ctrl->value & 0x3f);
+ return 0;
+ case SN9C102_V4L2_CID_RESET_LEVEL:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x30)) < 0)
+ return -EIO;
+ ctrl->value &= 0x3f;
+ return 0;
+ case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
+ if ((ctrl->value = sn9c102_i2c_read(cam, 0x34)) < 0)
+ return -EIO;
+ ctrl->value &= 0x07;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+
+static int hv7131d_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
+{
+ int err = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8);
+ err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff);
+ break;
+ case V4L2_CID_RED_BALANCE:
+ err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value);
+ break;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value);
+ break;
+ case SN9C102_V4L2_CID_RESET_LEVEL:
+ err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
+ break;
+ case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
+ err += sn9c102_i2c_write(cam, 0x34, ctrl->value);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return err ? -EIO : 0;
+}
+
+
+static int hv7131d_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
+{
+ struct sn9c102_sensor* s = &hv7131d;
+ int err = 0;
+ u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
+ v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
+
+ err += sn9c102_write_reg(cam, h_start, 0x12);
+ err += sn9c102_write_reg(cam, v_start, 0x13);
+
+ return err;
+}
+
+
+static int hv7131d_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ int err = 0;
+
+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+ err += sn9c102_write_reg(cam, 0x42, 0x19);
+ else
+ err += sn9c102_write_reg(cam, 0xf2, 0x19);
+
+ return err;
+}
+
+
+static struct sn9c102_sensor hv7131d = {
+ .name = "HV7131D",
+ .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
+ .frequency = SN9C102_I2C_100KHZ,
+ .interface = SN9C102_I2C_2WIRES,
+ .i2c_slave_id = 0x11,
+ .init = &hv7131d_init,
+ .qctrl = {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "exposure",
+ .minimum = 0x0250,
+ .maximum = 0xffff,
+ .step = 0x0001,
+ .default_value = 0x0250,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "red balance",
+ .minimum = 0x00,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x00,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "blue balance",
+ .minimum = 0x00,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x20,
+ .flags = 0,
+ },
+ {
+ .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "green balance",
+ .minimum = 0x00,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x1e,
+ .flags = 0,
+ },
+ {
+ .id = SN9C102_V4L2_CID_RESET_LEVEL,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "reset level",
+ .minimum = 0x19,
+ .maximum = 0x3f,
+ .step = 0x01,
+ .default_value = 0x30,
+ .flags = 0,
+ },
+ {
+ .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "pixel bias voltage",
+ .minimum = 0x00,
+ .maximum = 0x07,
+ .step = 0x01,
+ .default_value = 0x02,
+ .flags = 0,
+ },
+ },
+ .get_ctrl = &hv7131d_get_ctrl,
+ .set_ctrl = &hv7131d_set_ctrl,
+ .cropcap = {
+ .bounds = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ .defrect = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ },
+ .set_crop = &hv7131d_set_crop,
+ .pix_format = {
+ .width = 640,
+ .height = 480,
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .priv = 8,
+ },
+ .set_pix_format = &hv7131d_set_pix_format
+};
+
+
+int sn9c102_probe_hv7131d(struct sn9c102_device* cam)
+{
+ int r0 = 0, r1 = 0, err = 0;
+
+ err += sn9c102_write_reg(cam, 0x01, 0x01);
+ err += sn9c102_write_reg(cam, 0x00, 0x01);
+ err += sn9c102_write_reg(cam, 0x28, 0x17);
+ if (err)
+ return -EIO;
+
+ r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
+ r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
+ if (r0 < 0 || r1 < 0)
+ return -EIO;
+
+ if (r0 != 0x00 && r1 != 0x04)
+ return -ENODEV;
+
+ sn9c102_attach_sensor(cam, &hv7131d);
+
+ return 0;
+}
diff --git a/drivers/usb/media/sn9c102_mi0343.c b/drivers/usb/media/sn9c102_mi0343.c
new file mode 100644
index 00000000000000..97f0d6d05c9ec5
--- /dev/null
+++ b/drivers/usb/media/sn9c102_mi0343.c
@@ -0,0 +1,363 @@
+/***************************************************************************
+ * Plug-in for MI-0343 image sensor connected to the SN9C10x PC Camera *
+ * Controllers *
+ * *
+ * Copyright (C) 2004 by Luca Risolia <luca.risolia@studio.unibo.it> *
+ * *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. *
+ ***************************************************************************/
+
+#include "sn9c102_sensor.h"
+
+
+static struct sn9c102_sensor mi0343;
+static u8 mi0343_i2c_data[5+1];
+
+
+static int mi0343_init(struct sn9c102_device* cam)
+{
+ int err = 0;
+
+ err += sn9c102_write_reg(cam, 0x00, 0x10);
+ err += sn9c102_write_reg(cam, 0x00, 0x11);
+ err += sn9c102_write_reg(cam, 0x0a, 0x14);
+ err += sn9c102_write_reg(cam, 0x40, 0x01);
+ err += sn9c102_write_reg(cam, 0x20, 0x17);
+ err += sn9c102_write_reg(cam, 0x07, 0x18);
+ err += sn9c102_write_reg(cam, 0xa0, 0x19);
+
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
+ 0x0d, 0x00, 0x01, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
+ 0x0d, 0x00, 0x00, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
+ 0x03, 0x01, 0xe1, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
+ 0x04, 0x02, 0x81, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
+ 0x05, 0x00, 0x17, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
+ 0x06, 0x00, 0x11, 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4, mi0343.i2c_slave_id,
+ 0x62, 0x04, 0x9a, 0, 0);
+
+ return err;
+}
+
+
+static int mi0343_get_ctrl(struct sn9c102_device* cam,
+ struct v4l2_control* ctrl)
+{
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
+ 0x09, 2+1, mi0343_i2c_data) < 0)
+ return -EIO;
+ ctrl->value = mi0343_i2c_data[2];
+ return 0;
+ case V4L2_CID_GAIN:
+ if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
+ 0x35, 2+1, mi0343_i2c_data) < 0)
+ return -EIO;
+ break;
+ case V4L2_CID_HFLIP:
+ if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
+ 0x20, 2+1, mi0343_i2c_data) < 0)
+ return -EIO;
+ ctrl->value = mi0343_i2c_data[3] & 0x20 ? 1 : 0;
+ return 0;
+ case V4L2_CID_VFLIP:
+ if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
+ 0x20, 2+1, mi0343_i2c_data) < 0)
+ return -EIO;
+ ctrl->value = mi0343_i2c_data[3] & 0x80 ? 1 : 0;
+ return 0;
+ case V4L2_CID_RED_BALANCE:
+ if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
+ 0x2d, 2+1, mi0343_i2c_data) < 0)
+ return -EIO;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
+ 0x2c, 2+1, mi0343_i2c_data) < 0)
+ return -EIO;
+ break;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id,
+ 0x2e, 2+1, mi0343_i2c_data) < 0)
+ return -EIO;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ case V4L2_CID_RED_BALANCE:
+ case V4L2_CID_BLUE_BALANCE:
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ ctrl->value = mi0343_i2c_data[3] | (mi0343_i2c_data[2] << 8);
+ if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
+ ctrl->value -= 0x10;
+ else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
+ ctrl->value -= 0x60;
+ else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff)
+ ctrl->value -= 0xe0;
+ }
+
+ return 0;
+}
+
+
+static int mi0343_set_ctrl(struct sn9c102_device* cam,
+ const struct v4l2_control* ctrl)
+{
+ u16 reg = 0;
+ int err = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_GAIN:
+ case V4L2_CID_RED_BALANCE:
+ case V4L2_CID_BLUE_BALANCE:
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ if (ctrl->value <= (0x3f-0x10))
+ reg = 0x10 + ctrl->value;
+ else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60)))
+ reg = 0x60 + (ctrl->value - (0x3f-0x10));
+ else
+ reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60));
+ break;
+ }
+
+ switch (ctrl->id) {
+ case V4L2_CID_EXPOSURE:
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x09, ctrl->value, 0x00,
+ 0, 0);
+ break;
+ case V4L2_CID_GAIN:
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x35, reg >> 8, reg & 0xff,
+ 0, 0);
+ break;
+ case V4L2_CID_HFLIP:
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x20, ctrl->value ? 0x40:0x00,
+ ctrl->value ? 0x20:0x00,
+ 0, 0);
+ break;
+ case V4L2_CID_VFLIP:
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x20, ctrl->value ? 0x80:0x00,
+ ctrl->value ? 0x80:0x00,
+ 0, 0);
+ break;
+ case V4L2_CID_RED_BALANCE:
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x2d, reg >> 8, reg & 0xff,
+ 0, 0);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x2c, reg >> 8, reg & 0xff,
+ 0, 0);
+ break;
+ case SN9C102_V4L2_CID_GREEN_BALANCE:
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x2b, reg >> 8, reg & 0xff,
+ 0, 0);
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x2e, reg >> 8, reg & 0xff,
+ 0, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return err ? -EIO : 0;
+}
+
+
+static int mi0343_set_crop(struct sn9c102_device* cam,
+ const struct v4l2_rect* rect)
+{
+ struct sn9c102_sensor* s = &mi0343;
+ int err = 0;
+ u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
+ v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
+
+ err += sn9c102_write_reg(cam, h_start, 0x12);
+ err += sn9c102_write_reg(cam, v_start, 0x13);
+
+ return err;
+}
+
+
+static int mi0343_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ int err = 0;
+
+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x0a, 0x00, 0x03, 0, 0);
+ err += sn9c102_write_reg(cam, 0x20, 0x19);
+ } else {
+ err += sn9c102_i2c_try_raw_write(cam, &mi0343, 4,
+ mi0343.i2c_slave_id,
+ 0x0a, 0x00, 0x05, 0, 0);
+ err += sn9c102_write_reg(cam, 0xa0, 0x19);
+ }
+
+ return err;
+}
+
+
+static struct sn9c102_sensor mi0343 = {
+ .name = "MI-0343",
+ .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .frequency = SN9C102_I2C_100KHZ,
+ .interface = SN9C102_I2C_2WIRES,
+ .i2c_slave_id = 0x5d,
+ .init = &mi0343_init,
+ .qctrl = {
+ {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "exposure",
+ .minimum = 0x00,
+ .maximum = 0x0f,
+ .step = 0x01,
+ .default_value = 0x06,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "global gain",
+ .minimum = 0x00,
+ .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/
+ .step = 0x01,
+ .default_value = 0x00,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "horizontal mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "vertical mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = 0,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "red balance",
+ .minimum = 0x00,
+ .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
+ .step = 0x01,
+ .default_value = 0x00,
+ .flags = 0,
+ },
+ {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "blue balance",
+ .minimum = 0x00,
+ .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
+ .step = 0x01,
+ .default_value = 0x00,
+ .flags = 0,
+ },
+ {
+ .id = SN9C102_V4L2_CID_GREEN_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "green balance",
+ .minimum = 0x00,
+ .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)),
+ .step = 0x01,
+ .default_value = 0x00,
+ .flags = 0,
+ },
+ },
+ .get_ctrl = &mi0343_get_ctrl,
+ .set_ctrl = &mi0343_set_ctrl,
+ .cropcap = {
+ .bounds = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ .defrect = {
+ .left = 0,
+ .top = 0,
+ .width = 640,
+ .height = 480,
+ },
+ },
+ .set_crop = &mi0343_set_crop,
+ .pix_format = {
+ .width = 640,
+ .height = 480,
+ .pixelformat = V4L2_PIX_FMT_SBGGR8,
+ .priv = 8,
+ },
+ .set_pix_format = &mi0343_set_pix_format
+};
+
+
+int sn9c102_probe_mi0343(struct sn9c102_device* cam)
+{
+ int err = 0;
+
+ err += sn9c102_write_reg(cam, 0x01, 0x01);
+ err += sn9c102_write_reg(cam, 0x00, 0x01);
+ err += sn9c102_write_reg(cam, 0x28, 0x17);
+ if (err)
+ return -EIO;
+
+ if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
+ 2, mi0343_i2c_data) < 0)
+ return -EIO;
+
+ if (mi0343_i2c_data[4] != 0x32 && mi0343_i2c_data[3] != 0xe3)
+ return -ENODEV;
+
+ sn9c102_attach_sensor(cam, &mi0343);
+
+ return 0;
+}
diff --git a/drivers/usb/media/sn9c102_pas106b.c b/drivers/usb/media/sn9c102_pas106b.c
index 54942d607a9306..c76abd88dad1e7 100644
--- a/drivers/usb/media/sn9c102_pas106b.c
+++ b/drivers/usb/media/sn9c102_pas106b.c
@@ -96,11 +96,6 @@ static int pas106b_get_ctrl(struct sn9c102_device* cam,
return -EIO;
ctrl->value &= 0xf8;
return 0;
- case SN9C102_V4L2_CID_DAC_SIGN:
- if ((ctrl->value = sn9c102_i2c_read(cam, 0x07)) < 0)
- return -EIO;
- ctrl->value &= 0x01;
- return 0;
default:
return -EINVAL;
}
@@ -136,13 +131,6 @@ static int pas106b_set_ctrl(struct sn9c102_device* cam,
case SN9C102_V4L2_CID_DAC_MAGNITUDE:
err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3);
break;
- case SN9C102_V4L2_CID_DAC_SIGN:
- {
- int r;
- err += (r = sn9c102_i2c_read(cam, 0x07)) < 0 ? r : 0;
- err += sn9c102_i2c_write(cam, 0x07, r | ctrl->value);
- }
- break;
default:
return -EINVAL;
}
@@ -167,13 +155,27 @@ static int pas106b_set_crop(struct sn9c102_device* cam,
}
+static int pas106b_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ int err = 0;
+
+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+ err += sn9c102_write_reg(cam, 0x2c, 0x17);
+ else
+ err += sn9c102_write_reg(cam, 0x20, 0x17);
+
+ return err;
+}
+
+
static struct sn9c102_sensor pas106b = {
.name = "PAS106B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
- .slave_read_id = 0x40,
- .slave_write_id = 0x40,
+ .i2c_slave_id = 0x40,
.init = &pas106b_init,
.qctrl = {
{
@@ -182,7 +184,7 @@ static struct sn9c102_sensor pas106b = {
.name = "exposure",
.minimum = 0x125,
.maximum = 0xfff,
- .step = 0x01,
+ .step = 0x001,
.default_value = 0x140,
.flags = 0,
},
@@ -246,16 +248,6 @@ static struct sn9c102_sensor pas106b = {
.default_value = 0x01,
.flags = 0,
},
- {
- .id = SN9C102_V4L2_CID_DAC_SIGN,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "DAC sign",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
},
.get_ctrl = &pas106b_get_ctrl,
.set_ctrl = &pas106b_set_ctrl,
@@ -279,7 +271,8 @@ static struct sn9c102_sensor pas106b = {
.height = 288,
.pixelformat = V4L2_PIX_FMT_SBGGR8,
.priv = 8, /* we use this field as 'bits per pixel' */
- }
+ },
+ .set_pix_format = &pas106b_set_pix_format
};
diff --git a/drivers/usb/media/sn9c102_pas202bcb.c b/drivers/usb/media/sn9c102_pas202bcb.c
index 3e2fd5a6f28130..5ca54c7daaf2be 100644
--- a/drivers/usb/media/sn9c102_pas202bcb.c
+++ b/drivers/usb/media/sn9c102_pas202bcb.c
@@ -6,7 +6,7 @@
* <medaglia@undl.org.br> *
* http://cadu.homelinux.com:8080/ *
* *
- * DAC Magnitude, DAC sign, exposure and green gain controls added by *
+ * DAC Magnitude, exposure and green gain controls added by *
* Luca Risolia <luca.risolia@studio.unibo.it> *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -95,17 +95,26 @@ static int pas202bcb_get_ctrl(struct sn9c102_device* cam,
if ((ctrl->value = sn9c102_i2c_read(cam, 0x0c)) < 0)
return -EIO;
return 0;
- case SN9C102_V4L2_CID_DAC_SIGN:
- if ((ctrl->value = sn9c102_i2c_read(cam, 0x0b)) < 0)
- return -EIO;
- ctrl->value &= 0x01;
- return 0;
default:
return -EINVAL;
}
}
+static int pas202bcb_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ int err = 0;
+
+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+ err += sn9c102_write_reg(cam, 0x24, 0x17);
+ else
+ err += sn9c102_write_reg(cam, 0x20, 0x17);
+
+ return err;
+}
+
+
static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
const struct v4l2_control* ctrl)
{
@@ -131,13 +140,6 @@ static int pas202bcb_set_ctrl(struct sn9c102_device* cam,
case SN9C102_V4L2_CID_DAC_MAGNITUDE:
err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
break;
- case SN9C102_V4L2_CID_DAC_SIGN:
- {
- int r;
- err += (r = sn9c102_i2c_read(cam, 0x0b)) < 0 ? r : 0;
- err += sn9c102_i2c_write(cam, 0x0b, r | ctrl->value);
- }
- break;
default:
return -EINVAL;
}
@@ -166,10 +168,10 @@ static struct sn9c102_sensor pas202bcb = {
.name = "PAS202BCB",
.maintainer = "Carlos Eduardo Medaglia Dyonisio "
"<medaglia@undl.org.br>",
+ .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_2WIRES,
- .slave_read_id = 0x40,
- .slave_write_id = 0x40,
+ .i2c_slave_id = 0x40,
.init = &pas202bcb_init,
.qctrl = {
{
@@ -178,7 +180,7 @@ static struct sn9c102_sensor pas202bcb = {
.name = "exposure",
.minimum = 0x01e5,
.maximum = 0x3fff,
- .step = 0x01,
+ .step = 0x0001,
.default_value = 0x01e5,
.flags = 0,
},
@@ -232,16 +234,6 @@ static struct sn9c102_sensor pas202bcb = {
.default_value = 0x04,
.flags = 0,
},
- {
- .id = SN9C102_V4L2_CID_DAC_SIGN,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "DAC sign",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x01,
- .flags = 0,
- },
},
.get_ctrl = &pas202bcb_get_ctrl,
.set_ctrl = &pas202bcb_set_ctrl,
@@ -265,7 +257,8 @@ static struct sn9c102_sensor pas202bcb = {
.height = 480,
.pixelformat = V4L2_PIX_FMT_SBGGR8,
.priv = 8,
- }
+ },
+ .set_pix_format = &pas202bcb_set_pix_format
};
@@ -286,7 +279,7 @@ int sn9c102_probe_pas202bcb(struct sn9c102_device* cam)
r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
-
+
if (r0 < 0 || r1 < 0)
return -EIO;
diff --git a/drivers/usb/media/sn9c102_sensor.h b/drivers/usb/media/sn9c102_sensor.h
index ebafc280911de8..035f3b32bf222d 100644
--- a/drivers/usb/media/sn9c102_sensor.h
+++ b/drivers/usb/media/sn9c102_sensor.h
@@ -62,6 +62,8 @@ struct sn9c102_sensor;
ahead.
Functions must return 0 on success, the appropriate error otherwise.
*/
+extern int sn9c102_probe_hv7131d(struct sn9c102_device* cam);
+extern int sn9c102_probe_mi0343(struct sn9c102_device* cam);
extern int sn9c102_probe_pas106b(struct sn9c102_device* cam);
extern int sn9c102_probe_pas202bcb(struct sn9c102_device* cam);
extern int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam);
@@ -74,8 +76,10 @@ extern int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam);
*/
#define SN9C102_SENSOR_TABLE \
static int (*sn9c102_sensor_table[])(struct sn9c102_device*) = { \
+ &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */ \
&sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */ \
&sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */ \
+ &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */ \
&sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */ \
&sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */ \
NULL, \
@@ -97,7 +101,7 @@ static const struct usb_device_id sn9c102_id_table[] = { \
{ USB_DEVICE(0x0c45, 0x6025), }, /* TAS5130D1B and TAS5110C1B */ \
{ USB_DEVICE(0x0c45, 0x6028), }, /* PAS202BCB */ \
{ USB_DEVICE(0x0c45, 0x6029), }, /* PAS106B */ \
- { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131[D|E1] */ \
+ { USB_DEVICE(0x0c45, 0x602a), }, /* HV7131D */ \
{ USB_DEVICE(0x0c45, 0x602b), }, /* MI-0343 */ \
{ USB_DEVICE(0x0c45, 0x602c), }, /* OV7620 */ \
{ USB_DEVICE(0x0c45, 0x6030), }, /* MI03x */ \
@@ -147,15 +151,23 @@ extern int sn9c102_i2c_try_read(struct sn9c102_device*,struct sn9c102_sensor*,
u8 address);
/*
- This must be used if and only if the sensor doesn't implement the standard
- I2C protocol. There a number of good reasons why you must use the
- single-byte versions of this function: do not abuse. It writes n bytes,
- from data0 to datan, (registers 0x09 - 0x09+n of SN9C10X chip).
+ These must be used if and only if the sensor doesn't implement the standard
+ I2C protocol. There are a number of good reasons why you must use the
+ single-byte versions of these functions: do not abuse. The first function
+ writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C10X
+ chip. The second one programs the registers 0x09 and 0x10 with data0 and
+ data1, and places the n bytes read from the sensor register table in the
+ buffer pointed by 'buffer'. Both the functions return -1 on error; the write
+ version returns 0 on success, while the read version returns the first read
+ byte.
*/
extern int sn9c102_i2c_try_raw_write(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor, u8 n,
u8 data0, u8 data1, u8 data2, u8 data3,
u8 data4, u8 data5);
+extern int sn9c102_i2c_try_raw_read(struct sn9c102_device* cam,
+ struct sn9c102_sensor* sensor, u8 data0,
+ u8 data1, u8 n, u8 buffer[]);
/* To be used after the sensor struct has been attached to the camera struct */
extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
@@ -166,16 +178,21 @@ extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
/*
- NOTE: there are no debugging functions here. To uniform the output you must
- use the dev_info()/dev_warn()/dev_err() macros defined in device.h, already
- included here, the argument being the struct device 'dev' of the sensor
- structure. Do NOT use these macros before the sensor is attached or the
- kernel will crash! However you should not need to notify the user about
+ NOTE: there are no exported debugging functions. To uniform the output you
+ must use the dev_info()/dev_warn()/dev_err() macros defined in device.h,
+ already included here, the argument being the struct device 'dev' of the
+ sensor structure. Do NOT use these macros before the sensor is attached or
+ the kernel will crash! However, you should not need to notify the user about
common errors or other messages, since this is done by the master module.
*/
/*****************************************************************************/
+enum sn9c102_i2c_sysfs_ops {
+ SN9C102_I2C_READ = 0x01,
+ SN9C102_I2C_WRITE = 0x02,
+};
+
enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */
SN9C102_I2C_100KHZ = 0x01,
SN9C102_I2C_400KHZ = 0x02,
@@ -186,13 +203,13 @@ enum sn9c102_i2c_interface {
SN9C102_I2C_3WIRES,
};
-#define SN9C102_I2C_SLAVEID_FICTITIOUS 0xff
-#define SN9C102_I2C_SLAVEID_UNAVAILABLE 0x00
-
struct sn9c102_sensor {
char name[32], /* sensor name */
maintainer[64]; /* name of the mantainer <email> */
+ /* Supported operations through the 'sysfs' interface */
+ enum sn9c102_i2c_sysfs_ops sysfs_ops;
+
/*
These sensor capabilities must be provided if the SN9C10X controller
needs to communicate through the sensor serial interface by using
@@ -202,10 +219,10 @@ struct sn9c102_sensor {
enum sn9c102_i2c_interface interface;
/*
- These identifiers must be provided if the image sensor implements
+ This identifier must be provided if the image sensor implements
the standard I2C protocol.
*/
- u8 slave_read_id, slave_write_id; /* reg. 0x09 */
+ u8 i2c_slave_id; /* reg. 0x09 */
/*
NOTE: Where not noted,most of the functions below are not mandatory.
@@ -215,7 +232,7 @@ struct sn9c102_sensor {
int (*init)(struct sn9c102_device* cam);
/*
- This function is called after the sensor has been attached.
+ This function will be called after the sensor has been attached.
It should be used to initialize the sensor only, but may also
configure part of the SN9C10X chip if necessary. You don't need to
setup picture settings like brightness, contrast, etc.. here, if
@@ -315,6 +332,14 @@ struct sn9c102_sensor {
matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
*/
+ int (*set_pix_format)(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix);
+ /*
+ To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to
+ SN9C10X pixel format or viceversa. On error return the corresponding
+ error code without rolling back.
+ */
+
const struct device* dev;
/*
This is the argument for dev_err(), dev_info() and dev_warn(). It
@@ -341,7 +366,8 @@ struct sn9c102_sensor {
/* Private ioctl's for control settings supported by some image sensors */
#define SN9C102_V4L2_CID_DAC_MAGNITUDE V4L2_CID_PRIVATE_BASE
-#define SN9C102_V4L2_CID_DAC_SIGN V4L2_CID_PRIVATE_BASE + 1
-#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 2
+#define SN9C102_V4L2_CID_GREEN_BALANCE V4L2_CID_PRIVATE_BASE + 1
+#define SN9C102_V4L2_CID_RESET_LEVEL V4L2_CID_PRIVATE_BASE + 2
+#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE V4L2_CID_PRIVATE_BASE + 3
#endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/usb/media/sn9c102_tas5110c1b.c b/drivers/usb/media/sn9c102_tas5110c1b.c
index 03153cae2db308..14a8bdd147a5f4 100644
--- a/drivers/usb/media/sn9c102_tas5110c1b.c
+++ b/drivers/usb/media/sn9c102_tas5110c1b.c
@@ -93,7 +93,21 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam,
/* Don't change ! */
err += sn9c102_write_reg(cam, 0x14, 0x1a);
err += sn9c102_write_reg(cam, 0x0a, 0x1b);
- err += sn9c102_write_reg(cam, 0xfb, 0x19);
+ err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
+
+ return err;
+}
+
+
+static int tas5110c1b_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ int err = 0;
+
+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+ err += sn9c102_write_reg(cam, 0x2b, 0x19);
+ else
+ err += sn9c102_write_reg(cam, 0xfb, 0x19);
return err;
}
@@ -102,10 +116,9 @@ static int tas5110c1b_set_crop(struct sn9c102_device* cam,
static struct sn9c102_sensor tas5110c1b = {
.name = "TAS5110C1B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .sysfs_ops = SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES,
- .slave_read_id = SN9C102_I2C_SLAVEID_UNAVAILABLE,
- .slave_write_id = SN9C102_I2C_SLAVEID_FICTITIOUS,
.init = &tas5110c1b_init,
.qctrl = {
{
@@ -141,7 +154,8 @@ static struct sn9c102_sensor tas5110c1b = {
.height = 288,
.pixelformat = V4L2_PIX_FMT_SBGGR8,
.priv = 8,
- }
+ },
+ .set_pix_format = &tas5110c1b_set_pix_format
};
@@ -151,9 +165,9 @@ int sn9c102_probe_tas5110c1b(struct sn9c102_device* cam)
sn9c102_attach_sensor(cam, &tas5110c1b);
/* Sensor detection is based on USB pid/vid */
- if (tas5110c1b.usbdev->descriptor.idProduct != 0x6001 &&
- tas5110c1b.usbdev->descriptor.idProduct != 0x6005 &&
- tas5110c1b.usbdev->descriptor.idProduct != 0x60ab)
+ if (le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6001 &&
+ le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x6005 &&
+ le16_to_cpu(tas5110c1b.usbdev->descriptor.idProduct) != 0x60ab)
return -ENODEV;
return 0;
diff --git a/drivers/usb/media/sn9c102_tas5130d1b.c b/drivers/usb/media/sn9c102_tas5130d1b.c
index 36b00d12a6e5c3..6bb23e16be3ee5 100644
--- a/drivers/usb/media/sn9c102_tas5130d1b.c
+++ b/drivers/usb/media/sn9c102_tas5130d1b.c
@@ -98,7 +98,21 @@ static int tas5130d1b_set_crop(struct sn9c102_device* cam,
/* Do NOT change! */
err += sn9c102_write_reg(cam, 0x1f, 0x1a);
err += sn9c102_write_reg(cam, 0x1a, 0x1b);
- err += sn9c102_write_reg(cam, 0xf3, 0x19);
+ err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
+
+ return err;
+}
+
+
+static int tas5130d1b_set_pix_format(struct sn9c102_device* cam,
+ const struct v4l2_pix_format* pix)
+{
+ int err = 0;
+
+ if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
+ err += sn9c102_write_reg(cam, 0x63, 0x19);
+ else
+ err += sn9c102_write_reg(cam, 0xf3, 0x19);
return err;
}
@@ -107,10 +121,9 @@ static int tas5130d1b_set_crop(struct sn9c102_device* cam,
static struct sn9c102_sensor tas5130d1b = {
.name = "TAS5130D1B",
.maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
+ .sysfs_ops = SN9C102_I2C_WRITE,
.frequency = SN9C102_I2C_100KHZ,
.interface = SN9C102_I2C_3WIRES,
- .slave_read_id = SN9C102_I2C_SLAVEID_UNAVAILABLE,
- .slave_write_id = SN9C102_I2C_SLAVEID_FICTITIOUS,
.init = &tas5130d1b_init,
.qctrl = {
{
@@ -156,7 +169,8 @@ static struct sn9c102_sensor tas5130d1b = {
.height = 480,
.pixelformat = V4L2_PIX_FMT_SBGGR8,
.priv = 8,
- }
+ },
+ .set_pix_format = &tas5130d1b_set_pix_format
};
@@ -166,8 +180,8 @@ int sn9c102_probe_tas5130d1b(struct sn9c102_device* cam)
sn9c102_attach_sensor(cam, &tas5130d1b);
/* Sensor detection is based on USB pid/vid */
- if (tas5130d1b.usbdev->descriptor.idProduct != 0x6025 &&
- tas5130d1b.usbdev->descriptor.idProduct != 0x60aa)
+ if (le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x6025 &&
+ le16_to_cpu(tas5130d1b.usbdev->descriptor.idProduct) != 0x60aa)
return -ENODEV;
return 0;
diff --git a/drivers/usb/media/stv680.c b/drivers/usb/media/stv680.c
index b8e798345595ae..ae455c8e370286 100644
--- a/drivers/usb/media/stv680.c
+++ b/drivers/usb/media/stv680.c
@@ -1371,7 +1371,8 @@ static int stv680_probe (struct usb_interface *intf, const struct usb_device_id
interface = &intf->altsetting[0];
/* Is it a STV680? */
- if ((dev->descriptor.idVendor == USB_PENCAM_VENDOR_ID) && (dev->descriptor.idProduct == USB_PENCAM_PRODUCT_ID)) {
+ if ((le16_to_cpu(dev->descriptor.idVendor) == USB_PENCAM_VENDOR_ID) &&
+ (le16_to_cpu(dev->descriptor.idProduct) == USB_PENCAM_PRODUCT_ID)) {
camera_name = "STV0680";
PDEBUG (0, "STV(i): STV0680 camera found.");
} else {
diff --git a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c
index 84f38839c49109..fec1f09615f4df 100644
--- a/drivers/usb/media/ultracam.c
+++ b/drivers/usb/media/ultracam.c
@@ -524,12 +524,8 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
if (dev->descriptor.bNumConfigurations != 1)
return -ENODEV;
- /* Is it an IBM camera? */
- if ((dev->descriptor.idVendor != ULTRACAM_VENDOR_ID) ||
- (dev->descriptor.idProduct != ULTRACAM_PRODUCT_ID))
- return -ENODEV;
-
- info("IBM Ultra camera found (rev. 0x%04x)", dev->descriptor.bcdDevice);
+ info("IBM Ultra camera found (rev. 0x%04x)",
+ le16_to_cpu(dev->descriptor.bcdDevice));
/* Validate found interface: must have one ISO endpoint */
nas = intf->num_altsetting;
@@ -569,7 +565,7 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
interface->desc.bInterfaceNumber);
return -ENODEV;
}
- if (endpoint->wMaxPacketSize == 0) {
+ if (le16_to_cpu(endpoint->wMaxPacketSize) == 0) {
if (inactInterface < 0)
inactInterface = i;
else {
@@ -579,15 +575,15 @@ static int ultracam_probe(struct usb_interface *intf, const struct usb_device_id
} else {
if (actInterface < 0) {
actInterface = i;
- maxPS = endpoint->wMaxPacketSize;
+ maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
if (debug > 0)
info("Active setting=%d. maxPS=%d.", i, maxPS);
} else {
/* Got another active alt. setting */
- if (maxPS < endpoint->wMaxPacketSize) {
+ if (maxPS < le16_to_cpu(endpoint->wMaxPacketSize)) {
/* This one is better! */
actInterface = i;
- maxPS = endpoint->wMaxPacketSize;
+ maxPS = le16_to_cpu(endpoint->wMaxPacketSize);
if (debug > 0) {
info("Even better ctive setting=%d. maxPS=%d.",
i, maxPS);
diff --git a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
index 411608f1b76f7b..908ff5b7a9d65a 100644
--- a/drivers/usb/media/vicam.c
+++ b/drivers/usb/media/vicam.c
@@ -1281,12 +1281,6 @@ vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
const struct usb_endpoint_descriptor *endpoint;
struct vicam_camera *cam;
- /* See if the device offered us matches what we can accept */
- if ((dev->descriptor.idVendor != USB_VICAM_VENDOR_ID) ||
- (dev->descriptor.idProduct != USB_VICAM_PRODUCT_ID)) {
- return -ENODEV;
- }
-
printk(KERN_INFO "ViCam based webcam connected\n");
interface = intf->cur_altsetting;
diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c
index 6604a30d5398e9..689e79e4bcee8b 100644
--- a/drivers/usb/media/w9968cf.c
+++ b/drivers/usb/media/w9968cf.c
@@ -3516,11 +3516,11 @@ w9968cf_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
u8 sc = 0; /* number of simultaneous cameras */
static unsigned short dev_nr = 0; /* we are handling device number n */
- if (udev->descriptor.idVendor == winbond_id_table[0].idVendor &&
- udev->descriptor.idProduct == winbond_id_table[0].idProduct)
+ if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[0].idVendor &&
+ le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[0].idProduct)
mod_id = W9968CF_MOD_CLVBWGP; /* see camlist[] table */
- else if (udev->descriptor.idVendor == winbond_id_table[1].idVendor &&
- udev->descriptor.idProduct == winbond_id_table[1].idProduct)
+ else if (le16_to_cpu(udev->descriptor.idVendor) == winbond_id_table[1].idVendor &&
+ le16_to_cpu(udev->descriptor.idProduct) == winbond_id_table[1].idProduct)
mod_id = W9968CF_MOD_GENERIC; /* see camlist[] table */
else
return -ENODEV;
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index a3dd6f03efb75e..c2251613a0aa0f 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -32,26 +32,6 @@ config USB_EMI26
To compile this driver as a module, choose M here: the
module will be called emi26.
-config USB_TIGL
- tristate "Texas Instruments Graph Link USB (aka SilverLink) cable support"
- depends on USB
- ---help---
- If you own a Texas Instruments graphing calculator and use a
- TI-GRAPH LINK USB cable (aka SilverLink), then you might be
- interested in this driver.
-
- If you enable this driver, you will be able to communicate with
- your calculator through a set of device nodes under /dev.
-
- To compile this driver as a module, choose M here: the
- module will be called tiglusb.
-
- If you don't know what the SilverLink cable is or what a Texas
- Instruments graphing calculator is, then you probably don't need this
- driver.
-
- If unsure, say N.
-
config USB_AUERSWALD
tristate "USB Auerswald ISDN support (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
index 4936caf5f6784b..4f12464a1c869b 100644
--- a/drivers/usb/misc/Makefile
+++ b/drivers/usb/misc/Makefile
@@ -14,5 +14,4 @@ obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o
obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o
obj-$(CONFIG_USB_RIO500) += rio500.o
obj-$(CONFIG_USB_TEST) += usbtest.o
-obj-$(CONFIG_USB_TIGL) += tiglusb.o
obj-$(CONFIG_USB_USS720) += uss720.o
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
index 94842c34a4c441..d656592c25dd23 100644
--- a/drivers/usb/misc/auerswald.c
+++ b/drivers/usb/misc/auerswald.c
@@ -1123,16 +1123,16 @@ static void auerswald_int_free (pauerswald_t cp)
static int auerswald_int_open (pauerswald_t cp)
{
int ret;
- struct usb_endpoint_descriptor *ep;
+ struct usb_host_endpoint *ep;
int irqsize;
dbg ("auerswald_int_open");
- ep = usb_epnum_to_ep_desc (cp->usbdev, USB_DIR_IN | AU_IRQENDP);
+ ep = cp->usbdev->ep_in[AU_IRQENDP];
if (!ep) {
ret = -EFAULT;
goto intoend;
}
- irqsize = ep->wMaxPacketSize;
+ irqsize = le16_to_cpu(ep->desc.wMaxPacketSize);
cp->irqsize = irqsize;
/* allocate the urb and data buffer */
@@ -1151,7 +1151,9 @@ static int auerswald_int_open (pauerswald_t cp)
}
}
/* setup urb */
- usb_fill_int_urb (cp->inturbp, cp->usbdev, usb_rcvintpipe (cp->usbdev,AU_IRQENDP), cp->intbufp, irqsize, auerswald_int_complete, cp, ep->bInterval);
+ usb_fill_int_urb (cp->inturbp, cp->usbdev,
+ usb_rcvintpipe (cp->usbdev,AU_IRQENDP), cp->intbufp,
+ irqsize, auerswald_int_complete, cp, ep->desc.bInterval);
/* start the urb */
cp->inturbp->status = 0; /* needed! */
ret = usb_submit_urb (cp->inturbp, GFP_KERNEL);
@@ -1929,11 +1931,8 @@ static int auerswald_probe (struct usb_interface *intf,
int ret;
dbg ("probe: vendor id 0x%x, device id 0x%x",
- usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
-
- /* See if the device offered us matches that we can accept */
- if (usbdev->descriptor.idVendor != ID_AUERSWALD)
- return -ENODEV;
+ le16_to_cpu(usbdev->descriptor.idVendor),
+ le16_to_cpu(usbdev->descriptor.idProduct));
/* we use only the first -and only- interface */
if (intf->altsetting->desc.bInterfaceNumber != 0)
@@ -1967,7 +1966,7 @@ static int auerswald_probe (struct usb_interface *intf,
cp->dtindex = intf->minor;
/* Get the usb version of the device */
- cp->version = cp->usbdev->descriptor.bcdDevice;
+ cp->version = le16_to_cpu(cp->usbdev->descriptor.bcdDevice);
dbg ("Version is %X", cp->version);
/* allow some time to settle the device */
diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c
index cd37e011c4638b..66920ab9faf657 100644
--- a/drivers/usb/misc/emi26.c
+++ b/drivers/usb/misc/emi26.c
@@ -213,11 +213,9 @@ static int emi26_probe(struct usb_interface *intf, const struct usb_device_id *i
struct usb_device *dev = interface_to_usbdev(intf);
info("%s start", __FUNCTION__);
-
- if((dev->descriptor.idVendor == EMI26_VENDOR_ID) && (dev->descriptor.idProduct == EMI26_PRODUCT_ID)) {
- emi26_load_firmware(dev);
- }
-
+
+ emi26_load_firmware(dev);
+
/* do not return the driver context, let real audio driver do that */
return -EIO;
}
diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c
index 5c5cb41844a548..189986af2ac7db 100644
--- a/drivers/usb/misc/emi62.c
+++ b/drivers/usb/misc/emi62.c
@@ -255,10 +255,8 @@ static int emi62_probe(struct usb_interface *intf, const struct usb_device_id *i
info("%s start", __FUNCTION__);
- if((dev->descriptor.idVendor == EMI62_VENDOR_ID) && (dev->descriptor.idProduct == EMI62_PRODUCT_ID)) {
- emi62_load_firmware(dev);
- }
-
+ emi62_load_firmware(dev);
+
/* do not return the driver context, let real audio driver do that */
return -EIO;
}
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
index e83e91148970e5..edf3df586a8c87 100644
--- a/drivers/usb/misc/legousbtower.c
+++ b/drivers/usb/misc/legousbtower.c
@@ -405,7 +405,7 @@ static int tower_open (struct inode *inode, struct file *file)
dev->udev,
usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress),
dev->interrupt_in_buffer,
- dev->interrupt_in_endpoint->wMaxPacketSize,
+ le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize),
tower_interrupt_in_callback,
dev,
dev->interrupt_in_interval);
@@ -859,13 +859,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
info ("udev is NULL.");
}
- /* See if the device offered us matches what we can accept */
- if ((udev->descriptor.idVendor != LEGO_USB_TOWER_VENDOR_ID) ||
- (udev->descriptor.idProduct != LEGO_USB_TOWER_PRODUCT_ID)) {
- return -ENODEV;
- }
-
-
/* allocate memory for our device state and intialize it */
dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL);
@@ -931,7 +924,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
err("Couldn't allocate read_buffer");
goto error;
}
- dev->interrupt_in_buffer = kmalloc (dev->interrupt_in_endpoint->wMaxPacketSize, GFP_KERNEL);
+ dev->interrupt_in_buffer = kmalloc (le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), GFP_KERNEL);
if (!dev->interrupt_in_buffer) {
err("Couldn't allocate interrupt_in_buffer");
goto error;
diff --git a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
deleted file mode 100644
index 4a5d2b0021901a..00000000000000
--- a/drivers/usb/misc/tiglusb.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/* Hey EMACS -*- linux-c -*-
- *
- * tiglusb -- Texas Instruments' USB GraphLink (aka SilverLink) driver.
- * Target: Texas Instruments graphing calculators (http://lpg.ticalc.org).
- *
- * Copyright (C) 2001-2004:
- * Romain Lievin <roms@tilp.info>
- * Julien BLACHE <jb@technologeek.org>
- * under the terms of the GNU General Public License.
- *
- * Based on dabusb.c, printer.c & scanner.c
- *
- * Please see the file: Documentation/usb/silverlink.txt
- * and the website at: http://lpg.ticalc.org/prj_usb/
- * for more info.
- *
- * History:
- * 1.0x, Romain & Julien: initial submit.
- * 1.03, Greg Kroah: modifications.
- * 1.04, Julien: clean-up & fixes; Romain: 2.4 backport.
- * 1.05, Randy Dunlap: bug fix with the timeout parameter (divide-by-zero).
- * 1.06, Romain: synched with 2.5, version/firmware changed (confusing).
- * 1.07, Romain: fixed bad use of usb_clear_halt (invalid argument);
- * timeout argument checked in ioctl + clean-up.
- * 1.08, Romain: added support of USB port embedded on some TI's handhelds.
- */
-
-#include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <linux/usb.h>
-#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/device.h>
-
-#include <linux/ticable.h>
-#include "tiglusb.h"
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "1.08"
-#define DRIVER_AUTHOR "Romain Lievin <roms@tilp.info> & Julien Blache <jb@jblache.org>"
-#define DRIVER_DESC "TI-GRAPH LINK USB (aka SilverLink) driver"
-#define DRIVER_LICENSE "GPL"
-
-/* ----- global variables --------------------------------------------- */
-
-static tiglusb_t tiglusb[MAXTIGL];
-static int timeout = TIMAXTIME; /* timeout in tenth of seconds */
-static struct class_simple *tiglusb_class;
-
-/*---------- misc functions ------------------------------------------- */
-
-/*
- * Re-initialize device
- */
-static inline int
-clear_device (struct usb_device *dev)
-{
- if (usb_reset_configuration (dev) < 0) {
- err ("clear_device failed");
- return -1;
- }
-
- return 0;
-}
-
-/*
- * Clear input & output pipes (endpoints)
- */
-static inline int
-clear_pipes (struct usb_device *dev)
-{
- unsigned int pipe;
-
- pipe = usb_sndbulkpipe (dev, 2);
- if (usb_clear_halt (dev, pipe)) {
- err ("clear_pipe (w), request failed");
- return -1;
- }
-
- pipe = usb_rcvbulkpipe (dev, 1);
- if (usb_clear_halt (dev, pipe)) {
- err ("clear_pipe (r), request failed");
- return -1;
- }
-
- return 0;
-}
-
-/* ----- file operations functions--------------------------------------- */
-
-static int
-tiglusb_open (struct inode *inode, struct file *filp)
-{
- int devnum = iminor(inode);
- ptiglusb_t s;
-
- if (devnum < TIUSB_MINOR || devnum >= (TIUSB_MINOR + MAXTIGL))
- return -EIO;
-
- s = &tiglusb[devnum - TIUSB_MINOR];
-
- if (down_interruptible (&s->mutex)) {
- return -ERESTARTSYS;
- }
-
- while (!s->dev || s->opened) {
- up (&s->mutex);
-
- if (filp->f_flags & O_NONBLOCK) {
- return -EBUSY;
- }
-
- msleep_interruptible(500);
-
- if (signal_pending (current)) {
- return -EAGAIN;
- }
-
- if (down_interruptible (&s->mutex)) {
- return -ERESTARTSYS;
- }
- }
-
- s->opened = 1;
- up (&s->mutex);
-
- filp->f_pos = 0;
- filp->private_data = s;
-
- return nonseekable_open(inode, filp);
-}
-
-static int
-tiglusb_release (struct inode *inode, struct file *filp)
-{
- ptiglusb_t s = (ptiglusb_t) filp->private_data;
-
- if (down_interruptible (&s->mutex)) {
- return -ERESTARTSYS;
- }
-
- s->state = _stopped;
- up (&s->mutex);
-
- if (!s->remove_pending)
- clear_device (s->dev);
- else
- wake_up (&s->remove_ok);
-
- s->opened = 0;
-
- return 0;
-}
-
-static ssize_t
-tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos)
-{
- ptiglusb_t s = (ptiglusb_t) filp->private_data;
- ssize_t ret = 0;
- int bytes_to_read = 0;
- int bytes_read = 0;
- int result = 0;
- char *buffer;
- unsigned int pipe;
-
- if (*f_pos)
- return -ESPIPE;
-
- if (s->remove_pending)
- return -EIO;
-
- if (!s->dev)
- return -EIO;
-
- buffer = kmalloc (s->max_ps, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- bytes_to_read = (count >= s->max_ps) ? s->max_ps : count;
-
- pipe = usb_rcvbulkpipe (s->dev, 1);
- result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
- &bytes_read, (HZ * timeout) / 10);
- if (result == -ETIMEDOUT) { /* NAK */
- if (!bytes_read)
- dbg ("quirk !");
- warn ("tiglusb_read, NAK received.");
- ret = result;
- goto out;
- } else if (result == -EPIPE) { /* STALL -- shouldn't happen */
- warn ("clear_halt request to remove STALL condition.");
- if (usb_clear_halt (s->dev, pipe))
- err ("clear_halt, request failed");
- clear_device (s->dev);
- ret = result;
- goto out;
- } else if (result < 0) { /* We should not get any I/O errors */
- err ("funky result: %d. Please notify maintainer.", result);
- ret = -EIO;
- goto out;
- }
-
- if (copy_to_user (buf, buffer, bytes_read)) {
- ret = -EFAULT;
- }
-
- out:
- kfree(buffer);
- return ret ? ret : bytes_read;
-}
-
-static ssize_t
-tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t * f_pos)
-{
- ptiglusb_t s = (ptiglusb_t) filp->private_data;
- ssize_t ret = 0;
- int bytes_to_write = 0;
- int bytes_written = 0;
- int result = 0;
- char *buffer;
- unsigned int pipe;
-
- if (*f_pos)
- return -ESPIPE;
-
- if (s->remove_pending)
- return -EIO;
-
- if (!s->dev)
- return -EIO;
-
- buffer = kmalloc (s->max_ps, GFP_KERNEL);
- if (!buffer)
- return -ENOMEM;
-
- bytes_to_write = (count >= s->max_ps) ? s->max_ps : count;
- if (copy_from_user (buffer, buf, bytes_to_write)) {
- ret = -EFAULT;
- goto out;
- }
-
- pipe = usb_sndbulkpipe (s->dev, 2);
- result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_write,
- &bytes_written, (HZ * timeout) / 10);
-
- if (result == -ETIMEDOUT) { /* NAK */
- warn ("tiglusb_write, NAK received.");
- ret = result;
- goto out;
- } else if (result == -EPIPE) { /* STALL -- shouldn't happen */
- warn ("clear_halt request to remove STALL condition.");
- if (usb_clear_halt (s->dev, pipe))
- err ("clear_halt, request failed");
- clear_device (s->dev);
- ret = result;
- goto out;
- } else if (result < 0) { /* We should not get any I/O errors */
- warn ("funky result: %d. Please notify maintainer.", result);
- ret = -EIO;
- goto out;
- }
-
- if (bytes_written != bytes_to_write) {
- ret = -EIO;
- }
-
- out:
- kfree(buffer);
- return ret ? ret : bytes_written;
-}
-
-static int
-tiglusb_ioctl (struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- ptiglusb_t s = (ptiglusb_t) filp->private_data;
- int ret = 0;
-
- if (s->remove_pending)
- return -EIO;
-
- if (down_interruptible (&s->mutex)) {
- return -ERESTARTSYS;
- }
-
- if (!s->dev) {
- up (&s->mutex);
- return -EIO;
- }
-
- switch (cmd) {
- case IOCTL_TIUSB_TIMEOUT:
- if (arg > 0)
- timeout = arg;
- else
- ret = -EINVAL;
- break;
- case IOCTL_TIUSB_RESET_DEVICE:
- if (clear_device (s->dev))
- ret = -EIO;
- break;
- case IOCTL_TIUSB_RESET_PIPES:
- if (clear_pipes (s->dev))
- ret = -EIO;
- break;
- case IOCTL_TIUSB_GET_MAXPS:
- if (copy_to_user((int __user *) arg, &s->max_ps, sizeof(int)))
- return -EFAULT;
- break;
- case IOCTL_TIUSB_GET_DEVID:
- if (copy_to_user((int __user *) arg, &s->dev->descriptor.idProduct,
- sizeof(int)))
- return -EFAULT;
- break;
- default:
- ret = -ENOTTY;
- break;
- }
-
- up (&s->mutex);
-
- return ret;
-}
-
-/* ----- kernel module registering ------------------------------------ */
-
-static struct file_operations tiglusb_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .read = tiglusb_read,
- .write = tiglusb_write,
- .ioctl = tiglusb_ioctl,
- .open = tiglusb_open,
- .release = tiglusb_release,
-};
-
-/* --- initialisation code ------------------------------------- */
-
-static int
-tiglusb_probe (struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *dev = interface_to_usbdev(intf);
- int minor = -1;
- int i, err = 0;
- ptiglusb_t s;
- struct usb_host_config *conf;
- struct usb_host_interface *ifdata = NULL;
- int max_ps;
-
- dbg ("probing vendor id 0x%x, device id 0x%x",
- dev->descriptor.idVendor, dev->descriptor.idProduct);
-
- /*
- * We don't handle multiple configurations. As of version 0x0103 of
- * the TIGL hardware, there's only 1 configuration.
- */
-
- if (dev->descriptor.bNumConfigurations != 1) {
- err = -ENODEV;
- goto out;
- }
-
- if (dev->descriptor.idVendor != 0x451) {
- err = -ENODEV;
- goto out;
- }
-
- if ((dev->descriptor.idProduct != 0xe001) &&
- (dev->descriptor.idProduct != 0xe004) &&
- (dev->descriptor.idProduct != 0xe008)) {
- err = -ENODEV;
- goto out;
- }
-
- /*
- * TI introduced some new handhelds with embedded USB port.
- * Port advertises same config as SilverLink cable but with a
- * different maximum packet size (64 rather than 32).
- */
-
- conf = dev->actconfig;
- ifdata = conf->interface[0]->cur_altsetting;
- max_ps = ifdata->endpoint[0].desc.wMaxPacketSize;
-
- info("max packet size of %d/%d bytes\n",
- ifdata->endpoint[0].desc.wMaxPacketSize,
- ifdata->endpoint[1].desc.wMaxPacketSize);
-
- /*
- * Find a tiglusb struct
- */
- for (i = 0; i < MAXTIGL; i++) {
- ptiglusb_t s = &tiglusb[i];
- if (!s->dev) {
- minor = i;
- break;
- }
- }
-
- if (minor == -1) {
- err = -ENODEV;
- goto out;
- }
-
- s = &tiglusb[minor];
-
- down (&s->mutex);
- s->remove_pending = 0;
- s->dev = dev;
- s->max_ps = max_ps;
- up (&s->mutex);
- dbg ("bound to interface");
-
- class_simple_device_add(tiglusb_class, MKDEV(TIUSB_MAJOR, TIUSB_MINOR + s->minor),
- NULL, "usb%d", s->minor);
- err = devfs_mk_cdev(MKDEV(TIUSB_MAJOR, TIUSB_MINOR) + s->minor,
- S_IFCHR | S_IRUGO | S_IWUGO,
- "ticables/usb/%d", s->minor);
-
- if (err)
- goto out_class;
-
- /* Display firmware version */
- info ("firmware revision %i.%02x",
- dev->descriptor.bcdDevice >> 8,
- dev->descriptor.bcdDevice & 0xff);
-
- usb_set_intfdata (intf, s);
- err = 0;
- goto out;
-
-out_class:
- class_simple_device_remove(MKDEV(TIUSB_MAJOR, TIUSB_MINOR + s->minor));
-out:
- return err;
-}
-
-static void
-tiglusb_disconnect (struct usb_interface *intf)
-{
- wait_queue_t __wait;
- ptiglusb_t s = usb_get_intfdata (intf);
-
- init_waitqueue_entry(&__wait, current);
-
-
- usb_set_intfdata (intf, NULL);
- if (!s || !s->dev) {
- info ("bogus disconnect");
- return;
- }
-
- s->remove_pending = 1;
- wake_up (&s->wait);
- add_wait_queue(&s->wait, &__wait);
- set_current_state(TASK_UNINTERRUPTIBLE);
- if (s->state == _started)
- schedule();
- current->state = TASK_RUNNING;
- remove_wait_queue(&s->wait, &__wait);
- down (&s->mutex);
- s->dev = NULL;
- s->opened = 0;
-
- class_simple_device_remove(MKDEV(TIUSB_MAJOR, TIUSB_MINOR + s->minor));
- devfs_remove("ticables/usb/%d", s->minor);
-
- info ("device %d removed", s->minor);
-
- up (&s->mutex);
-}
-
-static struct usb_device_id tiglusb_ids[] = {
- {USB_DEVICE (0x0451, 0xe001)},
- {}
-};
-
-MODULE_DEVICE_TABLE (usb, tiglusb_ids);
-
-static struct usb_driver tiglusb_driver = {
- .owner = THIS_MODULE,
- .name = "tiglusb",
- .probe = tiglusb_probe,
- .disconnect = tiglusb_disconnect,
- .id_table = tiglusb_ids,
-};
-
-/* --- initialisation code ------------------------------------- */
-
-#ifndef MODULE
-/*
- * You can use 'tiusb=timeout' to set timeout.
- */
-static int __init
-tiglusb_setup (char *str)
-{
- int ints[2];
-
- str = get_options (str, ARRAY_SIZE (ints), ints);
-
- if (ints[0] > 0) {
- if (ints[1] > 0)
- timeout = ints[1];
- else
- info ("tiglusb: wrong timeout value (0), using default value.");
- }
-
- return 1;
-}
-#endif
-
-static int __init
-tiglusb_init (void)
-{
- unsigned u;
- int result, err = 0;
-
- /* initialize struct */
- for (u = 0; u < MAXTIGL; u++) {
- ptiglusb_t s = &tiglusb[u];
- memset (s, 0, sizeof (tiglusb_t));
- init_MUTEX (&s->mutex);
- s->dev = NULL;
- s->minor = u;
- s->opened = 0;
- init_waitqueue_head (&s->wait);
- init_waitqueue_head (&s->remove_ok);
- }
-
- /* register device */
- if (register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) {
- err ("unable to get major %d", TIUSB_MAJOR);
- err = -EIO;
- goto out;
- }
-
- /* Use devfs, tree: /dev/ticables/usb/[0..3] */
- devfs_mk_dir ("ticables/usb");
-
- tiglusb_class = class_simple_create(THIS_MODULE, "tiglusb");
- if (IS_ERR(tiglusb_class)) {
- err = PTR_ERR(tiglusb_class);
- goto out_chrdev;
- }
- /* register USB module */
- result = usb_register (&tiglusb_driver);
- if (result < 0) {
- err = -1;
- goto out_chrdev;
- }
-
- info (DRIVER_DESC ", version " DRIVER_VERSION);
-
- err = 0;
- goto out;
-
-out_chrdev:
- unregister_chrdev (TIUSB_MAJOR, "tiglusb");
-out:
- return err;
-}
-
-static void __exit
-tiglusb_cleanup (void)
-{
- usb_deregister (&tiglusb_driver);
- class_simple_destroy(tiglusb_class);
- devfs_remove("ticables/usb");
- unregister_chrdev (TIUSB_MAJOR, "tiglusb");
-}
-
-/* --------------------------------------------------------------------- */
-
-__setup ("tiusb=", tiglusb_setup);
-module_init (tiglusb_init);
-module_exit (tiglusb_cleanup);
-
-MODULE_AUTHOR (DRIVER_AUTHOR);
-MODULE_DESCRIPTION (DRIVER_DESC);
-MODULE_LICENSE (DRIVER_LICENSE);
-
-module_param(timeout, int, 0);
-MODULE_PARM_DESC (timeout, "Timeout in tenths of seconds (default=1.5 seconds)");
-
-/* --------------------------------------------------------------------- */
diff --git a/drivers/usb/misc/tiglusb.h b/drivers/usb/misc/tiglusb.h
deleted file mode 100644
index 0c90cb2901e925..00000000000000
--- a/drivers/usb/misc/tiglusb.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Hey EMACS -*- linux-c -*-
- *
- * tiglusb - low level driver for SilverLink cable
- *
- * Copyright (C) 2000-2002, Romain Lievin <roms@lpg.ticalc.org>
- * under the terms of the GNU General Public License.
- *
- * Redistribution of this file is permitted under the terms of the GNU
- * Public License (GPL)
- */
-
-#ifndef _TIGLUSB_H
-#define _TIGLUSB_H
-
-/*
- * Max. number of devices supported
- */
-#define MAXTIGL 16
-
-/*
- * The driver context...
- */
-
-typedef enum { _stopped=0, _started } driver_state_t;
-
-typedef struct
-{
- struct usb_device *dev; /* USB device handle */
- struct semaphore mutex; /* locks this struct */
-
- wait_queue_head_t wait; /* for timed waits */
- wait_queue_head_t remove_ok;
-
- int minor; /* which minor dev #? */
-
- driver_state_t state; /* started/stopped */
- int opened; /* tru if open */
- int remove_pending;
-
- int max_ps; /* max packet size */
-} tiglusb_t, *ptiglusb_t;
-
-#endif
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
index 9ff010f1a93bba..da8a43830a822a 100644
--- a/drivers/usb/misc/usblcd.c
+++ b/drivers/usb/misc/usblcd.c
@@ -74,7 +74,7 @@ ioctl_lcd(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
struct lcd_usb_data *lcd = &lcd_instance;
- int i;
+ u16 bcdDevice;
char buf[30];
/* Sanity check to make sure lcd is connected, powered, etc */
@@ -85,9 +85,12 @@ ioctl_lcd(struct inode *inode, struct file *file, unsigned int cmd,
switch (cmd) {
case IOCTL_GET_HARD_VERSION:
- i = (lcd->lcd_dev)->descriptor.bcdDevice;
- sprintf(buf,"%1d%1d.%1d%1d",(i & 0xF000)>>12,(i & 0xF00)>>8,
- (i & 0xF0)>>4,(i & 0xF));
+ bcdDevice = le16_to_cpu((lcd->lcd_dev)->descriptor.bcdDevice);
+ sprintf(buf,"%1d%1d.%1d%1d",
+ (bcdDevice & 0xF000)>>12,
+ (bcdDevice & 0xF00)>>8,
+ (bcdDevice & 0xF0)>>4,
+ (bcdDevice & 0xF));
if (copy_to_user((void __user *)arg,buf,strlen(buf))!=0)
return -EFAULT;
break;
@@ -258,7 +261,7 @@ static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id)
int i;
int retval;
- if (dev->descriptor.idProduct != 0x0001 ) {
+ if (le16_to_cpu(dev->descriptor.idProduct) != 0x0001) {
warn(KERN_INFO "USBLCD model not supported.");
return -ENODEV;
}
@@ -268,7 +271,7 @@ static int probe_lcd(struct usb_interface *intf, const struct usb_device_id *id)
return -ENODEV;
}
- i = dev->descriptor.bcdDevice;
+ i = le16_to_cpu(dev->descriptor.bcdDevice);
info("USBLCD Version %1d%1d.%1d%1d found at address %d",
(i & 0xF000)>>12,(i & 0xF00)>>8,(i & 0xF0)>>4,(i & 0xF),
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index d630edfacad5e4..02bf324f8f5ba3 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -527,10 +527,9 @@ static int is_good_config (char *buf, int len)
return 0;
}
- le16_to_cpus (&config->wTotalLength);
- if (config->wTotalLength == len) /* read it all */
+ if (le16_to_cpu(config->wTotalLength) == len) /* read it all */
return 1;
- if (config->wTotalLength >= TBUF_SIZE) /* max partial read */
+ if (le16_to_cpu(config->wTotalLength) >= TBUF_SIZE) /* max partial read */
return 1;
dbg ("bogus config descriptor read size");
return 0;
@@ -636,7 +635,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
}
/* and sometimes [9.2.6.6] speed dependent descriptors */
- if (udev->descriptor.bcdUSB == 0x0200) { /* pre-swapped */
+ if (le16_to_cpu(udev->descriptor.bcdUSB) == 0x0200) {
struct usb_qualifier_descriptor *d = NULL;
/* device qualifier [9.6.2] */
@@ -954,13 +953,13 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param)
case 13: // short read, resembling case 10
req.wValue = cpu_to_le16 ((USB_DT_CONFIG << 8) | 0);
// last data packet "should" be DATA1, not DATA0
- len = 1024 - udev->epmaxpacketin [0];
+ len = 1024 - udev->descriptor.bMaxPacketSize0;
expected = -EREMOTEIO;
break;
case 14: // short read; try to fill the last packet
req.wValue = cpu_to_le16 ((USB_DT_DEVICE << 8) | 0);
// device descriptor size == 18 bytes
- len = udev->epmaxpacketin [0];
+ len = udev->descriptor.bMaxPacketSize0;
switch (len) {
case 8: len = 24; break;
case 16: len = 32; break;
@@ -1372,8 +1371,8 @@ static struct urb *iso_alloc_urb (
if (bytes < 0 || !desc)
return NULL;
- maxp = 0x7ff & desc->wMaxPacketSize;
- maxp *= 1 + (0x3 & (desc->wMaxPacketSize >> 11));
+ maxp = 0x7ff & le16_to_cpu(desc->wMaxPacketSize);
+ maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11));
packets = (bytes + maxp - 1) / maxp;
urb = usb_alloc_urb (packets, SLAB_KERNEL);
@@ -1433,7 +1432,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param,
"... iso period %d %sframes, wMaxPacket %04x\n",
1 << (desc->bInterval - 1),
(udev->speed == USB_SPEED_HIGH) ? "micro" : "",
- desc->wMaxPacketSize);
+ le16_to_cpu(desc->wMaxPacketSize));
for (i = 0; i < param->sglen; i++) {
urbs [i] = iso_alloc_urb (udev, pipe, desc,
@@ -1842,13 +1841,13 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
/* specify devices by module parameters? */
if (id->match_flags == 0) {
/* vendor match required, product match optional */
- if (!vendor || udev->descriptor.idVendor != (u16)vendor)
+ if (!vendor || le16_to_cpu(udev->descriptor.idVendor) != (u16)vendor)
return -ENODEV;
- if (product && udev->descriptor.idProduct != (u16)product)
+ if (product && le16_to_cpu(udev->descriptor.idProduct) != (u16)product)
return -ENODEV;
dbg ("matched module params, vend=0x%04x prod=0x%04x",
- udev->descriptor.idVendor,
- udev->descriptor.idProduct);
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct));
}
#endif
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 8b22320d5ea65d..de91f8bafe6241 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -544,7 +544,8 @@ static int uss720_probe(struct usb_interface *intf,
int i;
printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n",
- usbdev->descriptor.idVendor, usbdev->descriptor.idProduct);
+ le16_to_cpu(usbdev->descriptor.idVendor),
+ le16_to_cpu(usbdev->descriptor.idProduct));
/* our known interfaces have 3 alternate settings */
if (intf->num_altsetting != 3)
diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
index c825ef78c1119a..af883ae40d6536 100644
--- a/drivers/usb/net/catc.c
+++ b/drivers/usb/net/catc.c
@@ -800,8 +800,9 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
}
/* The F5U011 has the same vendor/product as the netmate but a device version of 0x130 */
- if (usbdev->descriptor.idVendor == 0x0423 && usbdev->descriptor.idProduct == 0xa &&
- catc->usbdev->descriptor.bcdDevice == 0x0130 ) {
+ 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);
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index 1d16b0c572445c..2a83b0c33c2960 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -160,6 +160,7 @@ static struct usb_device_id usb_klsi_table[] = {
{ 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 */
@@ -903,9 +904,9 @@ static int kaweth_probe(
kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x",
dev->devnum,
- (int)dev->descriptor.idVendor,
- (int)dev->descriptor.idProduct,
- (int)dev->descriptor.bcdDevice);
+ le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct),
+ le16_to_cpu(dev->descriptor.bcdDevice));
kaweth_dbg("Device at %p", dev);
@@ -933,7 +934,7 @@ static int kaweth_probe(
* downloaded. Don't try to do it again, or we'll hang the device.
*/
- if (dev->descriptor.bcdDevice >> 8) {
+ if (le16_to_cpu(dev->descriptor.bcdDevice) >> 8) {
kaweth_info("Firmware present in device.");
} else {
/* Download the firmware */
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index 3fe730f76d49e6..25b4944a400d9a 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -202,6 +202,19 @@ config USB_SERIAL_EDGEPORT_TI
To compile this driver as a module, choose M here: the
module will be called io_ti.
+config USB_SERIAL_GARMIN
+ tristate "Garmin GPS driver"
+ depends on USB_SERIAL
+ help
+ Say Y here if you want to connect to your Garmin GPS.
+ Should work with most Garmin GPS devices which have a native USB port.
+
+ See <http://sourceforge.net/projects/garmin-gps> for the latest
+ version of the driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called garmin_gps.
+
config USB_SERIAL_IPW
tristate "USB IPWireless (3G UMTS TDD) Driver (EXPERIMENTAL)"
depends on USB_SERIAL && EXPERIMENTAL
@@ -380,6 +393,16 @@ config USB_SERIAL_SAFE_PADDED
bool "USB Secure Encapsulated Driver - Padded"
depends on USB_SERIAL_SAFE
+config USB_SERIAL_TI
+ tristate "USB TI 3410/5052 Serial Driver"
+ depends on USB_SERIAL
+ help
+ Say Y here if you want to use the TI USB 3410 or 5052
+ serial devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ti_usb_3410_5052.
+
config USB_SERIAL_CYBERJACK
tristate "USB REINER SCT cyberJack pinpad/e-com chipcard reader (EXPERIMENTAL)"
depends on USB_SERIAL && EXPERIMENTAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index 682ac09b8cd9fe..1432b18125a65e 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o
obj-$(CONFIG_USB_SERIAL_FTDI_SIO) += ftdi_sio.o
+obj-$(CONFIG_USB_SERIAL_GARMIN) += garmin_gps.o
obj-$(CONFIG_USB_SERIAL_IPAQ) += ipaq.o
obj-$(CONFIG_USB_SERIAL_IPW) += ipw.o
obj-$(CONFIG_USB_SERIAL_IR) += ir-usb.o
@@ -30,6 +31,7 @@ obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
+obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o
obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o
obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
index 75dd41d98f86e8..a16502e474fe38 100644
--- a/drivers/usb/serial/belkin_sa.c
+++ b/drivers/usb/serial/belkin_sa.c
@@ -181,8 +181,8 @@ static int belkin_sa_startup (struct usb_serial *serial)
priv->last_lsr = 0;
priv->last_msr = 0;
/* see comments at top of file */
- priv->bad_flow_control = (dev->descriptor.bcdDevice <= 0x0206) ? 1 : 0;
- info("bcdDevice: %04x, bfc: %d", dev->descriptor.bcdDevice, priv->bad_flow_control);
+ priv->bad_flow_control = (le16_to_cpu(dev->descriptor.bcdDevice) <= 0x0206) ? 1 : 0;
+ info("bcdDevice: %04x, bfc: %d", le16_to_cpu(dev->descriptor.bcdDevice), priv->bad_flow_control);
init_waitqueue_head(&serial->port[0]->write_wait);
usb_set_serial_port_data(serial->port[0], priv);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 884879c9985642..4f824d2191f741 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1174,6 +1174,135 @@ check_and_exit:
} /* set_serial_info */
+
+/*
+ * ***************************************************************************
+ * Sysfs Attribute
+ * ***************************************************************************
+ */
+
+ssize_t show_latency_timer(struct device *dev, char *buf)
+{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ struct usb_device *udev;
+ unsigned short latency = 0;
+ int rv = 0;
+
+ udev = to_usb_device(dev);
+
+ dbg("%s",__FUNCTION__);
+
+ rv = usb_control_msg(udev,
+ usb_rcvctrlpipe(udev, 0),
+ FTDI_SIO_GET_LATENCY_TIMER_REQUEST,
+ FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE,
+ 0, priv->interface,
+ (char*) &latency, 1, WDR_TIMEOUT);
+
+ if (rv < 0) {
+ dev_err(dev, "Unable to read latency timer: %i", rv);
+ return -EIO;
+ }
+ return sprintf(buf, "%i\n", latency);
+}
+
+/* Write a new value of the latency timer, in units of milliseconds. */
+ssize_t store_latency_timer(struct device *dev, const char *valbuf, size_t count)
+{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ struct usb_device *udev;
+ char buf[1];
+ int v = simple_strtoul(valbuf, NULL, 10);
+ int rv = 0;
+
+ udev = to_usb_device(dev);
+
+ dbg("%s: setting latency timer = %i", __FUNCTION__, v);
+
+ rv = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
+ FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
+ v, priv->interface,
+ buf, 0, WDR_TIMEOUT);
+
+ if (rv < 0) {
+ dev_err(dev, "Unable to write latency timer: %i", rv);
+ return -EIO;
+ }
+
+ return count;
+}
+
+/* Write an event character directly to the FTDI register. The ASCII
+ value is in the low 8 bits, with the enable bit in the 9th bit. */
+ssize_t store_event_char(struct device *dev, const char *valbuf, size_t count)
+{
+ struct usb_serial_port *port = to_usb_serial_port(dev);
+ struct ftdi_private *priv = usb_get_serial_port_data(port);
+ struct usb_device *udev;
+ char buf[1];
+ int v = simple_strtoul(valbuf, NULL, 10);
+ int rv = 0;
+
+ udev = to_usb_device(dev);
+
+ dbg("%s: setting event char = %i", __FUNCTION__, v);
+
+ rv = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ FTDI_SIO_SET_EVENT_CHAR_REQUEST,
+ FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE,
+ v, priv->interface,
+ buf, 0, WDR_TIMEOUT);
+
+ if (rv < 0) {
+ dbg("Unable to write event character: %i", rv);
+ return -EIO;
+ }
+
+ return count;
+}
+
+static DEVICE_ATTR(latency_timer, S_IWUGO | S_IRUGO, show_latency_timer, store_latency_timer);
+static DEVICE_ATTR(event_char, S_IWUGO, NULL, store_event_char);
+
+void create_sysfs_attrs(struct usb_serial *serial)
+{
+ struct ftdi_private *priv;
+ struct usb_device *udev;
+
+ dbg("%s",__FUNCTION__);
+
+ priv = usb_get_serial_port_data(serial->port[0]);
+ udev = serial->dev;
+
+ if (priv->chip_type == FT232BM) {
+ dbg("sysfs attributes for FT232BM");
+ device_create_file(&udev->dev, &dev_attr_event_char);
+ device_create_file(&udev->dev, &dev_attr_latency_timer);
+ }
+}
+
+void remove_sysfs_attrs(struct usb_serial *serial)
+{
+ struct ftdi_private *priv;
+ struct usb_device *udev;
+
+ dbg("%s",__FUNCTION__);
+
+ priv = usb_get_serial_port_data(serial->port[0]);
+ udev = serial->dev;
+
+ if (priv->chip_type == FT232BM) {
+ device_remove_file(&udev->dev, &dev_attr_event_char);
+ device_remove_file(&udev->dev, &dev_attr_latency_timer);
+ }
+
+}
+
/*
* ***************************************************************************
* FTDI driver specific functions
@@ -1291,6 +1420,8 @@ static int ftdi_FT232BM_startup (struct usb_serial *serial)
priv->chip_type = FT232BM;
priv->baud_base = 48000000 / 2; /* Would be / 16, but FT232BM supports multiple of 0.125 divisor fractions! */
+ create_sysfs_attrs(serial);
+
return (0);
} /* ftdi_FT232BM_startup */
@@ -1384,6 +1515,8 @@ static void ftdi_shutdown (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
+ remove_sysfs_attrs(serial);
+
/* all open ports are closed at this point
* (by usbserial.c:__serial_close, which calls ftdi_close)
*/
@@ -1518,7 +1651,7 @@ static int ftdi_write (struct usb_serial_port *port,
dbg("%s port %d, %d bytes", __FUNCTION__, port->number, count);
if (count == 0) {
- err("write request of 0 bytes");
+ dbg("write request of 0 bytes");
return 0;
}
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index e7a7e0aba4f26f..7f190ac2f977f7 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -249,6 +249,8 @@
#define FTDI_SIO_GET_MODEM_STATUS 5 /* Retrieve current value of modern status register */
#define FTDI_SIO_SET_EVENT_CHAR 6 /* Set the event character */
#define FTDI_SIO_SET_ERROR_CHAR 7 /* Set the error character */
+#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */
+#define FTDI_SIO_GET_LATENCY_TIMER 10 /* Get the latency timer */
/* Port interface code for FT2232C */
#define INTERFACE_A 1
@@ -503,6 +505,55 @@ typedef enum {
*/
/*
+ * FTDI_SIO_GET_LATENCY_TIMER
+ *
+ * Set the timeout interval. The FTDI collects data from the slave
+ * device, transmitting it to the host when either A) 62 bytes are
+ * received, or B) the timeout interval has elapsed and the buffer
+ * contains at least 1 byte. Setting this value to a small number
+ * can dramatically improve performance for applications which send
+ * small packets, since the default value is 16ms.
+ */
+#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST FTDI_SIO_GET_LATENCY_TIMER
+#define FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE 0xC0
+
+/*
+ * BmRequestType: 1100 0000b
+ * bRequest: FTDI_SIO_GET_LATENCY_TIMER
+ * wValue: 0
+ * wIndex: Port
+ * wLength: 0
+ * Data: latency (on return)
+ */
+
+/*
+ * FTDI_SIO_SET_LATENCY_TIMER
+ *
+ * Set the timeout interval. The FTDI collects data from the slave
+ * device, transmitting it to the host when either A) 62 bytes are
+ * received, or B) the timeout interval has elapsed and the buffer
+ * contains at least 1 byte. Setting this value to a small number
+ * can dramatically improve performance for applications which send
+ * small packets, since the default value is 16ms.
+ */
+#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER
+#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40
+
+/*
+ * BmRequestType: 0100 0000b
+ * bRequest: FTDI_SIO_SET_LATENCY_TIMER
+ * wValue: Latency (milliseconds)
+ * wIndex: Port
+ * wLength: 0
+ * Data: None
+ *
+ * wValue:
+ * B0..7 Latency timer
+ * B8..15 0
+ *
+ */
+
+/*
* FTDI_SIO_SET_EVENT_CHAR
*
* Set the special event character for the specified communications port.
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
new file mode 100644
index 00000000000000..0c6c980bfd7ec1
--- /dev/null
+++ b/drivers/usb/serial/garmin_gps.c
@@ -0,0 +1,1541 @@
+/*
+ * Garmin GPS driver
+ *
+ * Copyright (C) 2004 Hermann Kneissel hkneissel@t-online.de
+ *
+ * The latest version of the driver can be found at
+ * http://sourceforge.net/projects/garmin-gps/
+ *
+ * This driver has been derived from v2.1 of the visor driver.
+ *
+ * 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 USA
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/uaccess.h>
+#include <linux/usb.h>
+
+/* the mode to be set when the port ist opened */
+static int initial_mode = 1;
+
+/* debug flag */
+static int debug = 0;
+
+#include "usb-serial.h"
+
+#define GARMIN_VENDOR_ID 0x091E
+
+/*
+ * Version Information
+ */
+
+#define VERSION_MAJOR 0
+#define VERSION_MINOR 23
+
+#define _STR(s) #s
+#define _DRIVER_VERSION(a,b) "v" _STR(a) "." _STR(b)
+#define DRIVER_VERSION _DRIVER_VERSION(VERSION_MAJOR, VERSION_MINOR)
+#define DRIVER_AUTHOR "hermann kneissel"
+#define DRIVER_DESC "garmin gps driver"
+
+/* error codes returned by the driver */
+#define EINVPKT 1000 /* invalid packet structure */
+
+
+// size of the header of a packet using the usb protocol
+#define GARMIN_PKTHDR_LENGTH 12
+
+// max. possible size of a packet using the serial protocol
+#define MAX_SERIAL_PKT_SIZ (3+255+3)
+
+// max. possible size of a packet with worst case stuffing
+#define MAX_SERIAL_PKT_SIZ_STUFFED MAX_SERIAL_PKT_SIZ+256
+
+// size of a buffer able to hold a complete (no stuffing) packet
+// (the document protocol does not contain packets with a larger
+// size, but in theory a packet may be 64k+12 bytes - if in
+// later protocol versions larger packet sizes occur, this value
+// should be increased accordingly, so the input buffer is always
+// large enough the store a complete packet inclusive header)
+#define GPS_IN_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ)
+
+// size of a buffer able to hold a complete (incl. stuffing) packet
+#define GPS_OUT_BUFSIZ (GARMIN_PKTHDR_LENGTH+MAX_SERIAL_PKT_SIZ_STUFFED)
+
+// where to place the packet id of a serial packet, so we can
+// prepend the usb-packet header without the need to move the
+// packets data
+#define GSP_INITIAL_OFFSET (GARMIN_PKTHDR_LENGTH-2)
+
+// max. size of incoming private packets (header+1 param)
+#define PRIVPKTSIZ (GARMIN_PKTHDR_LENGTH+4)
+
+#define GARMIN_LAYERID_TRANSPORT 0
+#define GARMIN_LAYERID_APPL 20
+// our own layer-id to use for some control mechanisms
+#define GARMIN_LAYERID_PRIVATE 0x01106E4B
+
+#define GARMIN_PKTID_PVT_DATA 51
+#define GARMIN_PKTID_L001_COMMAND_DATA 10
+
+#define CMND_ABORT_TRANSFER 0
+
+// packet ids used in private layer
+#define PRIV_PKTID_SET_DEBUG 1
+#define PRIV_PKTID_SET_MODE 2
+#define PRIV_PKTID_INFO_REQ 3
+#define PRIV_PKTID_INFO_RESP 4
+#define PRIV_PKTID_RESET_REQ 5
+#define PRIV_PKTID_SET_DEF_MODE 6
+
+
+#define ETX 0x03
+#define DLE 0x10
+#define ACK 0x06
+#define NAK 0x15
+
+/* structure used to queue incoming packets */
+struct garmin_packet {
+ struct list_head list;
+ int seq;
+ int size; // the real size of the data array, always > 0
+ __u8 data[1];
+};
+
+/* structure used to keep the current state of the driver */
+struct garmin_data {
+ __u8 state;
+ __u16 flags;
+ __u8 mode;
+ __u8 ignorePkts;
+ __u8 count;
+ __u8 pkt_id;
+ __u32 serial_num;
+ struct timer_list timer;
+ struct usb_serial_port *port;
+ int seq_counter;
+ int insize;
+ int outsize;
+ __u8 inbuffer [GPS_IN_BUFSIZ]; /* tty -> usb */
+ __u8 outbuffer[GPS_OUT_BUFSIZ]; /* usb -> tty */
+ __u8 privpkt[4*6];
+ spinlock_t lock;
+ struct list_head pktlist;
+};
+
+
+#define STATE_NEW 0
+#define STATE_INITIAL_DELAY 1
+#define STATE_TIMEOUT 2
+#define STATE_SESSION_REQ1 3
+#define STATE_SESSION_REQ2 4
+#define STATE_ACTIVE 5
+
+#define STATE_RESET 8
+#define STATE_DISCONNECTED 9
+#define STATE_WAIT_TTY_ACK 10
+#define STATE_GSP_WAIT_DATA 11
+
+#define MODE_NATIVE 0
+#define MODE_GARMIN_SERIAL 1
+
+// Flags used in garmin_data.flags:
+#define FLAGS_SESSION_REPLY_MASK 0x00C0
+#define FLAGS_SESSION_REPLY1_SEEN 0x0080
+#define FLAGS_SESSION_REPLY2_SEEN 0x0040
+#define FLAGS_BULK_IN_ACTIVE 0x0020
+#define FLAGS_THROTTLED 0x0010
+#define CLEAR_HALT_REQUIRED 0x0001
+
+#define FLAGS_QUEUING 0x0100
+#define FLAGS_APP_RESP_SEEN 0x0200
+#define FLAGS_APP_REQ_SEEN 0x0400
+#define FLAGS_DROP_DATA 0x0800
+
+#define FLAGS_GSP_SKIP 0x1000
+#define FLAGS_GSP_DLESEEN 0x2000
+
+
+
+
+
+
+/* function prototypes */
+static void gsp_next_packet(struct garmin_data * garmin_data_p);
+static int garmin_write_bulk(struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+
+/* some special packets to be send or received */
+static unsigned char const GARMIN_START_SESSION_REQ[]
+ = { 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char const GARMIN_START_SESSION_REQ2[]
+ = { 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char const GARMIN_START_SESSION_REPLY[]
+ = { 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0 };
+static unsigned char const GARMIN_SESSION_ACTIVE_REPLY[]
+ = { 0, 0, 0, 0, 17, 0, 0, 0, 4, 0, 0, 0, 0, 16, 0, 0 };
+static unsigned char const GARMIN_BULK_IN_AVAIL_REPLY[]
+ = { 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char const GARMIN_APP_LAYER_REPLY[]
+ = { 0x14, 0, 0, 0 };
+static unsigned char const GARMIN_START_PVT_REQ[]
+ = { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 49, 0 };
+static unsigned char const GARMIN_STOP_PVT_REQ[]
+ = { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 50, 0 };
+static unsigned char const GARMIN_STOP_TRANSFER_REQ[]
+ = { 20, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0 };
+static unsigned char const GARMIN_STOP_TRANSFER_REQ_V2[]
+ = { 20, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0 };
+static unsigned char const PRIVATE_REQ[]
+ = { 0x4B, 0x6E, 0x10, 0x01, 0xFF, 0, 0, 0, 0xFF, 0, 0, 0 };
+
+
+
+static struct usb_device_id id_table [] = {
+ /* the same device id seems to be used by all usb enabled gps devices */
+ { USB_DEVICE(GARMIN_VENDOR_ID, 3 ) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table);
+
+static struct usb_driver garmin_driver = {
+ .owner = THIS_MODULE,
+ .name = "garmin_gps",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = id_table,
+};
+
+
+static inline int noResponseFromAppLayer(struct garmin_data * garmin_data_p)
+{
+ return ((garmin_data_p->flags
+ & (FLAGS_APP_REQ_SEEN|FLAGS_APP_RESP_SEEN))
+ == FLAGS_APP_REQ_SEEN);
+}
+
+
+static inline int getLayerId(const __u8 *usbPacket)
+{
+ return __le32_to_cpup((__le32 *)(usbPacket));
+}
+
+static inline int getPacketId(const __u8 *usbPacket)
+{
+ return __le32_to_cpup((__le32 *)(usbPacket+4));
+}
+
+static inline int getDataLength(const __u8 *usbPacket)
+{
+ return __le32_to_cpup((__le32 *)(usbPacket+8));
+}
+
+
+/*
+ * check if the usb-packet in buf contains an abort-transfer command.
+ * (if yes, all queued data will be dropped)
+ */
+static inline int isAbortTrfCmnd(const unsigned char *buf)
+{
+ if (0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ,
+ sizeof(GARMIN_STOP_TRANSFER_REQ)) ||
+ 0 == memcmp(buf, GARMIN_STOP_TRANSFER_REQ_V2,
+ sizeof(GARMIN_STOP_TRANSFER_REQ_V2)))
+ return 1;
+ else
+ return 0;
+}
+
+
+
+static void send_to_tty(struct usb_serial_port *port,
+ char *data, unsigned int actual_length)
+{
+ struct tty_struct *tty = port->tty;
+ int i;
+
+ if (tty && actual_length) {
+
+ usb_serial_debug_data(debug, &port->dev,
+ __FUNCTION__, actual_length, data);
+
+ for (i = 0; i < actual_length ; ++i) {
+ /* if we insert more than TTY_FLIPBUF_SIZE characters,
+ we drop them. */
+ if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ }
+ /* this doesn't actually push the data through unless
+ tty->low_latency is set */
+ tty_insert_flip_char(tty, data[i], 0);
+ }
+ tty_flip_buffer_push(tty);
+ }
+}
+
+
+/******************************************************************************
+ * packet queue handling
+ ******************************************************************************/
+
+/*
+ * queue a received (usb-)packet for later processing
+ */
+static int pkt_add(struct garmin_data * garmin_data_p,
+ unsigned char *data, unsigned int data_length)
+{
+ int result = 0;
+ unsigned long flags;
+ struct garmin_packet *pkt;
+
+ /* process only packets containg data ... */
+ if (data_length) {
+ garmin_data_p->flags |= FLAGS_QUEUING;
+ pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
+ GFP_ATOMIC);
+ if (pkt == 0) {
+ dev_err(&garmin_data_p->port->dev, "out of memory\n");
+ return 0;
+ }
+ pkt->size = data_length;
+ memcpy(pkt->data, data, data_length);
+
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ result = list_empty(&garmin_data_p->pktlist);
+ pkt->seq = garmin_data_p->seq_counter++;
+ list_add_tail(&pkt->list, &garmin_data_p->pktlist);
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
+ /* in serial mode, if someone is waiting for data from
+ the device, iconvert and send the next packet to tty. */
+ if (result && (garmin_data_p->state == STATE_GSP_WAIT_DATA)) {
+ gsp_next_packet(garmin_data_p);
+ }
+ }
+ return result;
+}
+
+
+/* get the next pending packet */
+static struct garmin_packet *pkt_pop(struct garmin_data * garmin_data_p)
+{
+ unsigned long flags;
+ struct garmin_packet *result = NULL;
+
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ if (!list_empty(&garmin_data_p->pktlist)) {
+ result = (struct garmin_packet *)garmin_data_p->pktlist.next;
+ list_del(&result->list);
+ }
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ return result;
+}
+
+
+/* free up all queued data */
+static void pkt_clear(struct garmin_data * garmin_data_p)
+{
+ unsigned long flags;
+ struct garmin_packet *result = NULL;
+
+ dbg("%s", __FUNCTION__);
+
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ while (!list_empty(&garmin_data_p->pktlist)) {
+ result = (struct garmin_packet *)garmin_data_p->pktlist.next;
+ list_del(&result->list);
+ kfree(result);
+ }
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+}
+
+
+/******************************************************************************
+ * garmin serial protocol handling handling
+ ******************************************************************************/
+
+/* send an ack packet back to the tty */
+static int gsp_send_ack(struct garmin_data * garmin_data_p, __u8 pkt_id)
+{
+ __u8 pkt[10];
+ __u8 cksum = 0;
+ __u8 *ptr = pkt;
+ unsigned l = 0;
+
+ dbg("%s - pkt-id: 0x%X.", __FUNCTION__, 0xFF & pkt_id);
+
+ *ptr++ = DLE;
+ *ptr++ = ACK;
+ cksum += ACK;
+
+ *ptr++ = 2;
+ cksum += 2;
+
+ *ptr++ = pkt_id;
+ cksum += pkt_id;
+
+ if (pkt_id == DLE) {
+ *ptr++ = DLE;
+ }
+
+ *ptr++ = 0;
+ *ptr++ = 0xFF & (-cksum);
+ *ptr++ = DLE;
+ *ptr++ = ETX;
+
+ l = ptr-pkt;
+
+ send_to_tty(garmin_data_p->port, pkt, l);
+ return 0;
+}
+
+
+
+/*
+ * called for a complete packet received from tty layer
+ *
+ * the complete packet (pkzid ... cksum) is in garmin_data_p->inbuf starting
+ * at GSP_INITIAL_OFFSET.
+ *
+ * count - number of bytes in the input buffer including space reserved for
+ * the usb header: GSP_INITIAL_OFFSET + number of bytes in packet
+ * (including pkt-id, data-length a. cksum)
+ */
+static int gsp_rec_packet(struct garmin_data * garmin_data_p, int count)
+{
+ const __u8* recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
+ __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
+
+ int cksum = 0;
+ int n = 0;
+ int pktid = recpkt[0];
+ int size = recpkt[1];
+
+ usb_serial_debug_data(debug, &garmin_data_p->port->dev,
+ __FUNCTION__, count-GSP_INITIAL_OFFSET, recpkt);
+
+ if (size != (count-GSP_INITIAL_OFFSET-3)) {
+ dbg("%s - invalid size, expected %d bytes, got %d",
+ __FUNCTION__, size, (count-GSP_INITIAL_OFFSET-3));
+ return -EINVPKT;
+ }
+
+ cksum += *recpkt++;
+ cksum += *recpkt++;
+
+ // sanity check, remove after test ...
+ if ((__u8*)&(usbdata[3]) != recpkt) {
+ dbg("%s - ptr mismatch %p - %p",
+ __FUNCTION__, &(usbdata[4]), recpkt);
+ return -EINVPKT;
+ }
+
+ while (n < size) {
+ cksum += *recpkt++;
+ n++;
+ }
+
+ if ((0xff & (cksum + *recpkt)) != 0) {
+ dbg("%s - invalid checksum, expected %02x, got %02x",
+ __FUNCTION__, 0xff & -cksum, 0xff & *recpkt);
+ return -EINVPKT;
+ }
+
+ usbdata[0] = __cpu_to_le32(GARMIN_LAYERID_APPL);
+ usbdata[1] = __cpu_to_le32(pktid);
+ usbdata[2] = __cpu_to_le32(size);
+
+ garmin_write_bulk (garmin_data_p->port, garmin_data_p->inbuffer,
+ GARMIN_PKTHDR_LENGTH+size);
+
+ /* if this was an abort-transfer command, flush all
+ queued data. */
+ if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
+ garmin_data_p->flags |= FLAGS_DROP_DATA;
+ pkt_clear(garmin_data_p);
+ }
+
+ return count;
+}
+
+
+
+/*
+ * Called for data received from tty
+ *
+ * buf contains the data read, it may span more than one packet or even
+ * incomplete packets
+ *
+ * input record should be a serial-record, but it may not be complete.
+ * Copy it into our local buffer, until an etx is seen (or an error
+ * occurs).
+ * Once the record is complete, convert into a usb packet and send it
+ * to the bulk pipe, send an ack back to the tty.
+ *
+ * If the input is an ack, just send the last queued packet to the
+ * tty layer.
+ *
+ * if the input is an abort command, drop all queued data.
+ */
+
+static int gsp_receive(struct garmin_data * garmin_data_p,
+ const unsigned char *buf, int count)
+{
+ int offs = 0;
+ int ack_or_nak_seen = 0;
+ int i = 0;
+ __u8 *dest = garmin_data_p->inbuffer;
+ int size = garmin_data_p->insize;
+ // dleSeen: set if last byte read was a DLE
+ int dleSeen = garmin_data_p->flags & FLAGS_GSP_DLESEEN;
+ // skip: if set, skip incoming data until possible start of
+ // new packet
+ int skip = garmin_data_p->flags & FLAGS_GSP_SKIP;
+ __u8 data;
+
+ dbg("%s - dle=%d skip=%d size=%d count=%d",
+ __FUNCTION__, dleSeen, skip, size, count);
+
+ if (size == 0) {
+ size = GSP_INITIAL_OFFSET;
+ }
+
+ while (offs < count) {
+
+ data = *(buf+offs);
+ offs ++;
+
+ if (data == DLE) {
+ if (skip) { /* start of a new pkt */
+ skip = 0;
+ size = GSP_INITIAL_OFFSET;
+ dleSeen = 1;
+ } else if (dleSeen) {
+ dest[size++] = data;
+ dleSeen = 0;
+ } else {
+ dleSeen = 1;
+ }
+ } else if (data == ETX) {
+ if (dleSeen) {
+ /* packet complete */
+
+ data = dest[GSP_INITIAL_OFFSET];
+
+ if (data == ACK) {
+ ack_or_nak_seen = ACK;
+ dbg("ACK packet complete.");
+ } else if (data == NAK) {
+ ack_or_nak_seen = NAK;
+ dbg("NAK packet complete.");
+ } else {
+ dbg("packet complete "
+ "- id=0x%X.",
+ 0xFF & data);
+ gsp_rec_packet(garmin_data_p, size);
+ }
+
+ skip = 1;
+ size = GSP_INITIAL_OFFSET;
+ dleSeen = 0;
+ } else {
+ dest[size++] = data;
+ }
+ } else if (!skip) {
+
+ if (dleSeen) {
+ dbg("non-masked DLE at %d - restarting", i);
+ size = GSP_INITIAL_OFFSET;
+ dleSeen = 0;
+ }
+
+ dest[size++] = data;
+ }
+
+ if (size >= GPS_IN_BUFSIZ) {
+ dbg("%s - packet too large.", __FUNCTION__);
+ skip = 1;
+ size = GSP_INITIAL_OFFSET;
+ dleSeen = 0;
+ }
+ }
+
+ garmin_data_p->insize = size;
+
+ // copy flags back to structure
+ if (skip)
+ garmin_data_p->flags |= FLAGS_GSP_SKIP;
+ else
+ garmin_data_p->flags &= ~FLAGS_GSP_SKIP;
+
+ if (dleSeen)
+ garmin_data_p->flags |= FLAGS_GSP_DLESEEN;
+ else
+ garmin_data_p->flags &= ~FLAGS_GSP_DLESEEN;
+
+ if (ack_or_nak_seen) {
+ garmin_data_p->state = STATE_GSP_WAIT_DATA;
+ gsp_next_packet(garmin_data_p);
+ }
+
+ return count;
+}
+
+
+
+
+/*
+ * Sends a usb packet to the tty
+ *
+ * Assumes, that all packages and at an usb-packet boundary.
+ *
+ * return <0 on error, 0 if packet is incomplete or > 0 if packet was sent
+ */
+int gsp_send(struct garmin_data * garmin_data_p, const unsigned char *buf,
+ int count)
+{
+ const unsigned char *src;
+ unsigned char *dst;
+ int pktid = 0;
+ int datalen = 0;
+ int cksum = 0;
+ int i=0;
+ int k;
+
+ dbg("%s - state %d - %d bytes.", __FUNCTION__,
+ garmin_data_p->state, count);
+
+ k = garmin_data_p->outsize;
+ if ((k+count) > GPS_OUT_BUFSIZ) {
+ dbg("packet too large");
+ garmin_data_p->outsize = 0;
+ return -4;
+ }
+
+ memcpy(garmin_data_p->outbuffer+k, buf, count);
+ k += count;
+ garmin_data_p->outsize = k;
+
+ if (k >= GARMIN_PKTHDR_LENGTH) {
+ pktid = getPacketId(garmin_data_p->outbuffer);
+ datalen= getDataLength(garmin_data_p->outbuffer);
+ i = GARMIN_PKTHDR_LENGTH + datalen;
+ if (k < i)
+ return 0;
+ } else {
+ return 0;
+ }
+
+ dbg("%s - %d bytes in buffer, %d bytes in pkt.", __FUNCTION__,
+ k, i);
+
+ /* garmin_data_p->outbuffer now contains a complete packet */
+
+ usb_serial_debug_data(debug, &garmin_data_p->port->dev,
+ __FUNCTION__, k, garmin_data_p->outbuffer);
+
+ garmin_data_p->outsize = 0;
+
+ if (GARMIN_LAYERID_APPL != getLayerId(garmin_data_p->outbuffer)) {
+ dbg("not an application packet (%d)",
+ getLayerId(garmin_data_p->outbuffer));
+ return -1;
+ }
+
+ if (pktid > 255) {
+ dbg("packet-id %d too large", pktid);
+ return -2;
+ }
+
+ if (datalen > 255) {
+ dbg("packet-size %d too large", datalen);
+ return -3;
+ }
+
+ /* the serial protocol should be able to handle this packet */
+
+ k = 0;
+ src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
+ for (i=0; i<datalen; i++) {
+ if (*src++ == DLE)
+ k++;
+ }
+
+ src = garmin_data_p->outbuffer+GARMIN_PKTHDR_LENGTH;
+ if (k > (GARMIN_PKTHDR_LENGTH-2)) {
+ /* can't add stuffing DLEs in place, move data to end
+ of buffer ... */
+ dst = garmin_data_p->outbuffer+GPS_OUT_BUFSIZ-datalen;
+ memcpy(dst, src, datalen);
+ src = dst;
+ }
+
+ dst = garmin_data_p->outbuffer;
+
+ *dst++ = DLE;
+ *dst++ = pktid;
+ cksum += pktid;
+ *dst++ = datalen;
+ cksum += datalen;
+ if (datalen == DLE)
+ *dst++ = DLE;
+
+ for (i=0; i<datalen; i++) {
+ __u8 c = *src++;
+ *dst++ = c;
+ cksum += c;
+ if (c == DLE)
+ *dst++ = DLE;
+ }
+
+ cksum = 0xFF & -cksum;
+ *dst++ = cksum;
+ if (cksum == DLE)
+ *dst++ = DLE;
+ *dst++ = DLE;
+ *dst++ = ETX;
+
+ i = dst-garmin_data_p->outbuffer;
+
+ send_to_tty(garmin_data_p->port, garmin_data_p->outbuffer, i);
+
+ garmin_data_p->pkt_id = pktid;
+ garmin_data_p->state = STATE_WAIT_TTY_ACK;
+
+ return i;
+}
+
+
+
+
+
+/*
+ * Process the next pending data packet - if there is one
+ */
+static void gsp_next_packet(struct garmin_data * garmin_data_p)
+{
+ struct garmin_packet *pkt = NULL;
+
+ while ((pkt = pkt_pop(garmin_data_p)) != 0) {
+ dbg("%s - next pkt: %d", __FUNCTION__, pkt->seq);
+ if (gsp_send(garmin_data_p, pkt->data, pkt->size) > 0) {
+ kfree(pkt);
+ return;
+ }
+ kfree(pkt);
+ }
+}
+
+
+
+
+/******************************************************************************
+ * garmin native mode
+ ******************************************************************************/
+
+
+/*
+ * Called for data received from tty
+ *
+ * The input data is expected to be in garmin usb-packet format.
+ *
+ * buf contains the data read, it may span more than one packet
+ * or even incomplete packets
+ */
+static int nat_receive(struct garmin_data * garmin_data_p,
+ const unsigned char *buf, int count)
+{
+ __u8 * dest;
+ int offs = 0;
+ int result = count;
+ int len;
+
+ while (offs < count) {
+ // if buffer contains header, copy rest of data
+ if (garmin_data_p->insize >= GARMIN_PKTHDR_LENGTH)
+ len = GARMIN_PKTHDR_LENGTH
+ +getDataLength(garmin_data_p->inbuffer);
+ else
+ len = GARMIN_PKTHDR_LENGTH;
+
+ if (len >= GPS_IN_BUFSIZ) {
+ /* seem to be an invalid packet, ignore rest of input */
+ dbg("%s - packet size too large: %d",
+ __FUNCTION__, len);
+ garmin_data_p->insize = 0;
+ count = 0;
+ result = -EINVPKT;
+ } else {
+ len -= garmin_data_p->insize;
+ if (len > (count-offs))
+ len = (count-offs);
+ if (len > 0) {
+ dest = garmin_data_p->inbuffer
+ +garmin_data_p->insize;
+ memcpy(dest, buf+offs, len);
+ garmin_data_p->insize += len;
+ offs += len;
+ }
+ }
+
+ /* do we have a complete packet ? */
+ if (garmin_data_p->insize >= GARMIN_PKTHDR_LENGTH) {
+ len = GARMIN_PKTHDR_LENGTH+
+ getDataLength(garmin_data_p->inbuffer);
+ if (garmin_data_p->insize >= len) {
+ garmin_write_bulk (garmin_data_p->port,
+ garmin_data_p->inbuffer,
+ len);
+ garmin_data_p->insize = 0;
+
+ /* if this was an abort-transfer command,
+ flush all queued data. */
+ if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
+ garmin_data_p->flags |= FLAGS_DROP_DATA;
+ pkt_clear(garmin_data_p);
+ }
+ }
+ }
+ }
+ return result;
+}
+
+
+/******************************************************************************
+ * private packets
+ ******************************************************************************/
+
+static void priv_status_resp(struct usb_serial_port *port)
+{
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ __le32 *pkt = (__le32 *)garmin_data_p->privpkt;
+
+ pkt[0] = __cpu_to_le32(GARMIN_LAYERID_PRIVATE);
+ pkt[1] = __cpu_to_le32(PRIV_PKTID_INFO_RESP);
+ pkt[2] = __cpu_to_le32(12);
+ pkt[3] = __cpu_to_le32(VERSION_MAJOR << 16 | VERSION_MINOR);
+ pkt[4] = __cpu_to_le32(garmin_data_p->mode);
+ pkt[5] = __cpu_to_le32(garmin_data_p->serial_num);
+
+ send_to_tty(port, (__u8*)pkt, 6*4);
+}
+
+
+/******************************************************************************
+ * Garmin specific driver functions
+ ******************************************************************************/
+
+static int process_resetdev_request(struct usb_serial_port *port)
+{
+ int status;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+ garmin_data_p->flags &= ~(CLEAR_HALT_REQUIRED);
+ garmin_data_p->state = STATE_RESET;
+ garmin_data_p->serial_num = 0;
+
+ usb_kill_urb (port->interrupt_in_urb);
+ dbg("%s - usb_reset_device", __FUNCTION__ );
+ status = usb_reset_device(port->serial->dev);
+ if (status)
+ dbg("%s - usb_reset_device failed: %d",
+ __FUNCTION__, status);
+ return status;
+}
+
+
+
+/*
+ * clear all cached data
+ */
+static int garmin_clear(struct garmin_data * garmin_data_p)
+{
+ int status = 0;
+
+ struct usb_serial_port *port = garmin_data_p->port;
+
+ if (port != 0 && garmin_data_p->flags & FLAGS_APP_RESP_SEEN) {
+ /* send a terminate command */
+ status = garmin_write_bulk(port, GARMIN_STOP_TRANSFER_REQ,
+ sizeof(GARMIN_STOP_TRANSFER_REQ));
+ }
+
+ /* flush all queued data */
+ pkt_clear(garmin_data_p);
+
+ garmin_data_p->insize = 0;
+ garmin_data_p->outsize = 0;
+
+ return status;
+}
+
+
+
+
+
+
+static int garmin_init_session(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ int status = 0;
+
+ if (status == 0) {
+ usb_kill_urb (port->interrupt_in_urb);
+
+ dbg("%s - adding interrupt input", __FUNCTION__);
+ port->interrupt_in_urb->dev = serial->dev;
+ status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (status)
+ dev_err(&serial->dev->dev,
+ "%s - failed submitting interrupt urb,"
+ " error %d\n",
+ __FUNCTION__, status);
+ }
+
+ if (status == 0) {
+ dbg("%s - starting session ...", __FUNCTION__);
+ garmin_data_p->state = STATE_ACTIVE;
+ status = garmin_write_bulk(port, GARMIN_START_SESSION_REQ,
+ sizeof(GARMIN_START_SESSION_REQ));
+
+ if (status >= 0) {
+
+ garmin_data_p->ignorePkts++;
+
+ /* not needed, but the win32 driver does it too ... */
+ status = garmin_write_bulk(port,
+ GARMIN_START_SESSION_REQ2,
+ sizeof(GARMIN_START_SESSION_REQ2));
+ if (status >= 0) {
+ status = 0;
+ garmin_data_p->ignorePkts++;
+ }
+ }
+ }
+
+ return status;
+}
+
+
+
+
+
+static int garmin_open (struct usb_serial_port *port, struct file *filp)
+{
+ int status = 0;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ /*
+ * Force low_latency on so that our tty_push actually forces the data
+ * through, otherwise it is scheduled, and with high data rates (like
+ * with OHCI) data can get lost.
+ */
+ if (port->tty)
+ port->tty->low_latency = 1;
+
+ garmin_data_p->mode = initial_mode;
+ garmin_data_p->count = 0;
+ garmin_data_p->flags = 0;
+
+ /* shutdown any bulk reads that might be going on */
+ usb_kill_urb (port->write_urb);
+ usb_kill_urb (port->read_urb);
+
+ if (garmin_data_p->state == STATE_RESET) {
+ status = garmin_init_session(port);
+ }
+
+ garmin_data_p->state = STATE_ACTIVE;
+
+ return status;
+}
+
+
+static void garmin_close (struct usb_serial_port *port, struct file * filp)
+{
+ struct usb_serial *serial = port->serial;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+ dbg("%s - port %d - mode=%d state=%d flags=0x%X", __FUNCTION__,
+ port->number, garmin_data_p->mode,
+ garmin_data_p->state, garmin_data_p->flags);
+
+ if (!serial)
+ return;
+
+ garmin_clear(garmin_data_p);
+
+ /* shutdown our urbs */
+ usb_kill_urb (port->read_urb);
+ usb_kill_urb (port->write_urb);
+
+ if (noResponseFromAppLayer(garmin_data_p) ||
+ ((garmin_data_p->flags & CLEAR_HALT_REQUIRED) != 0)) {
+ process_resetdev_request(port);
+ garmin_data_p->state = STATE_RESET;
+ } else {
+ garmin_data_p->state = STATE_DISCONNECTED;
+ }
+}
+
+
+static void garmin_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+ /* free up the transfer buffer, as usb_free_urb() does not do this */
+ kfree (urb->transfer_buffer);
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (urb->status) {
+ dbg("%s - nonzero write bulk status received: %d",
+ __FUNCTION__, urb->status);
+ garmin_data_p->flags |= CLEAR_HALT_REQUIRED;
+ }
+
+ schedule_work(&port->work);
+}
+
+
+static int garmin_write_bulk (struct usb_serial_port *port,
+ const unsigned char *buf, int count)
+{
+ struct usb_serial *serial = port->serial;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ struct urb *urb;
+ unsigned char *buffer;
+ int status;
+
+ dbg("%s - port %d, state %d", __FUNCTION__, port->number,
+ garmin_data_p->state);
+
+ garmin_data_p->flags &= ~FLAGS_DROP_DATA;
+
+ buffer = kmalloc (count, GFP_ATOMIC);
+ if (!buffer) {
+ dev_err(&port->dev, "out of memory\n");
+ return -ENOMEM;
+ }
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ dev_err(&port->dev, "no more free urbs\n");
+ kfree (buffer);
+ return -ENOMEM;
+ }
+
+ memcpy (buffer, buf, count);
+
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer);
+
+ usb_fill_bulk_urb (urb, serial->dev,
+ usb_sndbulkpipe (serial->dev,
+ port->bulk_out_endpointAddress),
+ buffer, count,
+ garmin_write_bulk_callback, port);
+ urb->transfer_flags |= URB_ZERO_PACKET;
+
+ if (GARMIN_LAYERID_APPL == getLayerId(buffer)) {
+ garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
+ if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
+ pkt_clear(garmin_data_p);
+ garmin_data_p->state = STATE_GSP_WAIT_DATA;
+ }
+ }
+
+ /* send it down the pipe */
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ dev_err(&port->dev,
+ "%s - usb_submit_urb(write bulk) "
+ "failed with status = %d\n",
+ __FUNCTION__, status);
+ count = status;
+ } else {
+
+ if (GARMIN_LAYERID_APPL == getLayerId(buffer)
+ && (garmin_data_p->mode == MODE_GARMIN_SERIAL)) {
+
+ gsp_send_ack(garmin_data_p, buffer[4]);
+ }
+ }
+
+ /* we are done with this urb, so let the host driver
+ * really free it when it is finished with it */
+ usb_free_urb (urb);
+
+ return count;
+}
+
+
+
+static int garmin_write (struct usb_serial_port *port,
+ const unsigned char *buf, int count)
+{
+ int pktid, pktsiz, len;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ __le32 *privpkt = (__le32 *)garmin_data_p->privpkt;
+
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buf);
+
+ /* check for our private packets */
+ if (count >= GARMIN_PKTHDR_LENGTH) {
+
+ len = PRIVPKTSIZ;
+ if (count < len)
+ len = count;
+
+ memcpy(garmin_data_p->privpkt, buf, len);
+
+ pktsiz = getDataLength(garmin_data_p->privpkt);
+ pktid = getPacketId(garmin_data_p->privpkt);
+
+ if (count == (GARMIN_PKTHDR_LENGTH+pktsiz)
+ && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) {
+
+ dbg("%s - processing private request %d",
+ __FUNCTION__, pktid);
+
+ // drop all unfinished transfers
+ garmin_clear(garmin_data_p);
+
+ switch(pktid) {
+
+ case PRIV_PKTID_SET_DEBUG:
+ if (pktsiz != 4)
+ return -EINVPKT;
+ debug = __le32_to_cpu(privpkt[3]);
+ dbg("%s - debug level set to 0x%X",
+ __FUNCTION__, debug);
+ break;
+
+ case PRIV_PKTID_SET_MODE:
+ if (pktsiz != 4)
+ return -EINVPKT;
+ garmin_data_p->mode = __le32_to_cpu(privpkt[3]);
+ dbg("%s - mode set to %d",
+ __FUNCTION__, garmin_data_p->mode);
+ break;
+
+ case PRIV_PKTID_INFO_REQ:
+ priv_status_resp(port);
+ break;
+
+ case PRIV_PKTID_RESET_REQ:
+ garmin_data_p->flags |= FLAGS_APP_REQ_SEEN;
+ break;
+
+ case PRIV_PKTID_SET_DEF_MODE:
+ if (pktsiz != 4)
+ return -EINVPKT;
+ initial_mode = __le32_to_cpu(privpkt[3]);
+ dbg("%s - initial_mode set to %d",
+ __FUNCTION__,
+ garmin_data_p->mode);
+ break;
+ }
+ return count;
+ }
+ }
+
+ if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
+ return gsp_receive(garmin_data_p, buf, count);
+ } else { /* MODE_NATIVE */
+ return nat_receive(garmin_data_p, buf, count);
+ }
+}
+
+
+static int garmin_write_room (struct usb_serial_port *port)
+{
+ /*
+ * Report back the bytes currently available in the output buffer.
+ */
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ return GPS_OUT_BUFSIZ-garmin_data_p->outsize;
+}
+
+
+static int garmin_chars_in_buffer (struct usb_serial_port *port)
+{
+ /*
+ * Report back the number of bytes currently in our input buffer.
+ * Will this lock up the driver - the buffer contains an incomplete
+ * package which will not be written to the device until it
+ * has been completed ?
+ */
+ //struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ //return garmin_data_p->insize;
+ return 0;
+}
+
+
+static void garmin_read_process(struct garmin_data * garmin_data_p,
+ unsigned char *data, unsigned data_length)
+{
+ if (garmin_data_p->flags & FLAGS_DROP_DATA) {
+ /* abort-transfer cmd is actice */
+ dbg("%s - pkt dropped", __FUNCTION__);
+ } else if (garmin_data_p->state != STATE_DISCONNECTED &&
+ garmin_data_p->state != STATE_RESET ) {
+
+ /* remember any appl.layer packets, so we know
+ if a reset is required or not when closing
+ the device */
+ if (0 == memcmp(data, GARMIN_APP_LAYER_REPLY,
+ sizeof(GARMIN_APP_LAYER_REPLY)))
+ garmin_data_p->flags |= FLAGS_APP_RESP_SEEN;
+
+ /* if throttling is active or postprecessing is required
+ put the received data in th input queue, otherwise
+ send it directly to the tty port */
+ if (garmin_data_p->flags & FLAGS_QUEUING) {
+ pkt_add(garmin_data_p, data, data_length);
+ } else if (garmin_data_p->mode == MODE_GARMIN_SERIAL) {
+ if (getLayerId(data) == GARMIN_LAYERID_APPL) {
+ pkt_add(garmin_data_p, data, data_length);
+ }
+ } else {
+ send_to_tty(garmin_data_p->port, data, data_length);
+ }
+ }
+}
+
+
+static void garmin_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
+{
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial = port->serial;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ unsigned char *data = urb->transfer_buffer;
+ int status;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (!serial) {
+ dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+ return;
+ }
+
+ if (urb->status) {
+ dbg("%s - nonzero read bulk status received: %d",
+ __FUNCTION__, urb->status);
+ return;
+ }
+
+ usb_serial_debug_data(debug, &port->dev,
+ __FUNCTION__, urb->actual_length, data);
+
+ garmin_read_process(garmin_data_p, data, urb->actual_length);
+
+ /* Continue trying to read until nothing more is received */
+ if (urb->actual_length > 0) {
+ usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_rcvbulkpipe (serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ garmin_read_bulk_callback, port);
+ status = usb_submit_urb(port->read_urb, GFP_ATOMIC);
+ if (status)
+ dev_err(&port->dev,
+ "%s - failed resubmitting read urb, error %d\n",
+ __FUNCTION__, status);
+ }
+ return;
+}
+
+
+static void garmin_read_int_callback (struct urb *urb, struct pt_regs *regs)
+{
+ int status;
+ struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+ struct usb_serial *serial = port->serial;
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+ unsigned char *data = urb->transfer_buffer;
+
+ switch (urb->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__, urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d",
+ __FUNCTION__, urb->status);
+ return;
+ }
+
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__,
+ urb->actual_length, urb->transfer_buffer);
+
+ if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) &&
+ 0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY,
+ sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) {
+
+ dbg("%s - bulk data available.", __FUNCTION__);
+
+ /* bulk data available */
+ usb_fill_bulk_urb (port->read_urb, serial->dev,
+ usb_rcvbulkpipe (serial->dev,
+ port->bulk_in_endpointAddress),
+ port->read_urb->transfer_buffer,
+ port->read_urb->transfer_buffer_length,
+ garmin_read_bulk_callback, port);
+ status = usb_submit_urb(port->read_urb, GFP_KERNEL);
+ if (status) {
+ dev_err(&port->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __FUNCTION__, status);
+ }
+
+ } else if (urb->actual_length == (4+sizeof(GARMIN_START_SESSION_REPLY))
+ && 0 == memcmp(data, GARMIN_START_SESSION_REPLY,
+ sizeof(GARMIN_START_SESSION_REPLY))) {
+
+ garmin_data_p->flags |= FLAGS_SESSION_REPLY1_SEEN;
+
+ /* save the serial number */
+ garmin_data_p->serial_num
+ = __le32_to_cpup((__le32*)(data+GARMIN_PKTHDR_LENGTH));
+
+ dbg("%s - start-of-session reply seen - serial %u.",
+ __FUNCTION__, garmin_data_p->serial_num);
+ }
+
+ if (garmin_data_p->ignorePkts) {
+ /* this reply belongs to a request generated by the driver,
+ ignore it. */
+ dbg("%s - pkt ignored (%d)",
+ __FUNCTION__, garmin_data_p->ignorePkts);
+ garmin_data_p->ignorePkts--;
+ } else {
+ garmin_read_process(garmin_data_p, data, urb->actual_length);
+ }
+
+ port->interrupt_in_urb->dev = port->serial->dev;
+ status = usb_submit_urb (urb, GFP_ATOMIC);
+ if (status)
+ dev_err(&urb->dev->dev,
+ "%s - Error %d submitting interrupt urb\n",
+ __FUNCTION__, status);
+}
+
+
+/*
+ * Sends the next queued packt to the tty port (garmin native mode only)
+ * and then sets a timer to call itself again until all queued data
+ * is sent.
+ */
+static int garmin_flush_queue(struct garmin_data * garmin_data_p)
+{
+ struct garmin_packet *pkt;
+
+ if ((garmin_data_p->flags & FLAGS_THROTTLED) == 0) {
+ pkt = pkt_pop(garmin_data_p);
+ if (pkt != 0) {
+
+ send_to_tty(garmin_data_p->port, pkt->data, pkt->size);
+ kfree(pkt);
+ mod_timer(&garmin_data_p->timer, (1)+jiffies);
+
+ } else {
+ garmin_data_p->flags &= ~FLAGS_QUEUING;
+ }
+ }
+ return 0;
+}
+
+
+static void garmin_throttle (struct usb_serial_port *port)
+{
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+ /* set flag, data received will be put into a queue
+ for later processing */
+ garmin_data_p->flags |= FLAGS_QUEUING|FLAGS_THROTTLED;
+}
+
+
+static void garmin_unthrottle (struct usb_serial_port *port)
+{
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+ garmin_data_p->flags &= ~FLAGS_THROTTLED;
+
+ /* in native mode send queued data to tty, in
+ serial mode nothing needs to be done here */
+ if (garmin_data_p->mode == MODE_NATIVE)
+ garmin_flush_queue(garmin_data_p);
+}
+
+
+
+/*
+ * The timer is currently only used to send queued packets to
+ * the tty in cases where the protocol provides no own handshaking
+ * to initiate the transfer.
+ */
+static void timeout_handler(unsigned long data)
+{
+ struct garmin_data *garmin_data_p = (struct garmin_data *) data;
+
+ /* send the next queued packet to the tty port */
+ if (garmin_data_p->mode == MODE_NATIVE)
+ if (garmin_data_p->flags & FLAGS_QUEUING)
+ garmin_flush_queue(garmin_data_p);
+}
+
+
+
+static int garmin_attach (struct usb_serial *serial)
+{
+ int status = 0;
+ struct usb_serial_port *port = serial->port[0];
+ struct garmin_data * garmin_data_p = NULL;
+
+ dbg("%s", __FUNCTION__);
+
+ garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL);
+ if (garmin_data_p == NULL) {
+ dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+ memset (garmin_data_p, 0, sizeof(struct garmin_data));
+ init_timer(&garmin_data_p->timer);
+ spin_lock_init(&garmin_data_p->lock);
+ INIT_LIST_HEAD(&garmin_data_p->pktlist);
+ //garmin_data_p->timer.expires = jiffies + session_timeout;
+ garmin_data_p->timer.data = (unsigned long)garmin_data_p;
+ garmin_data_p->timer.function = timeout_handler;
+ garmin_data_p->port = port;
+ garmin_data_p->state = 0;
+ garmin_data_p->count = 0;
+ usb_set_serial_port_data(port, garmin_data_p);
+
+ status = garmin_init_session(port);
+
+ return status;
+}
+
+
+static void garmin_shutdown (struct usb_serial *serial)
+{
+ struct usb_serial_port *port = serial->port[0];
+ struct garmin_data * garmin_data_p = usb_get_serial_port_data(port);
+
+ dbg("%s", __FUNCTION__);
+
+ usb_kill_urb (port->interrupt_in_urb);
+ del_timer_sync(&garmin_data_p->timer);
+ kfree (garmin_data_p);
+ usb_set_serial_port_data(port, NULL);
+}
+
+
+
+
+
+
+
+/* All of the device info needed */
+static struct usb_serial_device_type garmin_device = {
+ .owner = THIS_MODULE,
+ .name = "Garmin GPS usb/tty",
+ .short_name = "garmin_gps",
+ .id_table = id_table,
+ .num_interrupt_in = 1,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .open = garmin_open,
+ .close = garmin_close,
+ .throttle = garmin_throttle,
+ .unthrottle = garmin_unthrottle,
+ .attach = garmin_attach,
+ .shutdown = garmin_shutdown,
+ .write = garmin_write,
+ .write_room = garmin_write_room,
+ .chars_in_buffer = garmin_chars_in_buffer,
+ .write_bulk_callback = garmin_write_bulk_callback,
+ .read_bulk_callback = garmin_read_bulk_callback,
+ .read_int_callback = garmin_read_int_callback,
+};
+
+
+static int __init garmin_init (void)
+{
+ int retval;
+
+ retval = usb_serial_register(&garmin_device);
+ if (retval)
+ goto failed_garmin_register;
+ retval = usb_register(&garmin_driver);
+ if (retval)
+ goto failed_usb_register;
+ info(DRIVER_DESC " " DRIVER_VERSION);
+
+ return 0;
+failed_usb_register:
+ usb_serial_deregister(&garmin_device);
+failed_garmin_register:
+ return retval;
+}
+
+
+static void __exit garmin_exit (void)
+{
+ usb_deregister (&garmin_driver);
+ usb_serial_deregister (&garmin_device);
+}
+
+
+
+
+module_init(garmin_init);
+module_exit(garmin_exit);
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+module_param(initial_mode, int, S_IRUGO);
+MODULE_PARM_DESC(initial_mode, "Initial mode");
+
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 010160ed1f409a..b194420025ef9e 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -659,7 +659,7 @@ static void get_product_info(struct edgeport_serial *edge_serial)
memset (product_info, 0, sizeof(struct edgeport_product_info));
- product_info->ProductId = (__u16)(edge_serial->serial->dev->descriptor.idProduct & ~ION_DEVICE_ID_80251_NETCHIP);
+ product_info->ProductId = (__u16)(le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ~ION_DEVICE_ID_80251_NETCHIP);
product_info->NumPorts = edge_serial->manuf_descriptor.NumPorts;
product_info->ProdInfoVer = 0;
@@ -675,7 +675,7 @@ static void get_product_info(struct edgeport_serial *edge_serial)
memcpy(product_info->ManufactureDescDate, edge_serial->manuf_descriptor.DescDate, sizeof(edge_serial->manuf_descriptor.DescDate));
// check if this is 2nd generation hardware
- if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_80251_NETCHIP) {
+ if (le16_to_cpu(edge_serial->serial->dev->descriptor.idProduct) & ION_DEVICE_ID_80251_NETCHIP) {
product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN2.MajorVersion;
product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN2.MinorVersion;
product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber);
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index bd86f7e7c3574c..b9846a5ae636d0 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -1342,9 +1342,9 @@ static int TIDownloadFirmware (struct edgeport_serial *serial)
if (status)
return status;
- if (serial->serial->dev->descriptor.idVendor != USB_VENDOR_ID_ION) {
+ if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) {
dbg ("%s - VID = 0x%x", __FUNCTION__,
- serial->serial->dev->descriptor.idVendor);
+ le16_to_cpu(serial->serial->dev->descriptor.idVendor));
serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II;
goto StayInBootMode;
}
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index 20adf2eedcbb4f..7bd1e28c4526fd 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -1174,16 +1174,16 @@ static int keyspan_fake_startup (struct usb_serial *serial)
char *fw_name;
dbg("Keyspan startup version %04x product %04x",
- serial->dev->descriptor.bcdDevice,
- serial->dev->descriptor.idProduct);
+ le16_to_cpu(serial->dev->descriptor.bcdDevice),
+ le16_to_cpu(serial->dev->descriptor.idProduct));
- if ((serial->dev->descriptor.bcdDevice & 0x8000) != 0x8000) {
+ if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) != 0x8000) {
dbg("Firmware already loaded. Quitting.");
return(1);
}
/* Select firmware image on the basis of idProduct */
- switch (serial->dev->descriptor.idProduct) {
+ switch (le16_to_cpu(serial->dev->descriptor.idProduct)) {
case keyspan_usa28_pre_product_id:
record = &keyspan_usa28_firmware[0];
fw_name = "USA28";
@@ -2248,10 +2248,10 @@ static int keyspan_startup (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
- if (d_details->product_id == serial->dev->descriptor.idProduct)
+ if (d_details->product_id == le16_to_cpu(serial->dev->descriptor.idProduct))
break;
if (d_details == NULL) {
- dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __FUNCTION__, serial->dev->descriptor.idProduct);
+ dev_err(&serial->dev->dev, "%s - unknown product id %x\n", __FUNCTION__, le16_to_cpu(serial->dev->descriptor.idProduct));
return 1;
}
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
index 2f45c60bd25caf..eaa290bbf40d2d 100644
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -713,12 +713,12 @@ static int keyspan_pda_fake_startup (struct usb_serial *serial)
response = ezusb_set_reset(serial, 1);
#ifdef KEYSPAN
- if (serial->dev->descriptor.idVendor == KEYSPAN_VENDOR_ID)
+ if (le16_to_cpu(serial->dev->descriptor.idVendor) == KEYSPAN_VENDOR_ID)
record = &keyspan_pda_firmware[0];
#endif
#ifdef XIRCOM
- if ((serial->dev->descriptor.idVendor == XIRCOM_VENDOR_ID) ||
- (serial->dev->descriptor.idVendor == ENTREGRA_VENDOR_ID))
+ if ((le16_to_cpu(serial->dev->descriptor.idVendor) == XIRCOM_VENDOR_ID) ||
+ (le16_to_cpu(serial->dev->descriptor.idVendor) == ENTREGRA_VENDOR_ID))
record = &xircom_pgs_firmware[0];
#endif
if (record == NULL) {
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c
index a37b28d134ce4c..10d5cd1377a581 100644
--- a/drivers/usb/serial/kobil_sct.c
+++ b/drivers/usb/serial/kobil_sct.c
@@ -155,7 +155,7 @@ static int kobil_startup (struct usb_serial *serial)
priv->filled = 0;
priv->cur_pos = 0;
- priv->device_type = serial->product;
+ priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);
priv->line_state = 0;
switch (priv->device_type){
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
index 1c16a1f0bfd205..a61fecf5cdd127 100644
--- a/drivers/usb/serial/mct_u232.c
+++ b/drivers/usb/serial/mct_u232.c
@@ -82,21 +82,10 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.2"
+#define DRIVER_VERSION "z2.0" /* Linux in-kernel version */
#define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>"
#define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver"
-/*
- * Some not properly written applications do not handle the return code of
- * write() correctly. This can result in character losses. A work-a-round
- * can be compiled in with the following definition. This work-a-round
- * should _NOT_ be part of an 'official' kernel release, of course!
- */
-#undef FIX_WRITE_RETURN_CODE_PROBLEM
-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
-static int write_blocking; /* disabled by default */
-#endif
-
static int debug;
/*
@@ -108,12 +97,6 @@ static int mct_u232_open (struct usb_serial_port *port,
struct file *filp);
static void mct_u232_close (struct usb_serial_port *port,
struct file *filp);
-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
-static int mct_u232_write (struct usb_serial_port *port,
- const unsigned char *buf,
- int count);
-static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
-#endif
static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs);
static void mct_u232_set_termios (struct usb_serial_port *port,
struct termios * old);
@@ -151,7 +134,7 @@ static struct usb_driver mct_u232_driver = {
static struct usb_serial_device_type mct_u232_device = {
.owner = THIS_MODULE,
- .name = "Magic Control Technology USB-RS232",
+ .name = "MCT U232",
.short_name = "mct_u232",
.id_table = id_table_combined,
.num_interrupt_in = 2,
@@ -160,10 +143,6 @@ static struct usb_serial_device_type mct_u232_device = {
.num_ports = 1,
.open = mct_u232_open,
.close = mct_u232_close,
-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
- .write = mct_u232_write,
- .write_bulk_callback = mct_u232_write_bulk_callback,
-#endif
.read_int_callback = mct_u232_read_int_callback,
.ioctl = mct_u232_ioctl,
.set_termios = mct_u232_set_termios,
@@ -194,9 +173,10 @@ struct mct_u232_private {
* we do not know how to support. We ignore them for the moment.
* XXX Rate-limit the error message, it's user triggerable.
*/
-static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) {
- if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID
- || serial->dev->descriptor.idProduct == MCT_U232_BELKIN_F5U109_PID) {
+static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value)
+{
+ if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
+ || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
switch (value) {
case B300: return 0x01;
case B600: return 0x02; /* this one not tested */
@@ -366,15 +346,11 @@ static int mct_u232_startup (struct usb_serial *serial)
struct mct_u232_private *priv;
struct usb_serial_port *port, *rport;
- /* allocate the private data structure */
priv = kmalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- /* set initial values for control structures */
+ memset(priv, 0, sizeof(struct mct_u232_private));
spin_lock_init(&priv->lock);
- priv->control_state = 0;
- priv->last_lsr = 0;
- priv->last_msr = 0;
usb_set_serial_port_data(serial->port[0], priv);
init_waitqueue_head(&serial->port[0]->write_wait);
@@ -404,8 +380,10 @@ static void mct_u232_shutdown (struct usb_serial *serial)
for (i=0; i < serial->num_ports; ++i) {
/* My special items, the standard routines free my urbs */
priv = usb_get_serial_port_data(serial->port[i]);
- if (priv)
+ if (priv) {
+ usb_set_serial_port_data(serial->port[i], NULL);
kfree(priv);
+ }
}
} /* mct_u232_shutdown */
@@ -426,7 +404,7 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
* it seems to be able to accept only 16 bytes (and that's what
* SniffUSB says too...)
*/
- if (serial->dev->descriptor.idProduct == MCT_U232_SITECOM_PID)
+ if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID)
port->bulk_out_size = 16;
/* Do a defined restart: the normal serial device seems to
@@ -459,14 +437,16 @@ static int mct_u232_open (struct usb_serial_port *port, struct file *filp)
port->read_urb->dev = port->serial->dev;
retval = usb_submit_urb(port->read_urb, GFP_KERNEL);
if (retval) {
- err("usb_submit_urb(read bulk) failed");
+ err("usb_submit_urb(read bulk) failed pipe 0x%x err %d",
+ port->read_urb->pipe, retval);
goto exit;
}
port->interrupt_in_urb->dev = port->serial->dev;
retval = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (retval)
- err(" usb_submit_urb(read int) failed");
+ err(" usb_submit_urb(read int) failed pipe 0x%x err %d",
+ port->interrupt_in_urb->pipe, retval);
exit:
return 0;
@@ -486,101 +466,6 @@ static void mct_u232_close (struct usb_serial_port *port, struct file *filp)
} /* mct_u232_close */
-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
-/* The generic routines work fine otherwise */
-
-static int mct_u232_write (struct usb_serial_port *port,
- const unsigned char *buf, int count)
-{
- struct usb_serial *serial = port->serial;
- int result, bytes_sent, size;
-
- dbg("%s - port %d", __FUNCTION__, port->number);
-
- if (count == 0) {
- dbg("%s - write request of 0 bytes", __FUNCTION__);
- return (0);
- }
-
- /* only do something if we have a bulk out endpoint */
- if (!serial->num_bulk_out)
- return(0);
-
- /* another write is still pending? */
- if (port->write_urb->status == -EINPROGRESS) {
- dbg("%s - already writing", __FUNCTION__);
- return (0);
- }
-
- bytes_sent = 0;
- while (count > 0) {
- size = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-
- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, size, buf);
-
- memcpy (port->write_urb->transfer_buffer, buf, size);
-
- /* set up our urb */
- usb_fill_bulk_urb(port->write_urb, serial->dev,
- usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- port->write_urb->transfer_buffer, size,
- ((serial->type->write_bulk_callback) ?
- serial->type->write_bulk_callback :
- mct_u232_write_bulk_callback),
- port);
-
- /* send the data out the bulk port */
- result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
- if (result) {
- err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
- return result;
- }
-
- bytes_sent += size;
- if (write_blocking)
- interruptible_sleep_on(&port->write_wait);
- else
- break;
-
- buf += size;
- count -= size;
- }
-
- return bytes_sent;
-} /* mct_u232_write */
-
-static void mct_u232_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
-{
- struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
- struct usb_serial *serial = port->serial;
- struct tty_struct *tty = port->tty;
-
- dbg("%s - port %d", __FUNCTION__, port->number);
-
- if (!serial) {
- dbg("%s - bad serial pointer, exiting", __FUNCTION__);
- return;
- }
-
- if (urb->status) {
- dbg("%s - nonzero write bulk status received: %d", __FUNCTION__,
- urb->status);
- return;
- }
-
- if (write_blocking) {
- wake_up_interruptible(&port->write_wait);
- tty_wakeup(tty);
- } else {
- /* from generic_write_bulk_callback */
- schedule_work(&port->work);
- }
-
- return;
-} /* mct_u232_write_bulk_callback */
-#endif
-
static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
{
struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
@@ -591,8 +476,6 @@ static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
int status;
unsigned long flags;
- dbg("%s - port %d", __FUNCTION__, port->number);
-
switch (urb->status) {
case 0:
/* success */
@@ -612,7 +495,8 @@ static void mct_u232_read_int_callback (struct urb *urb, struct pt_regs *regs)
dbg("%s - bad serial pointer, exiting", __FUNCTION__);
return;
}
-
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
/*
@@ -893,12 +777,5 @@ MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
-#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
-module_param(write_blocking, int, 0);
-MODULE_PARM_DESC(write_blocking,
- "The write function will block to write out all data");
-#endif
-
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
-
diff --git a/drivers/usb/serial/ti_fw_3410.h b/drivers/usb/serial/ti_fw_3410.h
new file mode 100644
index 00000000000000..71e88579dfe0e0
--- /dev/null
+++ b/drivers/usb/serial/ti_fw_3410.h
@@ -0,0 +1,885 @@
+/* vi: ts=8 sw=8
+ *
+ * TI 3410 USB Serial Driver Firmware Header
+ *
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * 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.
+ */
+
+#ifndef _TI_FW_3410_H_
+#define _TI_FW_3410_H_
+
+/* firmware 9/10/04 FW3410_Special_StartWdogOnStartPort */
+
+static unsigned char ti_fw_3410[] = {
+0xC2, 0x35, /* firmware image length excluding header, little endian */
+0x00, /* placeholder for checksum */
+
+0x02,0x00,0x1e,0x02,0x1a,0xdb,0xff,0xff,0xff,0xff,0xff,0x02,0x32,0xcb,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x02,0x33,0x76,0x75,0x81,
+0xce,0x90,0xfd,0xe8,0x85,0x83,0xa0,0x12,0x34,0xea,0xec,0x4d,0x60,0x6a,0x78,0xab,
+0x80,0x03,0x76,0x00,0x18,0xb8,0x9c,0xfa,0x78,0x7f,0x80,0x03,0x76,0x00,0x18,0xb8,
+0x65,0xfa,0x78,0x20,0x80,0x03,0x76,0x00,0x18,0xb8,0x20,0xfa,0x90,0xfd,0xdd,0xae,
+0x83,0xaf,0x82,0x90,0xfb,0xf8,0x12,0x00,0xa1,0x60,0x05,0xe4,0xf0,0xa3,0x80,0xf6,
+0x90,0xfd,0xe8,0xa8,0x82,0x90,0xfd,0xe8,0xa9,0x82,0xe8,0xc3,0x99,0x50,0x05,0x76,
+0x00,0x08,0x80,0xf6,0x90,0x00,0xff,0x12,0x00,0xaa,0x90,0x01,0x03,0x12,0x00,0xaa,
+0x90,0x01,0x07,0x12,0x00,0xaa,0x90,0x01,0x0b,0x12,0x00,0xc8,0x90,0x01,0x11,0x12,
+0x00,0xc8,0x90,0x01,0x17,0x12,0x00,0xc8,0x75,0xd0,0x00,0x12,0x33,0xc8,0x02,0x01,
+0x1d,0xef,0x65,0x82,0x70,0x03,0xee,0x65,0x83,0x22,0xe4,0x93,0xf8,0x74,0x01,0x93,
+0xf9,0x74,0x02,0x93,0xfe,0x74,0x03,0x93,0xf5,0x82,0x8e,0x83,0xe8,0x69,0x70,0x01,
+0x22,0xe4,0x93,0xf6,0xa3,0x08,0x80,0xf4,0xe4,0x93,0xfc,0x74,0x01,0x93,0xfd,0x74,
+0x02,0x93,0xfe,0x74,0x03,0x93,0xff,0x74,0x04,0x93,0xf8,0x74,0x05,0x93,0xf5,0x82,
+0x88,0x83,0x12,0x00,0xa1,0x70,0x01,0x22,0xe4,0x93,0xa3,0xa8,0x83,0xa9,0x82,0x8c,
+0x83,0x8d,0x82,0xf0,0xa3,0xac,0x83,0xad,0x82,0x88,0x83,0x89,0x82,0x80,0xe3,0x21,
+0x21,0x04,0x92,0x80,0x80,0x04,0x92,0xac,0xae,0x04,0x92,0xfd,0xe8,0x04,0x94,0x04,
+0x94,0xfb,0xf3,0x04,0x99,0x04,0x94,0xfb,0xf3,0x04,0xf9,0x04,0xf9,0x80,0xfe,0xd0,
+0xf0,0x30,0xf0,0x09,0x20,0xf3,0x03,0xf6,0x80,0x10,0xf7,0x80,0x0d,0x30,0xf1,0x09,
+0x20,0xf3,0x03,0xf2,0x80,0x04,0xf3,0x80,0x01,0xf0,0x20,0xf4,0x04,0xfc,0xd0,0xe0,
+0xcc,0x22,0xcc,0xc0,0xe0,0x12,0x01,0x5a,0x02,0x01,0x4b,0xbc,0x00,0x05,0xd0,0xf0,
+0xac,0xf0,0x22,0xc3,0x13,0xdc,0xfc,0x02,0x01,0x21,0xbf,0x00,0x09,0xed,0x25,0x82,
+0x75,0xf0,0x01,0xf8,0xe6,0x22,0xbf,0x01,0x0f,0xed,0x25,0x82,0xf5,0x82,0xee,0x35,
+0x83,0xf5,0x83,0x75,0xf0,0x04,0xe0,0x22,0xed,0x25,0x82,0x75,0xf0,0x02,0xf8,0xe2,
+0x22,0xd0,0x83,0xd0,0x82,0xf5,0xf0,0xc3,0xe4,0x93,0xa3,0xc5,0xf0,0x95,0xf0,0xc0,
+0xe0,0xc3,0xd0,0xf0,0xe4,0x93,0xa3,0x95,0xf0,0x40,0x12,0xa3,0xa3,0xc3,0xe5,0xf0,
+0x33,0x50,0x02,0x05,0x83,0x25,0x82,0xf5,0x82,0x50,0x02,0x05,0x83,0x74,0x01,0x93,
+0xc0,0xe0,0xe4,0x93,0xc0,0xe0,0x22,0xd0,0x83,0xd0,0x82,0xf5,0xf0,0xe4,0x93,0x70,
+0x09,0x74,0x01,0x93,0x70,0x04,0xa3,0xa3,0x80,0x0c,0x74,0x02,0x93,0x65,0xf0,0x60,
+0x05,0xa3,0xa3,0xa3,0x80,0xe7,0x74,0x01,0x93,0xc0,0xe0,0xe4,0x93,0xc0,0xe0,0x22,
+0x12,0x02,0x5b,0x02,0x01,0xf2,0x12,0x02,0xaf,0x02,0x01,0xf2,0x12,0x02,0xd3,0x02,
+0x01,0xf2,0x30,0xe0,0x07,0x20,0xe3,0x02,0xe6,0x22,0xe7,0x22,0x30,0xe1,0x07,0x20,
+0xe3,0x02,0xe2,0x22,0xe3,0x22,0x30,0xe2,0x02,0xe0,0x22,0xe4,0x93,0x22,0x12,0x02,
+0xd3,0x02,0x02,0x1a,0x12,0x02,0xaf,0x02,0x02,0x1a,0xab,0xf0,0x12,0x02,0x24,0xcb,
+0xc5,0xf0,0xcb,0x22,0x30,0xe0,0x10,0x20,0xe3,0x06,0xe6,0xf5,0xf0,0x08,0xe6,0x22,
+0xe7,0xf5,0xf0,0x09,0xe7,0x19,0x22,0x30,0xe1,0x10,0x20,0xe3,0x06,0xe2,0xf5,0xf0,
+0x08,0xe2,0x22,0xe3,0xf5,0xf0,0x09,0xe3,0x19,0x22,0x30,0xe2,0x06,0xe0,0xf5,0xf0,
+0xa3,0xe0,0x22,0xe4,0x93,0xf5,0xf0,0x74,0x01,0x93,0x22,0xbb,0x00,0x03,0x74,0x09,
+0x22,0xbb,0x01,0x07,0x89,0x82,0x8a,0x83,0x74,0x04,0x22,0xbb,0x02,0x07,0x89,0x82,
+0x8a,0x83,0x74,0x10,0x22,0x74,0x0a,0x22,0x02,0x02,0x7b,0xbb,0x00,0x07,0xe9,0x25,
+0x82,0xf8,0x74,0x01,0x22,0xbb,0x01,0x0d,0xe9,0x25,0x82,0xf5,0x82,0xea,0x35,0x83,
+0xf5,0x83,0x74,0x04,0x22,0xbb,0x02,0x0d,0xe9,0x25,0x82,0xf5,0x82,0xea,0x35,0x83,
+0xf5,0x83,0x74,0x10,0x22,0xe9,0x25,0x82,0xf8,0x74,0x02,0x22,0x02,0x02,0xaf,0xbf,
+0x00,0x05,0xed,0xf8,0x74,0x01,0x22,0xbf,0x01,0x07,0x8d,0x82,0x8e,0x83,0x74,0x04,
+0x22,0xbf,0x02,0x07,0x8d,0x82,0x8e,0x83,0x74,0x10,0x22,0xed,0xf8,0x74,0x02,0x22,
+0x02,0x02,0xd3,0xbf,0x00,0x07,0xed,0x25,0x82,0xf8,0x74,0x01,0x22,0xbf,0x01,0x0d,
+0xed,0x25,0x82,0xf5,0x82,0xee,0x35,0x83,0xf5,0x83,0x74,0x04,0x22,0xbf,0x02,0x0d,
+0xed,0x25,0x82,0xf5,0x82,0xee,0x35,0x83,0xf5,0x83,0x74,0x10,0x22,0xed,0x25,0x82,
+0xf8,0x74,0x02,0x22,0x02,0x03,0x07,0xc0,0xe0,0x12,0x02,0x5b,0x02,0x03,0x1f,0xc0,
+0xe0,0x12,0x02,0xaf,0x02,0x03,0x1f,0xc0,0xe0,0x12,0x02,0xd3,0x02,0x03,0x1f,0x30,
+0xe0,0x0b,0x20,0xe3,0x04,0xd0,0xe0,0xf6,0x22,0xd0,0xe0,0xf7,0x22,0x30,0xe1,0x0b,
+0x20,0xe3,0x04,0xd0,0xe0,0xf2,0x22,0xd0,0xe0,0xf3,0x22,0xd0,0xe0,0xf0,0x22,0xc9,
+0xcd,0xc9,0xca,0xce,0xca,0xcb,0xcf,0xcb,0x12,0x03,0x52,0xed,0xf9,0xee,0xfa,0xef,
+0xfb,0x22,0xbb,0x00,0x2f,0xbf,0x00,0x0a,0xfa,0xed,0xf8,0xe7,0xf6,0x08,0x09,0xda,
+0xfa,0x22,0xbf,0x01,0x12,0x8d,0x82,0x8e,0x83,0xf8,0x02,0x03,0x6f,0x09,0xa3,0xe7,
+0xf0,0xd8,0xfa,0x22,0x02,0x03,0x7a,0xfa,0xed,0xf8,0xe7,0xf2,0x08,0x09,0xda,0xfa,
+0x22,0x02,0x03,0x84,0xbb,0x01,0x4d,0xbf,0x00,0x14,0x89,0x82,0x8a,0x83,0xf9,0xed,
+0xf8,0x02,0x03,0x96,0x08,0xa3,0xe0,0xf6,0xd9,0xfa,0x22,0x02,0x03,0xa7,0xbf,0x01,
+0x22,0x8d,0x82,0x8e,0x83,0xfb,0x08,0xc9,0xc5,0x82,0xc9,0xca,0xc5,0x83,0xca,0xe0,
+0xa3,0xc9,0xc5,0x82,0xc9,0xca,0xc5,0x83,0xca,0xf0,0xa3,0xdb,0xea,0xd8,0xe8,0x22,
+0x02,0x03,0xca,0x8d,0x82,0x8e,0x83,0xf9,0xed,0xf8,0xe0,0xf2,0x08,0xa3,0xd9,0xfa,
+0x22,0x02,0x03,0xd4,0xbb,0x02,0x4d,0xbf,0x00,0x12,0x89,0x82,0x8a,0x83,0xf9,0xed,
+0xf8,0x02,0x03,0xe6,0x08,0xa3,0xe4,0x93,0xf6,0xd9,0xf9,0x22,0xbf,0x01,0x23,0x8d,
+0x82,0x8e,0x83,0xfb,0x08,0xc9,0xc5,0x82,0xc9,0xca,0xc5,0x83,0xca,0xe4,0x93,0xa3,
+0xc9,0xc5,0x82,0xc9,0xca,0xc5,0x83,0xca,0xf0,0xa3,0xdb,0xe9,0xd8,0xe7,0x22,0x02,
+0x04,0x19,0x89,0x82,0x8a,0x83,0xf9,0xed,0xf8,0xe4,0x93,0xf2,0x08,0xa3,0xd9,0xf9,
+0x22,0x02,0x04,0x2a,0xbf,0x00,0x0d,0xfa,0xed,0xf8,0xe3,0xf6,0x08,0x09,0xda,0xfa,
+0x22,0x02,0x04,0x34,0xbf,0x01,0x12,0x8d,0x82,0x8e,0x83,0xf8,0x02,0x04,0x41,0x09,
+0xa3,0xe3,0xf0,0xd8,0xfa,0x22,0x02,0x04,0x4c,0xfa,0xed,0xf8,0xe3,0xf2,0x08,0x09,
+0xda,0xfa,0x22,0x02,0x04,0x56,0xe6,0xfb,0x08,0xe6,0xfa,0x08,0xe6,0xf9,0x04,0xf6,
+0x18,0x70,0x01,0x06,0x22,0xe6,0xff,0x08,0xe6,0xfe,0x08,0xe6,0xfd,0x22,0xef,0xf0,
+0xa3,0xee,0xf0,0xa3,0xed,0xf0,0x22,0xeb,0xf0,0xa3,0xea,0xf0,0xa3,0xe9,0xf0,0x22,
+0xe0,0xff,0xa3,0xe0,0xfe,0xa3,0xe0,0xfd,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,
+0xf9,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xf9,0x00,0x61,0x05,0x68,0x00,
+0x26,0x05,0x8f,0x00,0x33,0x0a,0x00,0x00,0x61,0x0a,0x6c,0x00,0x66,0x15,0x1d,0x00,
+0x61,0x0c,0xf0,0x00,0x61,0x09,0xa0,0x00,0x61,0x09,0xd7,0x00,0x61,0x0d,0xb7,0x00,
+0x61,0x0b,0xe8,0x00,0x61,0x0a,0x13,0x00,0x61,0x0a,0x48,0x00,0x61,0x17,0x15,0x00,
+0x33,0x17,0x28,0x00,0x34,0x1d,0xf6,0x00,0x43,0x1e,0xa1,0x00,0x44,0x20,0x0e,0x00,
+0x44,0x1f,0xfc,0x00,0x47,0x1e,0xc8,0x00,0x47,0x1f,0x6d,0x00,0x4d,0x1f,0xbe,0x00,
+0x4f,0x1e,0xea,0x00,0x58,0x32,0x56,0x00,0x61,0x7c,0xcc,0x7d,0xff,0x12,0x1c,0xa7,
+0x22,0x90,0xff,0xfc,0xe0,0x20,0xe7,0x2d,0xc2,0xaf,0xae,0x59,0xaf,0x58,0x75,0x5a,
+0x20,0xe5,0x5a,0x14,0xc5,0x5a,0x60,0x19,0xe4,0xfe,0x7f,0x05,0xee,0x4f,0xce,0x24,
+0xff,0xce,0xcf,0x34,0xff,0xcf,0x60,0x07,0xe4,0x90,0xff,0x92,0xf0,0x80,0xed,0x80,
+0xe0,0x8e,0x59,0x8f,0x58,0x22,0x12,0x05,0x01,0x7d,0x07,0x7c,0xb7,0x12,0x32,0x72,
+0x7d,0x0f,0x7c,0x6e,0x12,0x32,0x8c,0x78,0x9d,0x7a,0x06,0xe4,0xf6,0x08,0xda,0xfc,
+0x7a,0x06,0x12,0x05,0xc4,0x7c,0x03,0x12,0x0e,0x4c,0x12,0x21,0x4a,0xe4,0xfe,0xff,
+0x7c,0x0f,0x12,0x31,0xfb,0xd2,0xa8,0x22,0x12,0x30,0xe6,0xe4,0x90,0xfc,0x38,0xf0,
+0x90,0xff,0xf0,0xe0,0x30,0xe4,0x08,0x74,0x01,0x90,0xfc,0x39,0xf0,0x80,0x05,0xe4,
+0x90,0xfc,0x39,0xf0,0x7d,0x0a,0x7c,0x00,0x12,0x25,0x26,0x12,0x31,0x69,0x22,0x12,
+0x30,0xe6,0x90,0xfc,0x39,0xe0,0x14,0x70,0x0e,0x90,0xff,0xf0,0xe0,0x44,0x10,0xf0,
+0x7c,0x00,0x12,0x25,0xbf,0x80,0x19,0x90,0xfc,0x39,0xe0,0x70,0x0e,0x90,0xff,0xf0,
+0xe0,0x54,0xef,0xf0,0x7c,0x00,0x12,0x25,0xbf,0x80,0x05,0x7c,0x17,0x12,0x25,0xbf,
+0x12,0x31,0x69,0x22,0x90,0xff,0xf0,0xe0,0x54,0xab,0xf0,0x90,0xff,0xf0,0xe0,0x44,
+0x20,0xf0,0x22,0x8c,0x37,0x8d,0x36,0x78,0x82,0xed,0xf6,0x08,0xec,0xf6,0xed,0xfe,
+0xec,0xfd,0x7f,0x01,0x90,0x00,0x05,0x12,0x01,0xec,0x78,0x80,0xf6,0x78,0x82,0xe6,
+0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x04,0x12,0x01,0xec,
+0x54,0x0f,0xfc,0x7d,0x80,0x12,0x17,0x46,0x78,0x80,0xe6,0x70,0x0d,0xad,0x3a,0xae,
+0x39,0xaf,0x38,0xe4,0x12,0x03,0x0f,0x7c,0x08,0x22,0x90,0xff,0xf0,0xe0,0x54,0xfe,
+0xf0,0x90,0xff,0xf0,0xe0,0x54,0xfd,0xf0,0x80,0x1e,0x78,0x82,0xe6,0xfd,0x08,0xe6,
+0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x08,0x12,0x02,0x0e,0x25,0xe0,0x44,
+0x01,0x90,0xff,0xf3,0xf0,0x02,0x06,0xd0,0x78,0x82,0xe6,0xfd,0x08,0xe6,0xfc,0xed,
+0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x06,0x12,0x02,0x0e,0x54,0xfe,0x90,0xff,0xf3,
+0xf0,0x80,0x2b,0x78,0x82,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,
+0x90,0x00,0x08,0x12,0x02,0x0e,0xfa,0xeb,0x90,0xff,0xf1,0xf0,0x12,0x08,0xbf,0x40,
+0x0d,0xad,0x3a,0xae,0x39,0xaf,0x38,0xe4,0x12,0x03,0x0f,0x7c,0x18,0x22,0x78,0x82,
+0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x08,0x12,0x02,
+0x0e,0x90,0xff,0xf1,0xf0,0x12,0x08,0xbf,0x40,0x0d,0xad,0x3a,0xae,0x39,0xaf,0x38,
+0xe4,0x12,0x03,0x0f,0x7c,0x18,0x22,0x78,0x82,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,
+0xec,0xfd,0x7f,0x01,0x90,0x00,0x06,0x12,0x02,0x0e,0x44,0x01,0x90,0xff,0xf3,0xf0,
+0x78,0x83,0xe6,0x24,0x03,0xf6,0x18,0xe6,0x34,0x00,0xf6,0x78,0x80,0xe6,0x24,0xfe,
+0x50,0x09,0x90,0xff,0xf0,0xe0,0x54,0xfd,0xf0,0x80,0x07,0x90,0xff,0xf0,0xe0,0x44,
+0x02,0xf0,0xe4,0x90,0xff,0xf1,0xf0,0x78,0x81,0x76,0x00,0x78,0x80,0xe6,0x24,0xff,
+0xfc,0xe4,0x34,0xff,0xfd,0x78,0x81,0xe6,0x7f,0x00,0xfe,0xec,0xd3,0x9e,0xef,0x64,
+0x80,0xcd,0x64,0x80,0x9d,0x40,0x2f,0x12,0x08,0xa4,0x40,0x0f,0x78,0x81,0xe6,0xad,
+0x3a,0xae,0x39,0xaf,0x38,0x12,0x03,0x0f,0x7c,0x18,0x22,0x90,0xff,0xf2,0xe0,0xfc,
+0x78,0x82,0x86,0x83,0x08,0x86,0x82,0xec,0xf0,0x78,0x81,0x06,0xa3,0x78,0x82,0xa6,
+0x83,0x08,0xa6,0x82,0x80,0xb5,0x12,0x08,0xa4,0x40,0x0f,0x78,0x81,0xe6,0xad,0x3a,
+0xae,0x39,0xaf,0x38,0x12,0x03,0x0f,0x7c,0x18,0x22,0x90,0xff,0xf2,0xe0,0xfc,0x78,
+0x82,0x86,0x83,0x08,0x86,0x82,0xec,0xf0,0x78,0x80,0xe6,0xad,0x3a,0xae,0x39,0xaf,
+0x38,0x12,0x03,0x0f,0x7c,0x00,0x22,0x8c,0x37,0x8d,0x36,0x78,0x82,0xed,0xf6,0x08,
+0xec,0xf6,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x05,0x12,0x01,0xec,0x78,0x81,
+0xf6,0x78,0x82,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,
+0x04,0x12,0x01,0xec,0x54,0x0f,0xfc,0x7d,0x81,0x12,0x17,0x46,0x78,0x81,0xe6,0x70,
+0x03,0x7c,0x08,0x22,0x90,0xff,0xf0,0xe0,0x54,0xfe,0xf0,0x90,0xff,0xf0,0xe0,0x54,
+0xfd,0xf0,0x80,0x1b,0x78,0x82,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,
+0x01,0x90,0x00,0x08,0x12,0x02,0x0e,0x25,0xe0,0x90,0xff,0xf3,0xf0,0x80,0x5b,0x78,
+0x82,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x06,0x12,
+0x02,0x0e,0x54,0xfe,0x90,0xff,0xf3,0xf0,0x80,0x21,0x78,0x82,0xe6,0xfd,0x08,0xe6,
+0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x08,0x12,0x02,0x0e,0xfa,0xeb,0x90,
+0xff,0xf1,0xf0,0x12,0x08,0xbf,0x40,0x03,0x7c,0x18,0x22,0x78,0x82,0xe6,0xfd,0x08,
+0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x08,0x12,0x02,0x0e,0x90,0xff,
+0xf1,0xf0,0x12,0x08,0xbf,0x40,0x03,0x7c,0x18,0x22,0x78,0x83,0xe6,0x24,0x0a,0xf6,
+0x18,0xe6,0x34,0x00,0xf6,0x78,0x80,0x76,0x00,0x78,0x81,0xe6,0x24,0xff,0xfc,0xe4,
+0x34,0xff,0xfd,0x78,0x80,0xe6,0x7f,0x00,0xfe,0xec,0xd3,0x9e,0xef,0x64,0x80,0xcd,
+0x64,0x80,0x9d,0x40,0x21,0x78,0x82,0x86,0x83,0x08,0x86,0x82,0xe0,0x90,0xff,0xf1,
+0xf0,0x12,0x08,0xbf,0x40,0x03,0x7c,0x18,0x22,0x78,0x80,0x06,0x78,0x83,0x06,0xe6,
+0x18,0x70,0x01,0x06,0x80,0xc3,0x90,0xff,0xf0,0xe0,0x44,0x01,0xf0,0x78,0x82,0x86,
+0x83,0x08,0x86,0x82,0xe0,0x90,0xff,0xf1,0xf0,0x12,0x08,0xbf,0x40,0x03,0x7c,0x18,
+0x22,0x7c,0x00,0x22,0x90,0xff,0xf0,0xe0,0x20,0xe7,0x12,0x90,0xff,0xf0,0xe0,0x30,
+0xe5,0x09,0x90,0xff,0xf0,0xe0,0x44,0x20,0xf0,0xc3,0x22,0x80,0xe7,0xd3,0x22,0x90,
+0xff,0xf0,0xe0,0x20,0xe3,0x12,0x90,0xff,0xf0,0xe0,0x30,0xe5,0x09,0x90,0xff,0xf0,
+0xe0,0x44,0x20,0xf0,0xc3,0x22,0x80,0xe7,0xd3,0x22,0x8c,0x42,0x8d,0x41,0x7c,0x00,
+0xed,0x54,0xf0,0xfd,0xec,0x70,0x03,0xed,0x64,0x30,0x70,0x05,0x75,0x3e,0x03,0x80,
+0x03,0x75,0x3e,0x04,0xac,0x3e,0x12,0x0f,0x69,0x75,0x83,0x00,0x85,0x83,0x40,0xe5,
+0x41,0x54,0x0f,0xf5,0x3f,0xe5,0x40,0x70,0x04,0xe5,0x3f,0x64,0x03,0x70,0x35,0xe5,
+0x3e,0x24,0xfd,0x75,0xf0,0x0a,0xa4,0x24,0x02,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,
+0xe0,0x30,0xe6,0x05,0x12,0x10,0x4b,0x80,0x19,0xe5,0x3e,0x24,0x9d,0xf8,0xc6,0x54,
+0xfb,0xf6,0x78,0xa9,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0x74,
+0x0f,0xf0,0x80,0x59,0xe5,0x40,0x70,0x04,0xe5,0x3f,0x64,0x04,0x70,0x48,0xe5,0x3e,
+0x24,0xfd,0x75,0xf0,0x0a,0xa4,0x24,0x02,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xe0,
+0x30,0xe5,0x07,0xac,0x42,0xad,0x41,0x12,0x1c,0x3c,0xe5,0x42,0x30,0xe2,0x15,0x78,
+0xad,0xe6,0x30,0xe0,0x0f,0x78,0xad,0xe6,0x30,0xe1,0x09,0xe4,0xff,0x04,0xfe,0x7c,
+0x04,0x12,0x31,0xfb,0x78,0xa9,0xe6,0x24,0x06,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0x74,0x0f,0xf0,0x80,0x07,0xe4,0xfc,0x7d,0xee,0x12,0x1c,0x3c,0xc2,0x03,0x22,
+0x12,0x30,0xe6,0x12,0x0f,0x69,0x78,0xa9,0xe6,0x24,0x06,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xe0,0x90,0xfc,0x38,0xf0,0x78,0xa9,0xe6,0x24,0x05,0xf5,0x82,0x18,
+0xe6,0x34,0x00,0xf5,0x83,0xe0,0x90,0xfc,0x39,0xf0,0xc2,0x03,0x7d,0x02,0x7c,0x00,
+0x12,0x25,0x26,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,0x78,0x95,0xec,0xf6,0xec,0x24,
+0x9d,0xf8,0xe6,0x30,0xe1,0x07,0x7c,0x13,0x12,0x25,0xbf,0x80,0x0f,0x90,0xfc,0x39,
+0xe0,0xfd,0x78,0x95,0xe6,0xfc,0x12,0x13,0xc8,0x12,0x25,0xbf,0x12,0x31,0x69,0x22,
+0x12,0x30,0xe6,0x78,0x95,0xec,0xf6,0x7d,0x00,0x12,0x0f,0x09,0x12,0x25,0xbf,0x12,
+0x31,0x69,0x22,0x12,0x30,0xe6,0x78,0x95,0xec,0xf6,0xec,0x24,0x9d,0xf8,0xe6,0x30,
+0xe2,0x07,0x7c,0x13,0x12,0x25,0xbf,0x80,0x1b,0x78,0x95,0xe6,0x24,0x9d,0xf8,0xe6,
+0x20,0xe1,0x07,0x7c,0x12,0x12,0x25,0xbf,0x80,0x0a,0x78,0x95,0xe6,0xfc,0x12,0x13,
+0xec,0x12,0x25,0xbf,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,0x78,0x95,0xec,0xf6,0xec,
+0x24,0x9d,0xf8,0xe6,0x20,0xe2,0x07,0x7c,0x11,0x12,0x25,0xbf,0x80,0x0a,0x78,0x95,
+0xe6,0xfc,0x12,0x14,0xed,0x12,0x25,0xbf,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,0x78,
+0x95,0xec,0xf6,0x12,0x0f,0x69,0x78,0xa9,0xe6,0x24,0x09,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xe0,0x90,0xfc,0x3f,0xf0,0x78,0xa9,0xe6,0x24,0x0a,0xf5,0x82,0x18,
+0xe6,0x34,0x00,0xf5,0x83,0xe0,0x90,0xfc,0x40,0xf0,0x78,0xa9,0xe6,0x24,0x03,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xfc,0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xf5,0x62,0x78,0xa9,0xe6,0x24,0x02,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xf5,0x63,0x8c,0x61,0xe4,0xec,0x33,0x33,0x54,
+0x01,0x78,0x95,0xf6,0x60,0x08,0xe5,0x62,0x30,0xe1,0x03,0x78,0x95,0x06,0x78,0x95,
+0xe6,0x90,0xfc,0x41,0xf0,0x78,0xa7,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0xfd,0xa3,0xe0,0x54,0x0c,0xfc,0xed,0x54,0xe6,0x8c,0x65,0xf5,0x64,
+0xe5,0x61,0x30,0xe5,0x03,0x43,0x65,0x01,0xe5,0x62,0x20,0xe5,0x0e,0xe5,0x61,0x54,
+0x7f,0x70,0x08,0xe5,0x61,0x20,0xe7,0x03,0x43,0x65,0x02,0xe5,0x61,0x30,0xe3,0x03,
+0x43,0x65,0x10,0xe5,0x61,0x30,0xe2,0x03,0x43,0x65,0x20,0xe5,0x61,0x54,0x03,0x60,
+0x03,0x43,0x65,0x40,0xe5,0x61,0x30,0xe1,0x03,0x43,0x65,0x80,0xe5,0x61,0x30,0xe4,
+0x03,0x43,0x64,0x01,0xe5,0x61,0x30,0xe6,0x03,0x43,0x64,0x08,0xe5,0x62,0x20,0xe4,
+0x0e,0xe5,0x61,0x54,0x7f,0x70,0x08,0xe5,0x61,0x20,0xe7,0x03,0x43,0x64,0x10,0x53,
+0x65,0xfb,0x53,0x64,0x79,0xad,0x64,0xe5,0x65,0x90,0xfc,0x3a,0xcd,0xf0,0xa3,0xcd,
+0xf0,0xe5,0x63,0x30,0xe3,0x0d,0xe5,0x63,0x54,0x30,0xc4,0x54,0x0f,0x90,0xfc,0x3d,
+0xf0,0x80,0x05,0xe4,0x90,0xfc,0x3d,0xf0,0xe5,0x63,0x54,0x03,0x90,0xfc,0x3c,0xf0,
+0xe5,0x63,0x54,0x04,0xc3,0x13,0x90,0xfc,0x3e,0xf0,0x90,0xfc,0x3c,0xe0,0x70,0x0e,
+0x7d,0x35,0x7e,0xfc,0x7f,0x01,0x74,0x01,0x90,0x00,0x09,0x12,0x01,0x42,0x78,0xa9,
+0xe6,0x24,0x08,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x7c,0x00,0xfd,0x78,
+0xa9,0xe6,0x24,0x07,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x7f,0x00,0x4c,
+0xfe,0xef,0x4d,0x90,0xfc,0x38,0xf0,0xa3,0xce,0xf0,0xce,0xc2,0x03,0x7d,0x0a,0x7c,
+0x00,0x12,0x25,0x26,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,0x78,0x95,0xec,0xf6,0x78,
+0x9a,0x76,0x01,0x08,0x76,0xfc,0x08,0x76,0x38,0x78,0x97,0x76,0x0c,0x78,0x9a,0x12,
+0x04,0x65,0x12,0x02,0x14,0x78,0x98,0xcb,0xf6,0xcb,0x08,0xf6,0x7f,0x00,0xef,0x24,
+0xea,0x40,0x1f,0xe4,0xef,0x25,0xe0,0x90,0x35,0x2c,0xfd,0x93,0xcd,0x04,0x93,0x78,
+0x99,0x66,0x70,0x03,0xed,0x18,0x66,0x70,0x06,0x78,0x97,0x76,0x00,0x80,0x03,0x0f,
+0x80,0xdc,0x78,0x96,0xef,0xf6,0x78,0x9a,0x12,0x04,0x65,0x90,0x00,0x02,0x12,0x02,
+0x0e,0x78,0x98,0xcb,0xf6,0xcb,0x08,0xf6,0x54,0x04,0xcb,0x54,0x86,0x4b,0x60,0x04,
+0x78,0x97,0x76,0x0b,0x78,0x99,0xe6,0x30,0xe3,0x13,0x78,0x9a,0x12,0x04,0x65,0x90,
+0x00,0x05,0x12,0x01,0xec,0x24,0xfb,0x50,0x04,0x78,0x97,0x76,0x0d,0x78,0x99,0xe6,
+0x54,0xc0,0x7d,0x00,0x64,0xc0,0x4d,0x70,0x04,0x78,0x97,0x76,0x0b,0x78,0x9a,0x12,
+0x04,0x65,0x90,0x00,0x04,0x12,0x01,0xec,0x24,0xfc,0x50,0x04,0x78,0x97,0x76,0x0f,
+0x78,0x9a,0x12,0x04,0x65,0x90,0x00,0x06,0x12,0x01,0xec,0x24,0xfd,0x50,0x04,0x78,
+0x97,0x76,0x0e,0x78,0x9a,0x12,0x04,0x65,0x90,0x00,0x09,0x12,0x01,0xec,0x24,0xfd,
+0x50,0x04,0x78,0x97,0x76,0x0a,0x78,0x97,0xe6,0x70,0x2a,0x78,0x95,0xe6,0xfc,0x12,
+0x0f,0x69,0x78,0x9a,0x12,0x04,0x65,0x78,0xa7,0xe6,0xf9,0x78,0xa6,0xe6,0xfa,0x7b,
+0x01,0x74,0x0a,0x78,0x00,0x12,0x03,0x3f,0xc2,0x03,0x78,0x95,0xe6,0xfc,0x12,0x11,
+0x07,0x78,0x97,0xec,0xf6,0x78,0x97,0xe6,0xfc,0x12,0x25,0xbf,0x12,0x31,0x69,0x22,
+0x12,0x30,0xe6,0x78,0x95,0xec,0xf6,0x12,0x0f,0x69,0x78,0x95,0xe6,0x24,0xfd,0x75,
+0xf0,0x0a,0xa4,0x24,0x14,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xac,0x82,0xad,0x83,
+0x78,0xa6,0x86,0x83,0x08,0x86,0x82,0xec,0xf9,0xed,0xfa,0x7b,0x0a,0x78,0x01,0x12,
+0x03,0xa7,0xc2,0x03,0x78,0x95,0xe6,0xfc,0x12,0x11,0x07,0x12,0x31,0x69,0x22,0x8d,
+0x2b,0x8c,0x2a,0xed,0x60,0x40,0x75,0x27,0x01,0x75,0x29,0x48,0x75,0x28,0xff,0xe5,
+0x2a,0x24,0xfd,0xfc,0xe4,0x34,0xff,0xfd,0xec,0x7c,0x03,0x25,0xe0,0xcd,0x33,0xcd,
+0xdc,0xf9,0xfc,0xe5,0x29,0x2c,0xf5,0x29,0xe5,0x28,0x3d,0xf5,0x28,0xad,0x29,0xae,
+0x28,0xaf,0x27,0x74,0x80,0x90,0x00,0x06,0x12,0x03,0x17,0x74,0x80,0x90,0x00,0x02,
+0x12,0x03,0x17,0x12,0x0f,0xb7,0xe5,0x2b,0x14,0x60,0x3b,0x75,0x27,0x01,0x75,0x29,
+0x08,0x75,0x28,0xff,0xe5,0x2a,0x24,0xfd,0xfc,0xe4,0x34,0xff,0xfd,0xec,0x7c,0x03,
+0x25,0xe0,0xcd,0x33,0xcd,0xdc,0xf9,0xfc,0xe5,0x29,0x2c,0xf5,0x29,0xe5,0x28,0x3d,
+0xf5,0x28,0xad,0x29,0xae,0x28,0xaf,0x27,0xe4,0x90,0x00,0x06,0x12,0x03,0x17,0xe4,
+0x90,0x00,0x02,0x12,0x03,0x17,0x22,0x12,0x30,0xe6,0x78,0x95,0xec,0xf6,0xec,0x24,
+0x9d,0xf8,0xe6,0x30,0xe2,0x09,0x78,0x95,0xe6,0xfc,0x12,0x14,0xed,0xd2,0x00,0x78,
+0x95,0xe6,0xfc,0x12,0x0f,0x69,0x78,0x96,0x76,0x00,0x90,0xfc,0x39,0xe0,0x30,0xe7,
+0x04,0x78,0x96,0x76,0x01,0x78,0x96,0xe6,0xfd,0x78,0x95,0xe6,0xfc,0x12,0x0d,0x2f,
+0xc2,0x03,0x30,0x00,0x07,0x78,0x95,0xe6,0xfc,0x12,0x13,0xec,0x7c,0x00,0x12,0x25,
+0xbf,0x12,0x31,0x69,0x22,0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x44,0x01,0xf0,0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xe0,0x30,0xe0,0x02,0x80,0xed,0x78,0xa9,0xe6,0x24,0x0b,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0xf8,0xf0,0x78,0xa9,0xe6,0x24,0x02,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x44,0x80,0xf0,0x22,0xc2,0x03,0x8c,0x58,
+0x12,0x0f,0x69,0x78,0xa6,0x86,0x83,0x08,0x86,0x82,0x79,0x5d,0x7a,0x35,0x7b,0x0a,
+0x78,0x01,0x12,0x03,0xf5,0x12,0x0e,0x05,0xac,0x58,0x7d,0x02,0x12,0x0d,0x2f,0xc2,
+0x03,0xac,0x58,0x12,0x11,0x07,0x22,0x8d,0x53,0x8e,0x52,0x8f,0x51,0x8c,0x50,0x12,
+0x0f,0x69,0x75,0x4f,0x00,0x78,0xa9,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x20,0xe4,0x1f,0xe5,0x4f,0x24,0xf6,0x40,0x19,0x05,0x4f,0xc2,0x03,
+0x7c,0x18,0x12,0x32,0xa9,0x90,0xff,0x93,0xe0,0x44,0x01,0xf0,0xb2,0xb3,0xac,0x50,
+0x12,0x0f,0x69,0x80,0xd0,0x78,0xa9,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x20,0xe4,0x05,0xc2,0x03,0x7c,0x02,0x22,0x78,0xa9,0xe6,0x24,0x05,
+0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0x0f,0x60,0x16,0x78,0xa9,0xe6,
+0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0x0f,0xf0,0xc2,0x03,
+0x7c,0x01,0x22,0x78,0xa8,0x86,0x83,0x08,0x86,0x82,0xe0,0xad,0x53,0xae,0x52,0xaf,
+0x51,0x12,0x03,0x0f,0xc2,0x03,0x7c,0x00,0x22,0x8d,0x31,0x8c,0x30,0x12,0x14,0xed,
+0xe5,0x31,0x60,0x0f,0xe5,0x30,0xb4,0x03,0x0a,0x7c,0x01,0x12,0x24,0xee,0x7c,0x81,
+0x12,0x24,0xee,0xac,0x30,0x12,0x0f,0x69,0xe5,0x31,0x60,0x1a,0x78,0xaa,0x86,0x83,
+0x08,0x86,0x82,0xe0,0x54,0xe7,0xf0,0xa3,0xa3,0xa3,0xa3,0xe0,0x54,0xe7,0xf0,0xac,
+0x30,0x7d,0x02,0x12,0x0d,0x2f,0x78,0xa6,0x86,0x83,0x08,0x86,0x82,0x79,0x67,0x7a,
+0x35,0x7b,0x0a,0x78,0x01,0x12,0x03,0xf5,0xc2,0x03,0xe5,0x30,0x24,0x9d,0xf8,0xc6,
+0x54,0xfd,0xf6,0xac,0x30,0x12,0x11,0x07,0x22,0x8c,0x26,0x30,0x03,0x05,0x12,0x32,
+0x48,0x80,0xf8,0x7c,0x0a,0x12,0x31,0x5b,0xd2,0x03,0xe5,0x26,0x24,0xfd,0x78,0xa3,
+0xf6,0x70,0x07,0x78,0xaa,0x76,0xff,0x08,0x76,0xe0,0x78,0xa3,0xe6,0x75,0xf0,0x10,
+0xa4,0xad,0xf0,0xfc,0x24,0xa0,0x78,0xa9,0xf6,0xed,0x34,0xff,0x18,0xf6,0x78,0xa3,
+0xe6,0x75,0xf0,0x0a,0xa4,0x24,0x00,0xfc,0xe4,0x34,0xfc,0xfd,0x78,0xa6,0xed,0xf6,
+0x08,0xec,0xf6,0x12,0x31,0xf4,0x22,0x78,0xa9,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xe0,0x30,0xe7,0x22,0x78,0xa9,0xe6,0x24,0x02,0xf5,0x82,0x18,
+0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0x7f,0xf0,0x78,0xa9,0xe6,0x24,0x02,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x44,0x80,0xf0,0x22,0x78,0xaa,0x86,0x83,0x08,
+0x86,0x82,0xe0,0x54,0x7f,0xf0,0xad,0x83,0xe5,0x82,0x24,0x04,0xfc,0xe4,0x3d,0x8c,
+0x82,0xf5,0x83,0xe0,0x54,0x7f,0xf0,0x78,0xa9,0xe6,0x24,0x0b,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xe0,0x54,0xf8,0xf0,0x78,0xab,0xe6,0x24,0x01,0xf5,0x82,0x18,
+0xe6,0x34,0x00,0xf5,0x83,0xe0,0x44,0x03,0xf0,0x78,0xab,0xe6,0x24,0x05,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x44,0x03,0xf0,0x78,0xa9,0xe6,0x24,0x05,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0x74,0x0f,0xf0,0x22,0x78,0xaa,0x86,0x83,0x08,
+0x86,0x82,0xe0,0x54,0x3f,0xf0,0xad,0x83,0xe5,0x82,0x24,0x04,0xfc,0xe4,0x3d,0x8c,
+0x82,0xf5,0x83,0xe0,0x54,0x3f,0xf0,0x78,0xa3,0xe6,0x24,0xa4,0xf8,0xe6,0xfc,0x78,
+0xab,0xe6,0x24,0x01,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x78,0xa3,
+0xe6,0x24,0xa4,0xf8,0xe6,0xfc,0x78,0xab,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xec,0xf0,0x78,0xa9,0xe6,0x24,0x0b,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x54,0xfb,0x44,0x02,0xf5,0x26,0x78,0xa7,0xe6,0x24,0x02,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x30,0xe5,0x03,0x43,0x26,0x01,0x78,0xa9,0xe6,
+0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x30,0xe0,0x03,0x12,0x0f,
+0xb7,0xe5,0x26,0xfc,0x78,0xa9,0xe6,0x24,0x0b,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xec,0xf0,0x78,0xa9,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,
+0x74,0x0f,0xf0,0x78,0xaa,0x86,0x83,0x08,0x86,0x82,0xe0,0x44,0x80,0xf0,0xa3,0xa3,
+0xa3,0xa3,0xe0,0x44,0x80,0xf0,0x22,0x8c,0x2a,0x12,0x0f,0x69,0x78,0xa7,0xe6,0x24,
+0x08,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xfc,0x78,0xa9,0xe6,0x24,0x0a,
+0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x78,0xa7,0xe6,0x24,0x07,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xfc,0x78,0xa9,0xe6,0x24,0x09,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x78,0xa6,0x86,0x83,0x08,0x86,0x82,0xe0,
+0xfd,0xa3,0xe0,0xfc,0xed,0xfe,0x78,0xa9,0xe6,0x24,0x08,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xee,0xf0,0xec,0xfe,0x78,0xa9,0xe6,0x24,0x07,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xee,0xf0,0x8c,0x29,0x8d,0x28,0xc3,0xec,0x94,0x05,0xed,0x94,
+0x0c,0x40,0x05,0x75,0x27,0x7c,0x80,0x33,0xd3,0xe5,0x29,0x94,0x01,0xe5,0x28,0x94,
+0x03,0x40,0x05,0x75,0x27,0x3c,0x80,0x23,0xd3,0xe5,0x29,0x94,0x81,0xe5,0x28,0x94,
+0x01,0x40,0x05,0x75,0x27,0x18,0x80,0x13,0xd3,0xe5,0x29,0x94,0x60,0xe5,0x28,0x94,
+0x00,0x40,0x05,0x75,0x27,0x0c,0x80,0x03,0x75,0x27,0x08,0xaf,0x27,0xe4,0xef,0x54,
+0x7c,0x44,0x83,0xff,0x8f,0x27,0xe5,0x27,0xfc,0x78,0xab,0xe6,0x24,0x01,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0xe5,0x27,0xfc,0x78,0xab,0xe6,0x24,0x05,
+0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0xe5,0x27,0xfc,0x78,0xa3,0xe6,
+0x24,0xa4,0xf8,0xec,0xf6,0x78,0xa9,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0xf5,0x27,0x78,0xa7,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xa3,0xe0,0x30,0xe3,0x17,0x53,0x27,0xc7,0x78,0xa7,0xe6,0x24,0x05,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x90,0x35,0x58,0x93,0x42,0x27,0x53,0x27,
+0xfb,0x78,0xa7,0xe6,0x24,0x06,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x60,
+0x03,0x43,0x27,0x04,0x53,0x27,0xfc,0x78,0xa7,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xe0,0x42,0x27,0x43,0x27,0x80,0xe5,0x27,0xfc,0x78,0xa9,0xe6,
+0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x78,0xa9,0xe6,0x24,
+0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xf5,0x27,0x78,0xa7,0xe6,0x24,
+0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,0xe0,0x30,0xe1,0x05,0x53,0x27,
+0xdf,0x80,0x03,0x43,0x27,0x20,0x78,0xa7,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xe0,0x30,0xe4,0x05,0x53,0x27,0xef,0x80,0x03,0x43,0x27,0x10,0x78,
+0xa7,0xe6,0x24,0x09,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xb4,0x02,0x03,
+0x43,0x27,0x02,0xe5,0x27,0xfc,0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xec,0xf0,0x78,0xa9,0xe6,0x24,0x03,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0xf5,0x27,0x78,0xa7,0xe6,0x24,0x09,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x70,0x05,0x53,0x27,0x7f,0x80,0x03,0x43,0x27,0x80,0x78,0xa7,0xe6,
+0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,0xe0,0x30,0xe0,0x05,0x43,
+0x27,0x20,0x80,0x03,0x53,0x27,0xdf,0x78,0xa7,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xe0,0x30,0xe3,0x05,0x43,0x27,0x40,0x80,0x03,0x53,0x27,0xbf,
+0x78,0xa7,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x30,0xe0,
+0x05,0x43,0x27,0x10,0x80,0x03,0x53,0x27,0xef,0x78,0xa7,0xe6,0x24,0x02,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,0xe0,0x30,0xe4,0x05,0x43,0x27,0x08,0x80,0x03,
+0x53,0x27,0xf7,0x78,0xa7,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,
+0xa3,0xe0,0x30,0xe5,0x05,0x43,0x27,0x04,0x80,0x03,0x53,0x27,0xfb,0x78,0xa7,0xe6,
+0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,0xe0,0x30,0xe6,0x05,0x43,
+0x27,0x01,0x80,0x03,0x53,0x27,0xfe,0x78,0xa7,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xa3,0xe0,0x30,0xe7,0x05,0x43,0x27,0x02,0x80,0x03,0x53,0x27,
+0xfd,0xe5,0x27,0xfc,0x78,0xa9,0xe6,0x24,0x03,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xec,0xf0,0xc2,0x03,0x7c,0x00,0x22,0x8d,0x27,0x8c,0x26,0xed,0x54,0x03,0x14,
+0x60,0x03,0x7c,0x10,0x22,0xe5,0x27,0x54,0x7c,0x24,0xfc,0x40,0x03,0x7c,0x0b,0x22,
+0xe5,0x26,0x24,0x9d,0xf8,0xc6,0x44,0x02,0xf6,0x7c,0x00,0x22,0x8c,0x30,0x12,0x0f,
+0x69,0xe5,0x30,0x24,0x9d,0xf8,0xe6,0x20,0xe2,0x4f,0xac,0x30,0x7d,0x02,0x12,0x0d,
+0x2f,0xe5,0x30,0x24,0xfe,0x44,0x28,0xfc,0x78,0xaa,0x86,0x83,0x08,0x86,0x82,0xec,
+0xf0,0xaf,0x83,0xe5,0x82,0x24,0x04,0xfe,0xe4,0x3f,0xff,0xec,0x8e,0x82,0x8f,0x83,
+0xf0,0x7c,0x03,0x8c,0x2c,0xe5,0x2c,0xfc,0x78,0xab,0xe6,0x24,0x01,0xf5,0x82,0x18,
+0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0xe5,0x2c,0xfc,0x78,0xab,0xe6,0x24,0x05,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x75,0x2d,0x01,0x75,0x2f,0x48,0x75,
+0x2e,0xff,0xe5,0x30,0x24,0xfd,0xfc,0xe4,0x34,0xff,0xfd,0xec,0x7c,0x03,0x25,0xe0,
+0xcd,0x33,0xcd,0xdc,0xf9,0xfc,0xe5,0x2f,0x2c,0xf5,0x2f,0xe5,0x2e,0x3d,0xf5,0x2e,
+0x78,0xab,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0xe7,
+0xf5,0x2c,0xad,0x2f,0xae,0x2e,0xaf,0x2d,0xe4,0x90,0x00,0x02,0x12,0x03,0x17,0xe4,
+0x90,0x00,0x06,0x12,0x03,0x17,0x12,0x01,0xe6,0x30,0xe5,0x03,0x43,0x2c,0x10,0xe5,
+0x2c,0xfc,0x78,0xab,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,
+0xf0,0x12,0x10,0x4b,0x78,0xa9,0xe6,0x24,0x06,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xe0,0xc2,0x03,0xfc,0xe5,0x30,0x24,0x9d,0xf8,0xc6,0x44,0x04,0xf6,0x8c,0x2c,
+0xe5,0x30,0x54,0x0f,0xc4,0x54,0xf0,0x7e,0x00,0xff,0xee,0xef,0x44,0x04,0x7d,0x00,
+0xff,0xec,0x4e,0xfc,0xed,0x4f,0xfd,0x12,0x1c,0xa7,0x7c,0x00,0x22,0x8c,0x2f,0x12,
+0x0f,0x69,0x12,0x0f,0xeb,0x78,0xaa,0x86,0x83,0x08,0x86,0x82,0xe0,0x54,0x08,0xf0,
+0xa3,0xa3,0xa3,0xa3,0xe0,0x54,0x08,0xf0,0xac,0x2f,0x7d,0x02,0x12,0x0d,0x2f,0xc2,
+0x03,0xe5,0x2f,0x24,0x9d,0xf8,0xc6,0x54,0xfb,0xf6,0x7c,0x00,0x22,0x12,0x30,0xe6,
+0x78,0x96,0xec,0xf6,0xec,0x24,0x9d,0xf8,0xe6,0x30,0xe1,0x0a,0x7d,0x00,0x7c,0x13,
+0x12,0x25,0x26,0x12,0x31,0x69,0x78,0x96,0xe6,0x24,0x9d,0xf8,0xc6,0x44,0x01,0xf6,
+0x78,0x96,0xe6,0xfc,0x12,0x0f,0x69,0x78,0x96,0xe6,0x24,0xfd,0x75,0xf0,0x0a,0xa4,
+0x24,0x14,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0x78,0xa6,0xe6,0xfa,0x08,0xe6,0xf9,
+0x7b,0x0a,0x78,0x01,0x12,0x03,0xa7,0x78,0xa6,0x86,0x83,0x08,0x86,0x82,0x79,0x67,
+0x7a,0x35,0x7b,0x0a,0x78,0x01,0x12,0x03,0xf5,0x12,0x0f,0xb7,0xc2,0x03,0x78,0x96,
+0xe6,0xfc,0x12,0x11,0x07,0x78,0x95,0xec,0xf6,0xec,0x60,0x0a,0x7d,0x00,0x7c,0x08,
+0x12,0x25,0x26,0x12,0x31,0x69,0x78,0x96,0xe6,0xfc,0x12,0x0f,0x69,0x78,0xa9,0xe6,
+0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x44,0x10,0x54,0xdf,0xfc,
+0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x78,
+0x95,0xec,0xf6,0xc2,0x03,0x7c,0xc8,0x12,0x32,0xa9,0x78,0x96,0xe6,0xfc,0x12,0x0f,
+0x69,0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,
+0xef,0xf0,0xc2,0x03,0x7c,0xc8,0x12,0x32,0xa9,0x78,0x96,0xe6,0xfc,0x12,0x0f,0x69,
+0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x44,0x10,
+0xf0,0xc2,0x03,0x7c,0xc8,0x12,0x32,0xa9,0x78,0x96,0xe6,0xfc,0x12,0x0f,0x69,0x78,
+0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x44,0x20,0xf0,
+0xc2,0x03,0x7c,0xf0,0x12,0x32,0xa9,0x78,0x96,0xe6,0xfc,0x12,0x0f,0x69,0x78,0xa9,
+0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x30,0xe4,0x15,0xc2,
+0x03,0x78,0x96,0xe6,0x44,0x10,0x7f,0x00,0xfe,0x7c,0x07,0x12,0x31,0xfb,0x12,0x31,
+0x69,0x02,0x17,0x14,0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xe0,0x54,0xcf,0xf0,0xc2,0x03,0x7c,0xc8,0x12,0x32,0xa9,0x78,0x96,0xe6,0xfc,
+0x12,0x0f,0x69,0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,
+0xe0,0x44,0x30,0xf0,0xc2,0x03,0x7c,0xf0,0x12,0x32,0xa9,0x78,0x96,0xe6,0xfc,0x12,
+0x0f,0x69,0x78,0xa9,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,
+0x30,0xe4,0x14,0xc2,0x03,0x78,0x96,0xe6,0x44,0x10,0x7f,0x00,0xfe,0x7c,0x07,0x12,
+0x31,0xfb,0x12,0x31,0x69,0x80,0x5d,0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xe0,0x54,0xef,0xf0,0x78,0xa9,0xe6,0x24,0x04,0xf5,0x82,0x18,
+0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0xdf,0xf0,0x78,0x96,0xe6,0x24,0xfd,0x75,0xf0,
+0x0a,0xa4,0x24,0x14,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xac,0x82,0xad,0x83,0x78,
+0xa6,0x86,0x83,0x08,0x86,0x82,0xec,0xf9,0xed,0xfa,0x7b,0x0a,0x78,0x01,0x12,0x03,
+0xa7,0xc2,0x03,0x78,0x96,0xe6,0xfc,0x12,0x11,0x07,0x7d,0x00,0x7c,0x0b,0x12,0x25,
+0x26,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,0xe4,0x90,0xfc,0x39,0xf0,0x7d,0x02,0x7c,
+0x00,0x12,0x25,0x26,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,0x7c,0x00,0x12,0x25,0xbf,
+0x12,0x31,0x69,0x22,0x74,0x3c,0x90,0xfb,0xe0,0xf0,0x74,0x3e,0x90,0xfb,0xe0,0xf0,
+0xe4,0x90,0xfc,0x28,0xf0,0x22,0x8d,0x35,0x8c,0x34,0xec,0xb4,0x01,0x02,0x80,0x03,
+0xd3,0x40,0x02,0x80,0x28,0xb4,0x02,0x02,0x80,0x03,0xd3,0x40,0x08,0xa8,0x35,0xc6,
+0x25,0xe0,0xf6,0x80,0x18,0xb4,0x04,0x02,0x80,0x03,0xd3,0x40,0x0a,0xa8,0x35,0xc6,
+0x25,0xe0,0x25,0xe0,0xf6,0x80,0x06,0xa8,0x35,0x76,0x00,0x80,0x00,0x22,0x8c,0x3c,
+0x8d,0x3b,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x75,0x66,0x06,0x75,0x67,0x00,0x90,0xfc,
+0x29,0x12,0x04,0x6e,0x12,0x01,0xe6,0xb4,0x80,0x02,0x80,0x06,0xd3,0x50,0x03,0x02,
+0x18,0x47,0x90,0xfc,0x29,0x12,0x04,0x80,0x90,0x00,0x03,0x12,0x01,0xec,0x54,0xf0,
+0xb4,0x30,0x02,0x80,0x03,0xd3,0x40,0x5f,0x90,0xfc,0x29,0x12,0x04,0x80,0x90,0x00,
+0x08,0x12,0x02,0x0e,0xfa,0xfd,0xeb,0xfe,0x7f,0x01,0x90,0xfc,0x2c,0x12,0x04,0x6e,
+0xee,0xcd,0x90,0x35,0x71,0xfc,0xe4,0x93,0xff,0x74,0x01,0x93,0xfe,0xf9,0xef,0xfa,
+0x7b,0x01,0xea,0xff,0xe9,0xfe,0xec,0xc3,0x9e,0xed,0x9f,0x40,0x25,0x90,0x35,0x73,
+0xe4,0x93,0xfd,0x74,0x01,0x93,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0xee,0xcd,0xfc,
+0x90,0xfc,0x2e,0xe0,0xd3,0x9c,0x90,0xfc,0x2d,0xe0,0x9d,0x50,0x05,0x75,0x66,0x80,
+0x80,0x33,0x12,0x19,0x65,0x80,0x2e,0xb4,0x60,0x02,0x80,0x03,0xd3,0x40,0x0b,0xac,
+0x3c,0xad,0x3b,0x12,0x07,0x77,0x8c,0x66,0x80,0x1b,0xb4,0x10,0x03,0xb3,0x40,0x10,
+0xc3,0xb4,0x20,0x03,0xb3,0x40,0x09,0xc3,0xb4,0x40,0x02,0x80,0x03,0xd3,0x40,0x00,
+0x75,0x66,0x81,0x80,0x00,0x80,0x75,0xb4,0x81,0x02,0x80,0x03,0xd3,0x40,0x6b,0x90,
+0xfc,0x29,0x12,0x04,0x80,0x90,0x00,0x03,0x12,0x01,0xec,0x54,0xf0,0xb4,0x30,0x02,
+0x80,0x03,0xd3,0x40,0x1d,0x90,0xfc,0x29,0x12,0x04,0x80,0x90,0x00,0x08,0x12,0x02,
+0x0e,0xfa,0xfd,0xeb,0xfe,0x7f,0x01,0x90,0xfc,0x2f,0x12,0x04,0x6e,0x12,0x18,0xcf,
+0x80,0x36,0xb4,0x60,0x02,0x80,0x03,0xd3,0x40,0x13,0x75,0x3a,0x67,0xe4,0xf5,0x39,
+0xf5,0x38,0xac,0x3c,0xad,0x3b,0x12,0x05,0xd3,0x8c,0x66,0x80,0x1b,0xb4,0x10,0x03,
+0xb3,0x40,0x10,0xc3,0xb4,0x20,0x03,0xb3,0x40,0x09,0xc3,0xb4,0x40,0x02,0x80,0x03,
+0xd3,0x40,0x00,0x75,0x66,0x81,0x80,0x00,0x80,0x02,0x80,0x00,0xe5,0x66,0xfc,0x90,
+0xfc,0x29,0x12,0x04,0x80,0xec,0x90,0x00,0x02,0x12,0x03,0x17,0xac,0x67,0x22,0x90,
+0xfc,0x29,0x12,0x04,0x80,0x90,0x00,0x04,0x12,0x01,0xec,0x60,0x04,0x74,0x01,0x80,
+0x01,0xe4,0xa2,0xe0,0x92,0x01,0x90,0xfc,0x29,0x12,0x04,0x80,0xed,0x24,0x03,0xfd,
+0x50,0x01,0x0e,0x90,0xfc,0x2c,0x12,0x04,0x6e,0x90,0xfc,0x29,0x12,0x04,0x80,0x90,
+0x00,0x05,0x12,0x01,0xec,0xf5,0x67,0x90,0x00,0x04,0x12,0x01,0xec,0x54,0x0f,0xfc,
+0x7d,0x67,0x12,0x17,0x46,0xe5,0x67,0x70,0x04,0x75,0x66,0x08,0x22,0x75,0x66,0x00,
+0x78,0x84,0x76,0x00,0x78,0x84,0xe6,0xc3,0x95,0x67,0x50,0x38,0x90,0xfc,0x2f,0x12,
+0x04,0x80,0x12,0x01,0xe6,0xfc,0x90,0xfc,0x2c,0x12,0x04,0x80,0xec,0x12,0x03,0x0f,
+0x30,0x01,0x0e,0x90,0xfc,0x31,0xe0,0x04,0xf0,0x90,0xfc,0x30,0x70,0x03,0xe0,0x04,
+0xf0,0x78,0x84,0x06,0x90,0xfc,0x2e,0xe0,0x04,0xf0,0x90,0xfc,0x2d,0x70,0x03,0xe0,
+0x04,0xf0,0x80,0xc0,0x22,0x90,0xfc,0x2a,0xe0,0xfd,0xa3,0xe0,0xfc,0xed,0xfe,0xec,
+0xfd,0x7f,0x01,0xed,0x24,0x0a,0xfd,0x50,0x01,0x0e,0x90,0xfc,0x32,0x12,0x04,0x6e,
+0x90,0xfc,0x29,0x12,0x04,0x80,0x90,0x00,0x04,0x12,0x01,0xec,0x54,0x0f,0xb4,0x01,
+0x02,0x80,0x03,0xd3,0x40,0x17,0x90,0xfc,0x32,0x12,0x04,0x80,0x0d,0xed,0x70,0x01,
+0x0e,0x90,0xfc,0x2f,0x12,0x04,0x6e,0x78,0x88,0x76,0x01,0x80,0x4e,0xb4,0x02,0x02,
+0x80,0x03,0xd3,0x40,0x19,0x90,0xfc,0x32,0x12,0x04,0x80,0xed,0x24,0x02,0xfd,0x50,
+0x01,0x0e,0x90,0xfc,0x2f,0x12,0x04,0x6e,0x78,0x88,0x76,0x02,0x80,0x2d,0xb4,0x04,
+0x02,0x80,0x03,0xd3,0x40,0x19,0x90,0xfc,0x32,0x12,0x04,0x80,0xed,0x24,0x04,0xfd,
+0x50,0x01,0x0e,0x90,0xfc,0x2f,0x12,0x04,0x6e,0x78,0x88,0x76,0x04,0x80,0x0c,0xb4,
+0x00,0x02,0x80,0x03,0xd3,0x40,0x00,0x75,0x66,0x08,0x22,0x90,0xfc,0x29,0x12,0x04,
+0x80,0x90,0x00,0x05,0x12,0x01,0xec,0xf5,0x67,0x78,0x85,0x76,0x00,0x78,0x85,0xe6,
+0xc3,0x95,0x67,0x40,0x03,0x02,0x1a,0xcd,0x78,0x86,0x76,0x00,0x78,0x86,0xe6,0xc3,
+0x78,0x88,0x96,0x50,0x76,0x90,0xfc,0x2c,0x12,0x04,0x80,0x12,0x01,0xe6,0xfc,0x90,
+0xfc,0x32,0x12,0x04,0x89,0x12,0x01,0xe0,0xf4,0x5c,0xfc,0x12,0x01,0xe0,0xf8,0x90,
+0xfc,0x2f,0x12,0x04,0x80,0xe8,0xc0,0xe0,0x12,0x01,0xe6,0xc8,0xd0,0xe0,0xc8,0x58,
+0x4c,0xfc,0x90,0xfc,0x2c,0x12,0x04,0x80,0xec,0x12,0x03,0x0f,0x78,0x87,0xec,0xf6,
+0x90,0xfc,0x31,0xe0,0x04,0xf0,0x90,0xfc,0x30,0x70,0x03,0xe0,0x04,0xf0,0x09,0xe9,
+0x70,0x01,0x0a,0x90,0xfc,0x32,0x12,0x04,0x77,0x90,0xfc,0x29,0x12,0x04,0x80,0x90,
+0x00,0x04,0x12,0x01,0xec,0x30,0xe4,0x0e,0x90,0xfc,0x2e,0xe0,0x04,0xf0,0x90,0xfc,
+0x2d,0x70,0x03,0xe0,0x04,0xf0,0x78,0x86,0x06,0x80,0x81,0x78,0x88,0xe6,0xfd,0xe4,
+0xfe,0xff,0xee,0xcd,0xfc,0x90,0xfc,0x31,0xe0,0x2c,0xf0,0x90,0xfc,0x30,0xe0,0x3d,
+0xf0,0x78,0x88,0xe6,0xfd,0xe4,0xfe,0xff,0xee,0xcd,0xfc,0x90,0xfc,0x34,0xe0,0x2c,
+0xf0,0x90,0xfc,0x33,0xe0,0x3d,0xf0,0x78,0x85,0x06,0x02,0x1a,0x0d,0x75,0x66,0x00,
+0x22,0xe5,0x3d,0x05,0x3d,0x04,0x70,0x02,0xb2,0xb0,0x22,0xc0,0xe0,0xc0,0xf0,0xc0,
+0x82,0xc0,0x83,0xc0,0xd0,0xe8,0xc0,0xe0,0xe9,0xc0,0xe0,0xea,0xc0,0xe0,0xeb,0xc0,
+0xe0,0xec,0xc0,0xe0,0xed,0xc0,0xe0,0xee,0xc0,0xe0,0xef,0xc0,0xe0,0x90,0xff,0x92,
+0xe0,0x12,0x01,0xb7,0x1b,0x29,0x30,0x1b,0x29,0x32,0x1b,0x38,0x38,0x1b,0x4a,0x3a,
+0x1b,0x5c,0x3e,0x1b,0x74,0x44,0x1b,0x68,0x46,0x1b,0x80,0x50,0x1b,0xc2,0x52,0x1b,
+0xa1,0x54,0x1b,0xe3,0x56,0x00,0x00,0x1c,0x04,0x90,0xff,0x92,0xe0,0x7f,0x00,0xfe,
+0x7c,0x01,0x12,0x31,0xfb,0x02,0x1c,0x14,0xe4,0xff,0x04,0xfe,0x7c,0x03,0x12,0x31,
+0xfb,0x74,0x20,0x90,0xff,0xfe,0xf0,0x02,0x1c,0x14,0xe4,0xff,0x04,0xfe,0x7c,0x02,
+0x12,0x31,0xfb,0x74,0x40,0x90,0xff,0xfe,0xf0,0x02,0x1c,0x14,0xe4,0xff,0x04,0xfe,
+0x7c,0x04,0x12,0x31,0xfb,0x02,0x1c,0x14,0xe4,0xff,0x04,0xfe,0x7c,0x05,0x12,0x31,
+0xfb,0x02,0x1c,0x14,0xe4,0xff,0x04,0xfe,0x7c,0x06,0x12,0x31,0xfb,0x02,0x1c,0x14,
+0x90,0xff,0xa5,0xe0,0x7d,0x00,0x90,0xfb,0xf8,0xcd,0xf0,0xa3,0xcd,0xf0,0x90,0xfb,
+0xf9,0xe0,0xfc,0xf5,0x83,0x90,0xfb,0xf8,0xe0,0x44,0x33,0xfd,0x12,0x1c,0xa7,0x80,
+0x73,0x90,0xff,0xb5,0xe0,0x7d,0x00,0x90,0xfb,0xfa,0xcd,0xf0,0xa3,0xcd,0xf0,0x90,
+0xfb,0xfb,0xe0,0xfc,0xf5,0x83,0x90,0xfb,0xfa,0xe0,0x44,0x43,0xfd,0x12,0x1c,0xa7,
+0x80,0x52,0x90,0xff,0xa6,0xe0,0x7d,0x00,0x90,0xfb,0xfc,0xcd,0xf0,0xa3,0xcd,0xf0,
+0x90,0xfb,0xfd,0xe0,0xfc,0xf5,0x83,0x90,0xfb,0xfc,0xe0,0x44,0x34,0xfd,0x12,0x1c,
+0xa7,0x80,0x31,0x90,0xff,0xb6,0xe0,0x7d,0x00,0x90,0xfb,0xfe,0xcd,0xf0,0xa3,0xcd,
+0xf0,0x90,0xfb,0xff,0xe0,0xfc,0xf5,0x83,0x90,0xfb,0xfe,0xe0,0x44,0x44,0xfd,0x12,
+0x1c,0xa7,0x80,0x10,0x90,0xff,0x92,0xe0,0x7d,0x00,0xfc,0xed,0x44,0xaa,0xfd,0x12,
+0x1c,0xa7,0x80,0x00,0xe4,0x90,0xff,0x92,0xf0,0xd0,0xe0,0xff,0xd0,0xe0,0xfe,0xd0,
+0xe0,0xfd,0xd0,0xe0,0xfc,0xd0,0xe0,0xfb,0xd0,0xe0,0xfa,0xd0,0xe0,0xf9,0xd0,0xe0,
+0xf8,0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0xd0,0xe0,0x32,0x05,0x81,0x05,0x81,
+0x05,0x81,0x05,0x81,0xa8,0x81,0x18,0x18,0x18,0xed,0xf6,0x08,0xec,0xf6,0x90,0xff,
+0x5a,0xe0,0x20,0xe7,0x02,0x80,0xf7,0x90,0xff,0x59,0xe0,0x7d,0x00,0xa8,0x81,0x18,
+0xcd,0xf6,0xcd,0x08,0xf6,0x7d,0x03,0xa8,0x81,0xe6,0x18,0xfc,0xe6,0xcc,0x25,0xe0,
+0xcc,0x33,0xcc,0xdd,0xf9,0xcc,0xf6,0xcc,0x08,0xf6,0xa8,0x81,0x18,0xe6,0x44,0xf8,
+0xf6,0xa8,0x81,0x18,0x18,0x18,0xe6,0xfd,0x08,0xe6,0xfc,0xa8,0x81,0x18,0x86,0x83,
+0x08,0x86,0x82,0xed,0xf0,0xa3,0xec,0xf0,0x74,0x02,0x90,0xff,0x5a,0xf0,0x15,0x81,
+0x15,0x81,0x15,0x81,0x15,0x81,0x22,0xe5,0x81,0x24,0x05,0xf5,0x81,0xe4,0xa8,0x81,
+0x18,0xf6,0xa8,0x81,0x18,0x18,0x18,0x18,0xed,0xf6,0x08,0xec,0xf6,0x90,0xfb,0xf5,
+0xe0,0x24,0xf8,0x50,0x03,0x02,0x1d,0xc8,0xe4,0xa8,0x81,0x18,0x18,0xf6,0xa8,0x81,
+0x18,0xe6,0xfe,0xa8,0x81,0x18,0x18,0x18,0x18,0xe6,0xfd,0x08,0xe6,0xfc,0x7f,0x00,
+0xef,0x24,0xf8,0x40,0x4d,0xe4,0xef,0x25,0xe0,0x24,0x7d,0xf5,0x82,0xe4,0x34,0xfc,
+0xf5,0x83,0xe0,0xfb,0xa3,0xe0,0x6c,0x70,0x03,0xfa,0xeb,0x6d,0x70,0x09,0x74,0x01,
+0xa8,0x81,0x18,0x18,0xf6,0x80,0x2b,0xe4,0xef,0x25,0xe0,0x24,0x7d,0xf5,0x82,0xe4,
+0x34,0xfc,0xf5,0x83,0x7a,0x00,0xe0,0x54,0xf0,0xcc,0xf8,0xcc,0xcd,0xf9,0xcd,0xfb,
+0x78,0x00,0xe9,0x54,0xf0,0xf9,0xea,0x68,0x70,0x02,0xeb,0x69,0x70,0x01,0x0e,0x0f,
+0x80,0xae,0xa8,0x81,0x18,0xee,0xf6,0xa8,0x81,0x18,0x18,0x18,0x18,0xed,0xf6,0x08,
+0xec,0xf6,0xa8,0x81,0xef,0xf6,0xa8,0x81,0x18,0x18,0xe6,0x70,0x79,0xa8,0x81,0x18,
+0xe6,0x24,0xf7,0x40,0x71,0xa8,0x81,0x18,0x18,0x18,0x18,0xe6,0x54,0x0f,0xa8,0x81,
+0xf6,0x64,0x04,0x60,0x17,0xa8,0x81,0xe6,0x64,0x03,0x60,0x10,0xa8,0x81,0x18,0x18,
+0x18,0x18,0xe6,0xfd,0x08,0xe6,0xfc,0x12,0x1c,0x3c,0x80,0x4a,0x7c,0x0a,0x12,0x31,
+0x5b,0xa8,0x81,0x18,0x18,0x18,0x18,0xe6,0xfd,0x08,0xe6,0xfc,0x90,0xfb,0xf4,0xe0,
+0x25,0xe0,0x24,0x7d,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xed,0xf0,0xa3,0xec,0xf0,
+0x90,0xfb,0xf4,0xe0,0xff,0xe4,0xef,0x04,0x54,0x07,0xff,0x90,0xfb,0xf4,0xf0,0x90,
+0xfb,0xf5,0xe0,0x04,0xf0,0x12,0x31,0xf4,0x90,0xfb,0xf6,0xe0,0x70,0x08,0xe4,0xfe,
+0xff,0x7c,0x0f,0x12,0x31,0xfb,0x80,0x27,0x90,0xfb,0xf7,0xe0,0x04,0xf0,0x54,0x3f,
+0x70,0x1d,0x90,0xfb,0xf7,0xe0,0x44,0xfe,0x7d,0x00,0xfc,0x90,0xfb,0xf4,0xe0,0x25,
+0xe0,0x24,0x7d,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xed,0xf0,0xa3,0xec,0xf0,0xe5,
+0x81,0x24,0xfb,0xf5,0x81,0x22,0x78,0x8b,0x76,0x00,0x78,0x8c,0x76,0x00,0x74,0x01,
+0x90,0xfb,0xf6,0xf0,0x12,0x30,0xe6,0x90,0xfb,0xf5,0xe0,0x60,0x57,0x7c,0x0a,0x12,
+0x31,0x5b,0x90,0xfb,0xf3,0xe0,0x25,0xe0,0x24,0x7d,0xf5,0x82,0xe4,0x34,0xfc,0xf5,
+0x83,0xe0,0xfd,0xa3,0xe0,0xfc,0x90,0xfb,0xf3,0xe0,0x25,0xe0,0x24,0x7d,0xf5,0x82,
+0xe4,0x34,0xfc,0xf5,0x83,0xe4,0xf0,0xa3,0xf0,0x90,0xfb,0xf3,0xe0,0xff,0xe4,0xef,
+0x04,0x54,0x07,0xff,0x90,0xfb,0xf3,0xf0,0x90,0xfb,0xf5,0xe0,0x14,0xf0,0x78,0x89,
+0xed,0xf6,0x08,0xec,0xf6,0x12,0x31,0xf4,0x78,0x89,0xe6,0xfd,0x08,0xe6,0xfc,0x12,
+0x08,0xda,0x80,0xa3,0x12,0x32,0x48,0x90,0xff,0x93,0xe0,0x44,0x01,0xf0,0xb2,0xb3,
+0x78,0x8b,0x06,0xb6,0x00,0x11,0x78,0x8b,0x76,0x00,0x78,0x8c,0xe6,0xf4,0x04,0x04,
+0xa2,0xe0,0x92,0xb4,0x78,0x8c,0xf6,0x02,0x1e,0x07,0xe4,0x90,0xfb,0xf6,0xf0,0x90,
+0xfb,0xf5,0xe0,0x7d,0x00,0xfc,0xed,0x44,0xcf,0xfd,0x12,0x1c,0x3c,0x12,0x31,0x69,
+0x22,0x12,0x30,0xe6,0xe5,0x70,0x64,0x49,0x45,0x6f,0x60,0x15,0x90,0xff,0x83,0xe0,
+0x54,0x0f,0x7d,0x00,0xd3,0x95,0x70,0xed,0x95,0x6f,0x50,0x05,0x12,0x2f,0x2f,0x80,
+0x03,0x12,0x2f,0xff,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,0xe5,0x70,0x64,0x49,0x45,
+0x6f,0x60,0x05,0x12,0x30,0x39,0x80,0x0e,0x90,0xff,0x80,0xe0,0x44,0x08,0xf0,0x90,
+0xff,0x83,0xe0,0x54,0x7f,0xf0,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,0x8c,0x54,0xec,
+0x54,0xf0,0xb4,0x10,0x15,0x75,0x6a,0x35,0x75,0x69,0xfc,0x75,0x68,0x01,0xe5,0x6a,
+0x24,0x03,0xf5,0x6a,0xe5,0x69,0x34,0x00,0xf5,0x69,0xe4,0xf5,0x57,0xf5,0x56,0xe5,
+0x56,0xc3,0x94,0x01,0x50,0x27,0xe5,0x54,0x54,0x0f,0xfc,0xad,0x6a,0xae,0x69,0xaf,
+0x68,0x12,0x0e,0x77,0x8c,0x55,0xec,0x60,0x02,0x80,0x12,0x05,0x6a,0xe5,0x6a,0x70,
+0x02,0x05,0x69,0x05,0x57,0xe5,0x57,0x70,0x02,0x05,0x56,0x80,0xd2,0xe5,0x54,0x54,
+0x0f,0x24,0x9d,0xf8,0xc6,0x54,0xfe,0xf6,0xe5,0x54,0x54,0x0f,0x7f,0x00,0xfe,0x7c,
+0x12,0x12,0x31,0xfb,0xe5,0x55,0x14,0x70,0x09,0x7d,0x00,0x7c,0x09,0x12,0x25,0x26,
+0x80,0x07,0xad,0x57,0x7c,0x00,0x12,0x25,0x26,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,
+0x90,0xff,0xfc,0xe0,0x44,0x02,0xf0,0x90,0xff,0x00,0xe0,0x30,0xe7,0x13,0x90,0xff,
+0x83,0xe0,0x44,0x80,0xf0,0x43,0x6d,0x80,0x90,0xff,0xfc,0xe0,0x44,0x01,0xf0,0x80,
+0x11,0x90,0xff,0x82,0xe0,0x44,0x08,0xf0,0x53,0x6d,0x7f,0x90,0xff,0xfc,0xe0,0x54,
+0xfe,0xf0,0x90,0xff,0x81,0xe0,0x44,0x80,0xf0,0x12,0x25,0xd9,0x90,0xff,0xfe,0xe0,
+0x44,0x05,0xf0,0x90,0xff,0xfc,0xe0,0x54,0xfd,0xf0,0x12,0x31,0x69,0x22,0x12,0x30,
+0xe6,0x7c,0x01,0x12,0x32,0xa9,0x78,0xad,0xe6,0x44,0x02,0xf6,0x74,0xfe,0xfc,0x04,
+0xfd,0x12,0x1c,0xa7,0x90,0xff,0x5a,0xe0,0x30,0xe7,0x02,0x80,0xf7,0xe4,0xf5,0x4e,
+0x75,0x4d,0x10,0xac,0x4e,0xad,0x4d,0xe5,0x4e,0x15,0x4e,0x70,0x02,0x15,0x4d,0xec,
+0x4d,0x60,0x02,0x80,0xee,0x43,0x87,0x01,0x12,0x31,0x69,0x22,0x12,0x30,0xe6,0x7c,
+0x02,0x12,0x31,0x75,0x78,0xad,0xe6,0x54,0xfd,0xf6,0x12,0x31,0x69,0x22,0x12,0x30,
+0xe6,0x78,0xad,0xe6,0x30,0xe0,0x2c,0x78,0xad,0xe6,0x30,0xe1,0x26,0x78,0xad,0xe6,
+0xfc,0xf5,0x83,0x18,0xe6,0x44,0xf0,0xfd,0x12,0x1c,0x3c,0x90,0xff,0xfc,0xe0,0x44,
+0x20,0xf0,0x7c,0x02,0x12,0x32,0xa9,0x78,0xad,0xe6,0x54,0xfd,0xf6,0x74,0x1a,0x90,
+0xff,0xfe,0xf0,0x78,0xad,0xe6,0xfc,0xf5,0x83,0x18,0xe6,0x44,0xf1,0xfd,0x12,0x1c,
+0x3c,0x12,0x31,0x69,0x22,0x75,0x6d,0x00,0x90,0xff,0xff,0xe0,0x60,0x03,0x43,0x6d,
+0x01,0x75,0x6e,0x00,0xe4,0xf5,0x6c,0xf5,0x6b,0xe4,0xf5,0x6f,0x75,0x70,0x49,0x74,
+0x84,0x90,0xff,0x82,0xf0,0x74,0x84,0x90,0xff,0x80,0xf0,0x74,0x80,0x90,0xff,0x58,
+0xf0,0x74,0x80,0x90,0xff,0x5a,0xf0,0xad,0x46,0xaf,0x45,0x7e,0x00,0xee,0x24,0xfe,
+0x50,0x03,0x02,0x21,0x24,0xe4,0xee,0x75,0xf0,0x07,0xa4,0x24,0x7f,0xf5,0x82,0xe4,
+0x34,0xf8,0xf5,0x83,0xe0,0xff,0xe4,0xef,0x54,0x80,0xfd,0xe4,0xef,0x54,0x0f,0x14,
+0xff,0xed,0x60,0x38,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,0x34,
+0xff,0xf5,0x83,0x74,0x90,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x4a,0xf5,0x82,
+0xe4,0x34,0xff,0xf5,0x83,0x74,0x80,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x4e,
+0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0x74,0x80,0xf0,0x80,0x34,0xe4,0xef,0x75,0xf0,
+0x08,0xa4,0x24,0x08,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0x74,0x90,0xf0,0xe4,0xef,
+0x75,0xf0,0x08,0xa4,0x24,0x0a,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0xe4,
+0xef,0x75,0xf0,0x08,0xa4,0x24,0x0e,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,
+0x0e,0x02,0x20,0x8d,0x8d,0x46,0x8e,0x44,0x8f,0x45,0x74,0x7f,0x90,0xff,0xfd,0xf0,
+0x74,0x90,0x90,0xff,0xfc,0xf0,0x22,0x8c,0x58,0xec,0x24,0xf6,0x50,0x06,0xe5,0x58,
+0x24,0x37,0xfc,0x22,0xe5,0x58,0x24,0x30,0xfc,0x22,0x12,0x25,0x23,0xec,0x70,0x03,
+0x02,0x22,0x5e,0x75,0x5c,0x03,0xae,0x5b,0x7f,0x00,0xe5,0x5c,0x15,0x5c,0x64,0x80,
+0x24,0x7f,0x50,0x35,0xef,0x24,0x00,0xf5,0x82,0xe4,0x34,0xfb,0xf5,0x83,0xe0,0xfe,
+0x24,0xfe,0x50,0x1e,0xef,0x7d,0x00,0xfc,0xe4,0xfb,0x74,0x74,0xc3,0x9c,0xfa,0xeb,
+0x9d,0xfb,0xee,0x7d,0x00,0xfc,0xea,0xc3,0x9c,0xed,0x64,0x80,0xcb,0x64,0x80,0x9b,
+0x50,0x02,0x80,0x05,0xef,0x2e,0xff,0x80,0xc1,0x8e,0x5b,0x8f,0x5a,0xe5,0x5c,0x64,
+0x80,0x24,0x7f,0x50,0x03,0x02,0x22,0x5e,0xe5,0x5a,0x24,0x8e,0x50,0x03,0x02,0x22,
+0x5e,0x85,0x5a,0x5d,0x75,0x5b,0x00,0xae,0x5a,0xaf,0x5b,0x90,0x35,0x9c,0xe4,0x93,
+0xf5,0x5c,0xe5,0x5c,0x15,0x5c,0x64,0x80,0x24,0x7f,0x50,0x18,0xee,0x24,0x00,0xf5,
+0x82,0xe4,0x34,0xfb,0xf5,0x83,0xe0,0xfc,0xef,0x90,0x35,0x9c,0x93,0x6c,0x70,0x04,
+0x0e,0x0f,0x80,0xde,0x8e,0x5a,0x8f,0x5b,0xe5,0x5c,0x64,0x80,0x24,0x7f,0x40,0x6e,
+0x75,0x5e,0x01,0x75,0x60,0xe8,0x75,0x5f,0xff,0xe5,0x5d,0x24,0x02,0xf5,0x5a,0x75,
+0x5c,0x07,0xe5,0x5c,0x33,0x40,0x57,0xad,0x60,0xae,0x5f,0xaf,0x5e,0xe5,0x5c,0xf5,
+0x82,0x33,0x95,0xe0,0xf5,0x83,0x12,0x01,0xec,0xc4,0x54,0x0f,0xfc,0x12,0x21,0x37,
+0xe5,0x5a,0x24,0x00,0xf5,0x82,0xe4,0x34,0xfb,0xf5,0x83,0xec,0xf0,0x05,0x5a,0x05,
+0x5a,0xad,0x60,0xae,0x5f,0xaf,0x5e,0xe5,0x5c,0xf5,0x82,0x33,0x95,0xe0,0xf5,0x83,
+0x12,0x01,0xec,0x54,0x0f,0xfc,0x12,0x21,0x37,0xe5,0x5a,0x24,0x00,0xf5,0x82,0xe4,
+0x34,0xfb,0xf5,0x83,0xec,0xf0,0x05,0x5a,0x05,0x5a,0x15,0x5c,0x80,0xa4,0x74,0x02,
+0x90,0xf8,0x51,0xf0,0x90,0xf8,0x6b,0x79,0x75,0x7a,0x35,0x7b,0x27,0x78,0x01,0x12,
+0x03,0xf5,0x75,0x6a,0x35,0x75,0x69,0xfc,0x75,0x68,0x01,0xe4,0x90,0xff,0x83,0xf0,
+0x74,0x80,0x90,0xff,0x81,0xf0,0x75,0x59,0x02,0xe5,0x59,0x75,0xf0,0x07,0xa4,0x24,
+0x7f,0xf5,0x82,0xe4,0x34,0xf8,0xf5,0x83,0xe0,0x78,0x8f,0xf6,0xfc,0x54,0x0f,0x14,
+0xfc,0x78,0x8f,0xec,0xf6,0xe5,0x59,0x75,0xf0,0x07,0xa4,0x24,0x81,0xf5,0x82,0xe4,
+0x34,0xf8,0xf5,0x83,0xe0,0x78,0x92,0x76,0xfd,0x08,0x76,0xe8,0xfc,0x78,0x8f,0xe6,
+0x75,0xf0,0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0x78,
+0x8f,0xe6,0x75,0xf0,0x08,0xa4,0x24,0x4f,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xec,
+0xf0,0x78,0x92,0xe6,0xff,0x08,0xe6,0x7e,0x03,0xcf,0xc3,0x13,0xcf,0x13,0xde,0xf9,
+0xfe,0x78,0x8f,0xe6,0x75,0xf0,0x08,0xa4,0x24,0x49,0xf5,0x82,0xe4,0x34,0xff,0xf5,
+0x83,0xee,0xf0,0x78,0x8f,0xe6,0x75,0xf0,0x08,0xa4,0x24,0x4a,0xf5,0x82,0xe4,0x34,
+0xff,0xf5,0x83,0x74,0x80,0xf0,0x78,0x90,0xec,0xf6,0x7d,0x00,0x78,0x93,0xe6,0x2c,
+0xf6,0x18,0xe6,0x3d,0xf6,0x78,0x92,0xe6,0xfd,0x08,0xe6,0x7c,0x03,0xcd,0xc3,0x13,
+0xcd,0x13,0xdc,0xf9,0xfc,0x78,0x8f,0xe6,0x75,0xf0,0x08,0xa4,0x24,0x4d,0xf5,0x82,
+0xe4,0x34,0xff,0xf5,0x83,0xec,0xf0,0x78,0x8f,0xe6,0x75,0xf0,0x08,0xa4,0x24,0x4e,
+0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0x78,0x92,0xe6,0xfd,0x08,0xe6,0xfc,
+0x78,0x8f,0xe6,0xff,0x7e,0x00,0xee,0x24,0xfe,0x50,0x03,0x02,0x24,0xdd,0xe4,0xee,
+0x75,0xf0,0x07,0xa4,0x24,0x7f,0xf5,0x82,0xe4,0x34,0xf8,0xf5,0x83,0xe0,0xff,0xe4,
+0xef,0x54,0x80,0xfa,0xe4,0xef,0x54,0x0f,0x14,0xff,0xe4,0xee,0x75,0xf0,0x07,0xa4,
+0x24,0x81,0xf5,0x82,0xe4,0x34,0xf8,0xf5,0x83,0xe0,0x78,0x90,0xf6,0xe4,0xee,0x13,
+0x13,0x54,0x80,0x24,0xf0,0xf8,0xe4,0x34,0xfd,0xf9,0xe8,0xfc,0xe9,0xfd,0x8a,0x5a,
+0xea,0x70,0x03,0x02,0x24,0x4a,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x48,0xf5,0x82,
+0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0x78,0x90,0xe6,0xfa,0xe4,0xef,0x75,0xf0,0x08,
+0xa4,0x24,0x4f,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xea,0xf0,0xed,0xfb,0xec,0x7a,
+0x03,0xcb,0xc3,0x13,0xcb,0x13,0xda,0xf9,0xfa,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,
+0x49,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xea,0xf0,0x78,0x90,0xe6,0x7b,0x00,0xfa,
+0xec,0x2a,0xfc,0xed,0x3b,0xfd,0xfb,0xec,0x7a,0x03,0xcb,0xc3,0x13,0xcb,0x13,0xda,
+0xf9,0xfa,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x4d,0xf5,0x82,0xe4,0x34,0xff,0xf5,
+0x83,0xea,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x4a,0xf5,0x82,0xe4,0x34,0xff,
+0xf5,0x83,0x74,0x80,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x4e,0xf5,0x82,0xe4,
+0x34,0xff,0xf5,0x83,0x74,0x80,0xf0,0x02,0x24,0xd9,0xe4,0xef,0x75,0xf0,0x08,0xa4,
+0x24,0x08,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0x78,0x90,0xe6,0xfa,0xe4,
+0xef,0x75,0xf0,0x08,0xa4,0x24,0x0f,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xea,0xf0,
+0xed,0xfb,0xec,0x7a,0x03,0xcb,0xc3,0x13,0xcb,0x13,0xda,0xf9,0xfa,0xe4,0xef,0x75,
+0xf0,0x08,0xa4,0x24,0x09,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xea,0xf0,0x78,0x90,
+0xe6,0x7b,0x00,0xfa,0xec,0x2a,0xfc,0xed,0x3b,0xfd,0xfb,0xec,0x7a,0x03,0xcb,0xc3,
+0x13,0xcb,0x13,0xda,0xf9,0xfa,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x0d,0xf5,0x82,
+0xe4,0x34,0xff,0xf5,0x83,0xea,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x0a,0xf5,
+0x82,0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x0e,
+0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0x0e,0x02,0x23,0x66,0x8e,0x59,0x78,
+0x92,0xed,0xf6,0x08,0xec,0xf6,0x78,0x8f,0xef,0xf6,0x12,0x20,0x55,0x22,0x8c,0x26,
+0xec,0x30,0xe7,0x18,0xe5,0x26,0x54,0x0f,0x14,0x75,0xf0,0x08,0xa4,0x24,0x48,0xf5,
+0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x54,0xdf,0xf0,0x80,0x16,0xe5,0x26,0x54,0x0f,
+0x14,0x75,0xf0,0x08,0xa4,0x24,0x08,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x54,
+0xdf,0xf0,0x22,0x7c,0x00,0x22,0xec,0x90,0xfc,0x37,0xf0,0x8c,0x24,0xed,0x24,0x03,
+0xf5,0x25,0x7d,0x00,0xd3,0x95,0x72,0xed,0x95,0x71,0x40,0x03,0x85,0x72,0x25,0xe5,
+0x25,0x24,0xb7,0x50,0x09,0x75,0x25,0x03,0x74,0x02,0x90,0xfc,0x37,0xf0,0xac,0x25,
+0x12,0x30,0x24,0x22,0xe4,0xf5,0x6c,0xf5,0x6b,0x12,0x25,0x5d,0x22,0x90,0xfc,0x35,
+0xe0,0x65,0x73,0x60,0x0e,0x74,0x04,0x90,0xfc,0x37,0xf0,0xe4,0xf5,0x6b,0x75,0x6c,
+0x03,0x80,0x46,0x7d,0x73,0xe4,0xfe,0xff,0x79,0x35,0x7a,0xfc,0x7b,0x01,0x74,0x05,
+0x78,0x00,0x12,0x03,0x3f,0xe5,0x6c,0x24,0x03,0xf5,0x6c,0xe5,0x6b,0x34,0x00,0xf5,
+0x6b,0xe5,0x6c,0xd3,0x95,0x72,0xe5,0x6b,0x95,0x71,0x40,0x06,0x85,0x72,0x6c,0x85,
+0x71,0x6b,0xd3,0xe5,0x6c,0x94,0x48,0xe5,0x6b,0x94,0x00,0x40,0x0c,0x74,0x02,0x90,
+0xfc,0x37,0xf0,0xe4,0xf5,0x6b,0x75,0x6c,0x03,0xac,0x6c,0x12,0x30,0x24,0x22,0xec,
+0x90,0xfc,0x37,0xf0,0xe4,0xf5,0x6c,0xf5,0x6b,0x8c,0x32,0xec,0x60,0x05,0x12,0x30,
+0x15,0x80,0x05,0x7c,0x00,0x12,0x30,0x24,0x22,0x90,0xff,0x93,0xe0,0x44,0x01,0xf0,
+0xb2,0xb3,0x90,0xff,0x04,0xe0,0xf5,0x4a,0x90,0xff,0x06,0xe0,0xfd,0xa3,0xe0,0xed,
+0x7d,0x00,0xfc,0x7d,0x00,0xfc,0x90,0xff,0x06,0xe0,0xff,0xa3,0xe0,0x7e,0x00,0xff,
+0xe4,0xfe,0xec,0x4e,0xfc,0xed,0x4f,0xfd,0xc3,0xec,0x94,0x48,0xed,0x94,0x00,0x50,
+0x22,0x90,0xff,0x06,0xe0,0xfd,0xa3,0xe0,0xed,0x7d,0x00,0xfc,0x7d,0x00,0xfc,0x90,
+0xff,0x06,0xe0,0xff,0xa3,0xe0,0x7e,0x00,0xff,0xe4,0xfe,0xec,0x4e,0xfc,0xed,0x4f,
+0xfd,0x80,0x04,0xe4,0xfd,0x7c,0x48,0x8c,0x72,0x8d,0x71,0x90,0xff,0x02,0xe0,0xfd,
+0xa3,0xe0,0xed,0x7d,0x00,0xfc,0x7d,0x00,0xfc,0x90,0xff,0x02,0xe0,0xff,0xa3,0xe0,
+0x7e,0x00,0xff,0xe4,0xfe,0xec,0x4e,0xf5,0x4c,0xed,0x4f,0xf5,0x4b,0x75,0x6a,0x35,
+0x75,0x69,0xfc,0x75,0x68,0x01,0x7d,0x35,0x7e,0xfc,0x7f,0x01,0x79,0x73,0xe4,0xfa,
+0xfb,0x74,0x05,0x78,0x00,0x12,0x03,0x3f,0x75,0x49,0x00,0xe5,0x49,0x24,0xfe,0x40,
+0x19,0xad,0x6a,0xae,0x69,0xaf,0x68,0xe4,0x12,0x03,0x0f,0x05,0x49,0x0d,0xed,0x70,
+0x01,0x0e,0x8d,0x6a,0x8e,0x69,0x8f,0x68,0x80,0xe1,0x75,0x6a,0x35,0x75,0x69,0xfc,
+0x75,0x68,0x01,0x90,0xff,0x00,0xe0,0x54,0x60,0xb4,0x00,0x02,0x80,0x06,0xd3,0x50,
+0x03,0x02,0x2c,0x6d,0xe5,0x4a,0x54,0x0f,0xf5,0x49,0xe5,0x4a,0x54,0x80,0xa2,0xe0,
+0x92,0x02,0x90,0xff,0x01,0xe0,0x12,0x01,0x81,0x00,0x0b,0x2c,0x68,0x26,0xe5,0x28,
+0x03,0x2c,0x68,0x29,0x0f,0x2c,0x68,0x29,0xf2,0x2a,0x26,0x2b,0x8d,0x2b,0x90,0x2b,
+0xd0,0x2c,0x11,0x2c,0x3f,0xe5,0x6d,0x30,0xe7,0x0e,0xe5,0x4c,0x45,0x4b,0x70,0x08,
+0xe5,0x72,0x64,0x02,0x45,0x71,0x60,0x03,0x02,0x2c,0x6a,0x90,0xff,0x00,0xe0,0x54,
+0x1f,0xb4,0x00,0x02,0x80,0x03,0xd3,0x40,0x29,0xe5,0x4a,0x60,0x03,0x02,0x28,0x00,
+0xad,0x6a,0xae,0x69,0xaf,0x68,0x74,0x01,0x12,0x03,0x0f,0x78,0xad,0xe6,0x30,0xe0,
+0x0b,0xad,0x6a,0xae,0x69,0xaf,0x68,0x74,0x02,0x12,0x03,0x0f,0x7c,0x02,0x12,0x30,
+0x24,0x22,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x1b,0xe5,0x6d,0x20,0xe1,0x07,0xe5,
+0x4a,0x60,0x03,0x02,0x28,0x00,0xe5,0x4a,0x24,0xfe,0x50,0x03,0x02,0x28,0x00,0x7c,
+0x02,0x12,0x30,0x24,0x22,0xb4,0x02,0x02,0x80,0x06,0xd3,0x50,0x03,0x02,0x27,0xfe,
+0xe5,0x6d,0x20,0xe1,0x0d,0xe5,0x4a,0x60,0x09,0xe5,0x4a,0x64,0x80,0x60,0x03,0x02,
+0x28,0x00,0xac,0x4a,0x12,0x30,0xab,0x40,0x03,0x02,0x28,0x00,0xe5,0x49,0x70,0x25,
+0x30,0x02,0x11,0x90,0xff,0x80,0xe0,0x54,0x08,0xad,0x6a,0xae,0x69,0xaf,0x68,0x12,
+0x03,0x0f,0x80,0x0f,0x90,0xff,0x82,0xe0,0x54,0x08,0xad,0x6a,0xae,0x69,0xaf,0x68,
+0x12,0x03,0x0f,0x80,0x3d,0x15,0x49,0x30,0x02,0x1d,0xe5,0x49,0x75,0xf0,0x08,0xa4,
+0x24,0x48,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x54,0x08,0xad,0x6a,0xae,0x69,
+0xaf,0x68,0x12,0x03,0x0f,0x80,0x1b,0xe5,0x49,0x75,0xf0,0x08,0xa4,0x24,0x08,0xf5,
+0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x54,0x08,0xad,0x6a,0xae,0x69,0xaf,0x68,0x12,
+0x03,0x0f,0xad,0x6a,0xae,0x69,0xaf,0x68,0x12,0x01,0xe6,0x60,0x0b,0xad,0x6a,0xae,
+0x69,0xaf,0x68,0x74,0x01,0x12,0x03,0x0f,0x7c,0x02,0x12,0x30,0x24,0x22,0x80,0x00,
+0x02,0x2c,0x6a,0xe5,0x6d,0x20,0xe7,0x06,0xe5,0x72,0x45,0x71,0x60,0x03,0x02,0x2c,
+0x6a,0x90,0xff,0x00,0xe0,0x54,0x1f,0xb4,0x00,0x02,0x80,0x03,0xd3,0x40,0x1a,0xe5,
+0x4c,0x14,0x45,0x4b,0x70,0x04,0xe5,0x4a,0x60,0x03,0x02,0x29,0x0c,0x78,0xad,0xe6,
+0x54,0xfe,0xf6,0x7c,0x00,0x12,0x30,0x24,0x22,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,
+0x2a,0xe5,0x6d,0x20,0xe1,0x08,0xe5,0x6d,0x20,0xe0,0x03,0x02,0x29,0x0c,0xe5,0x6d,
+0x30,0xe0,0x04,0xe5,0x4a,0x70,0x0b,0xe5,0x6d,0x30,0xe1,0x09,0xe5,0x4a,0x24,0xfe,
+0x50,0x03,0x02,0x29,0x0c,0x7c,0x00,0x12,0x30,0x24,0x22,0xb4,0x02,0x02,0x80,0x06,
+0xd3,0x50,0x03,0x02,0x29,0x0a,0xe5,0x4c,0x45,0x4b,0x60,0x03,0x02,0x29,0x0c,0xac,
+0x4a,0x12,0x30,0xab,0x40,0x03,0x02,0x29,0x0c,0xe5,0x6d,0x20,0xe1,0x07,0xe5,0x6d,
+0x20,0xe0,0x02,0x80,0x77,0xe5,0x6d,0x30,0xe0,0x06,0xe5,0x49,0x60,0x02,0x80,0x6c,
+0xe5,0x49,0x70,0x0f,0x90,0xff,0x82,0xe0,0x54,0xf7,0xf0,0x90,0xff,0x80,0xe0,0x54,
+0xf7,0xf0,0x22,0xe5,0x49,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x09,0x7d,0x01,0x7c,
+0x03,0x12,0x0f,0x09,0x80,0x11,0xb4,0x02,0x02,0x80,0x03,0xd3,0x40,0x09,0x7d,0x01,
+0x7c,0x04,0x12,0x0f,0x09,0x80,0x00,0x15,0x49,0x30,0x02,0x15,0xe5,0x49,0x75,0xf0,
+0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x54,0xf7,0xf0,0x80,
+0x13,0xe5,0x49,0x75,0xf0,0x08,0xa4,0x24,0x08,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,
+0xe0,0x54,0xf7,0xf0,0x7c,0x00,0x12,0x30,0x24,0x22,0x80,0x00,0x02,0x2c,0x6a,0xe5,
+0x6d,0x20,0xe7,0x06,0xe5,0x72,0x45,0x71,0x60,0x03,0x02,0x2c,0x6a,0x90,0xff,0x00,
+0xe0,0x54,0x1f,0xb4,0x00,0x02,0x80,0x03,0xd3,0x40,0x1a,0xe5,0x4c,0x14,0x45,0x4b,
+0x70,0x04,0xe5,0x4a,0x60,0x03,0x02,0x29,0xef,0x78,0xad,0xe6,0x44,0x01,0xf6,0x7c,
+0x00,0x12,0x30,0x24,0x22,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x29,0xe5,0x6d,0x20,
+0xe1,0x08,0xe5,0x6d,0x20,0xe0,0x03,0x02,0x29,0xef,0xe5,0x6d,0x30,0xe0,0x04,0xe5,
+0x49,0x70,0x0b,0xe5,0x6d,0x30,0xe1,0x08,0xe5,0x49,0x24,0xfe,0x50,0x02,0x80,0x7f,
+0x7c,0x00,0x12,0x30,0x24,0x22,0xb4,0x02,0x02,0x80,0x03,0xd3,0x40,0x6f,0xe5,0x4c,
+0x45,0x4b,0x60,0x02,0x80,0x69,0xac,0x4a,0x12,0x30,0xab,0x40,0x02,0x80,0x60,0xe5,
+0x6d,0x20,0xe1,0x07,0xe5,0x6d,0x20,0xe0,0x02,0x80,0x54,0xe5,0x49,0x70,0x14,0x30,
+0x02,0x09,0x90,0xff,0x80,0xe0,0x44,0x08,0xf0,0x80,0x07,0x90,0xff,0x82,0xe0,0x44,
+0x08,0xf0,0x22,0xe5,0x6d,0x30,0xe1,0x33,0x15,0x49,0x30,0x02,0x15,0xe5,0x49,0x75,
+0xf0,0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x44,0x08,0xf0,
+0x80,0x13,0xe5,0x49,0x75,0xf0,0x08,0xa4,0x24,0x08,0xf5,0x82,0xe4,0x34,0xff,0xf5,
+0x83,0xe0,0x44,0x08,0xf0,0x7c,0x00,0x12,0x30,0x24,0x22,0x80,0x02,0x80,0x00,0x02,
+0x2c,0x6a,0xe5,0x6d,0x20,0xe7,0x12,0xe5,0x72,0x45,0x71,0x70,0x0c,0xe5,0x4a,0x70,
+0x08,0x90,0xff,0x00,0xe0,0x54,0x1f,0x60,0x03,0x02,0x2c,0x6a,0xe5,0x4c,0x90,0xff,
+0xff,0xf0,0x90,0xff,0xff,0xe0,0x60,0x05,0x43,0x6d,0x01,0x80,0x03,0x53,0x6d,0xfe,
+0x7c,0x00,0x12,0x30,0x24,0x22,0xe5,0x6d,0x30,0xe7,0x0e,0xe5,0x72,0x45,0x71,0x60,
+0x08,0x90,0xff,0x00,0xe0,0x54,0x1f,0x60,0x03,0x02,0x2c,0x6a,0xad,0x4b,0xe5,0x4c,
+0xed,0x7d,0x00,0xfc,0x7d,0x00,0xfc,0xbd,0x00,0x02,0x80,0x03,0x02,0x2b,0x88,0xb4,
+0x01,0x02,0x80,0x03,0xd3,0x40,0x32,0xe5,0x4a,0x70,0x05,0xe5,0x4c,0xfc,0x60,0x03,
+0x02,0x2b,0x8a,0x75,0x6a,0x40,0x75,0x69,0xf8,0x75,0x68,0x01,0xd3,0xe5,0x72,0x94,
+0x12,0xe5,0x71,0x94,0x00,0x40,0x06,0xe4,0xfd,0x7c,0x12,0x80,0x04,0xac,0x72,0xad,
+0x71,0x8c,0x70,0x8d,0x6f,0x12,0x30,0x39,0x22,0xb4,0x02,0x02,0x80,0x03,0xd3,0x40,
+0x59,0xe5,0x4a,0x60,0x03,0x02,0x2b,0x8a,0xe5,0x4c,0xfc,0x70,0x27,0x75,0x6a,0x52,
+0x75,0x69,0xf8,0x75,0x68,0x01,0xd3,0xe5,0x72,0x94,0x19,0xe5,0x71,0x94,0x00,0x40,
+0x06,0xe4,0xfd,0x7c,0x19,0x80,0x04,0xac,0x72,0xad,0x71,0x8c,0x70,0x8d,0x6f,0x12,
+0x30,0x39,0x80,0x25,0x75,0x6a,0x6b,0x75,0x69,0xf8,0x75,0x68,0x01,0xd3,0xe5,0x72,
+0x94,0x27,0xe5,0x71,0x94,0x00,0x40,0x06,0xe4,0xfd,0x7c,0x27,0x80,0x04,0xac,0x72,
+0xad,0x71,0x8c,0x70,0x8d,0x6f,0x12,0x30,0x39,0x22,0xb4,0x03,0x02,0x80,0x06,0xd3,
+0x50,0x03,0x02,0x2b,0x88,0xe5,0x4c,0xf5,0x49,0x70,0x0f,0x90,0xff,0x04,0xe0,0xfd,
+0xa3,0xe0,0x4d,0x60,0x03,0x02,0x2b,0x8a,0x80,0x18,0x90,0xfb,0x02,0xe0,0xfd,0xa3,
+0xe0,0xfc,0x90,0xff,0x05,0xe0,0x6c,0x70,0x07,0x90,0xff,0x04,0xe0,0x6d,0x60,0x02,
+0x80,0x68,0xe4,0xf5,0x70,0xf5,0x6f,0x7f,0x00,0xe5,0x49,0x14,0xc5,0x49,0x60,0x0f,
+0xef,0x24,0x00,0xf5,0x82,0xe4,0x34,0xfb,0xf5,0x83,0xe0,0x2f,0xff,0x80,0xea,0x8f,
+0x4a,0xe5,0x4a,0x24,0x00,0xf5,0x82,0xe4,0x34,0xfb,0xf5,0x83,0xe0,0x7d,0x00,0xd3,
+0x95,0x72,0xed,0x95,0x71,0x40,0x06,0xac,0x72,0xad,0x71,0x80,0x0f,0xe5,0x4a,0x24,
+0x00,0xf5,0x82,0xe4,0x34,0xfb,0xf5,0x83,0xe0,0x7d,0x00,0xfc,0x8c,0x70,0x8d,0x6f,
+0xe5,0x4a,0x24,0x00,0xfc,0xe4,0x34,0xfb,0xfd,0xfe,0xec,0xfd,0x7f,0x01,0x8d,0x6a,
+0x8e,0x69,0x8f,0x68,0x12,0x30,0x39,0x22,0x80,0x00,0x02,0x2c,0x6a,0x02,0x2c,0x6a,
+0xe5,0x6d,0x30,0xe7,0x19,0xe5,0x72,0x14,0x45,0x71,0x70,0x12,0xe5,0x4a,0x70,0x0e,
+0xe5,0x4c,0x45,0x4b,0x70,0x08,0x90,0xff,0x00,0xe0,0x54,0x1f,0x60,0x03,0x02,0x2c,
+0x6a,0xe5,0x6d,0x20,0xe0,0x08,0xe5,0x6d,0x20,0xe1,0x03,0x02,0x2c,0x6a,0x75,0x6a,
+0x6e,0xe4,0xf5,0x69,0xf5,0x68,0xe4,0xf5,0x6f,0x04,0xf5,0x70,0x12,0x30,0x39,0x22,
+0xe5,0x6d,0x20,0xe7,0x12,0xe5,0x72,0x45,0x71,0x70,0x0c,0xe5,0x4a,0x70,0x08,0x90,
+0xff,0x00,0xe0,0x54,0x1f,0x60,0x03,0x02,0x2c,0x6a,0xe5,0x6d,0x20,0xe0,0x07,0xe5,
+0x6d,0x20,0xe1,0x02,0x80,0x74,0x85,0x4c,0x6e,0xe5,0x6e,0x70,0x08,0x43,0x6d,0x01,
+0x53,0x6d,0xfd,0x80,0x06,0x53,0x6d,0xfe,0x43,0x6d,0x02,0x7c,0x00,0x12,0x30,0x24,
+0x22,0xe5,0x6d,0x30,0xe7,0x1a,0xe5,0x72,0x14,0x45,0x71,0x70,0x13,0xe5,0x4a,0x70,
+0x0f,0xe5,0x4c,0x45,0x4b,0x70,0x09,0x90,0xff,0x00,0xe0,0x54,0x1f,0x14,0x60,0x02,
+0x80,0x38,0xe5,0x6d,0x20,0xe1,0x02,0x80,0x31,0x7c,0x01,0x12,0x30,0x24,0x22,0xe5,
+0x6d,0x20,0xe7,0x15,0xe5,0x72,0x45,0x71,0x70,0x0f,0xe5,0x4c,0x45,0x4b,0x70,0x09,
+0x90,0xff,0x00,0xe0,0x54,0x1f,0x14,0x60,0x02,0x80,0x0f,0xe5,0x6d,0x20,0xe1,0x02,
+0x80,0x08,0x7c,0x00,0x12,0x30,0x24,0x22,0x80,0x00,0x02,0x2f,0x2b,0xb4,0x40,0x02,
+0x80,0x06,0xd3,0x50,0x03,0x02,0x2f,0x21,0x90,0xff,0x01,0xe0,0x90,0xfc,0x35,0xf0,
+0xe5,0x4a,0x90,0xfc,0x36,0xf0,0xe4,0x90,0xfc,0x37,0xf0,0xe5,0x6a,0x24,0x03,0xf5,
+0x6a,0xe5,0x69,0x34,0x00,0xf5,0x69,0xad,0x4b,0xe5,0x4c,0x85,0x6a,0x82,0x85,0x69,
+0x83,0xcd,0xf0,0xa3,0xcd,0xf0,0x90,0xff,0x01,0xe0,0x12,0x01,0xb7,0x2c,0xd8,0x01,
+0x2c,0xfe,0x02,0x2d,0x28,0x03,0x2d,0x52,0x04,0x2d,0xa0,0x05,0x2d,0xdd,0x06,0x2e,
+0x03,0x07,0x2e,0x29,0x08,0x2e,0x55,0x09,0x2e,0x7b,0x0b,0x2e,0xa1,0x0c,0x2e,0xb0,
+0x80,0x2e,0xb0,0x81,0x00,0x00,0x2f,0x0e,0xe5,0x6d,0x20,0xe7,0x06,0x7c,0x05,0x12,
+0x25,0xbf,0x22,0x7d,0x24,0x7e,0x35,0x7f,0x02,0x79,0x38,0x7a,0xfc,0x7b,0x01,0x74,
+0x08,0x78,0x00,0x12,0x03,0x3f,0x7d,0x08,0x7c,0x00,0x12,0x25,0x26,0x22,0xe5,0x6d,
+0x20,0xe7,0x06,0x7c,0x05,0x12,0x25,0xbf,0x22,0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,
+0xb4,0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,0x7c,0x10,0x12,0x31,0xfb,0x22,
+0x7d,0x00,0x7c,0x07,0x12,0x25,0x26,0x22,0xe5,0x6d,0x20,0xe7,0x06,0x7c,0x05,0x12,
+0x25,0xbf,0x22,0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,
+0x4a,0x7f,0x00,0xfe,0x7c,0x11,0x12,0x31,0xfb,0x22,0x7d,0x00,0x7c,0x07,0x12,0x25,
+0x26,0x22,0xe5,0x6d,0x20,0xe7,0x06,0x7c,0x05,0x12,0x25,0xbf,0x22,0xe5,0x4a,0xb4,
+0x05,0x02,0x80,0x03,0xd3,0x40,0x0a,0xe4,0xff,0x04,0xfe,0x7c,0x0a,0x12,0x31,0xfb,
+0x22,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x0a,0xe4,0xff,0x04,0xfe,0x7c,0x08,0x12,
+0x31,0xfb,0x22,0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,
+0x00,0xfe,0x7c,0x13,0x12,0x31,0xfb,0x22,0x7d,0x00,0x7c,0x07,0x12,0x25,0x26,0x22,
+0xe5,0x6d,0x20,0xe7,0x34,0xd3,0xe5,0x72,0x94,0x48,0xe5,0x71,0x94,0x00,0x50,0x06,
+0xe5,0x72,0x45,0x71,0x70,0x06,0x7c,0x02,0x12,0x25,0xbf,0x22,0xe5,0x4a,0xb4,0x01,
+0x03,0xb3,0x40,0x0b,0xc3,0xb4,0x03,0x00,0x40,0x09,0xb4,0x06,0x00,0x50,0x04,0x12,
+0x30,0xd1,0x22,0x7c,0x07,0x12,0x25,0xbf,0x22,0x12,0x25,0x5d,0x22,0xe5,0x6d,0x20,
+0xe7,0x1d,0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,0x4a,
+0x7f,0x00,0xfe,0x7c,0x16,0x12,0x31,0xfb,0x22,0x7c,0x07,0x12,0x25,0xbf,0x22,0x12,
+0x25,0x5d,0x22,0xe5,0x6d,0x20,0xe7,0x1d,0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,0xb4,
+0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,0x7c,0x19,0x12,0x31,0xfb,0x22,0x7c,
+0x07,0x12,0x25,0xbf,0x22,0x12,0x25,0x5d,0x22,0xe5,0x6d,0x20,0xe7,0x23,0x74,0x81,
+0x90,0xff,0x93,0xf0,0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,
+0xe5,0x4a,0x7f,0x00,0xfe,0x7c,0x17,0x12,0x31,0xfb,0x22,0x7c,0x07,0x12,0x25,0xbf,
+0x22,0x12,0x25,0x5d,0x22,0xe5,0x6d,0x20,0xe7,0x1d,0xe5,0x4a,0xb4,0x03,0x00,0x40,
+0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,0x7c,0x18,0x12,0x31,0xfb,
+0x22,0x7c,0x07,0x12,0x25,0xbf,0x22,0x12,0x25,0x5d,0x22,0xe5,0x6d,0x20,0xe7,0x1d,
+0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,
+0xfe,0x7c,0x15,0x12,0x31,0xfb,0x22,0x7c,0x07,0x12,0x25,0xbf,0x22,0x12,0x25,0x5d,
+0x22,0xe5,0x6d,0x20,0xe7,0x06,0x7c,0x07,0x12,0x25,0xbf,0x22,0x12,0x25,0x5d,0x22,
+0xe5,0x6d,0x30,0xe7,0x20,0x90,0xff,0x00,0xe0,0x54,0x1f,0x70,0x10,0x90,0xff,0x01,
+0xe0,0xb4,0x80,0x05,0x12,0x25,0x54,0x80,0x03,0x12,0x25,0x5d,0x22,0x7d,0x00,0x7c,
+0x05,0x12,0x25,0x26,0x22,0x90,0xff,0x00,0xe0,0x54,0x1f,0x60,0x06,0x7c,0x05,0x12,
+0x25,0xbf,0x22,0xd3,0xe5,0x72,0x94,0x48,0xe5,0x71,0x94,0x00,0x50,0x0b,0xc3,0xe5,
+0x72,0x94,0x07,0xe5,0x71,0x94,0x00,0x50,0x06,0x7c,0x03,0x12,0x25,0xbf,0x22,0xe5,
+0x4a,0xb4,0x05,0x04,0x12,0x30,0xd1,0x22,0x7c,0x07,0x12,0x25,0xbf,0x22,0xe5,0x6d,
+0x30,0xe7,0x08,0x7d,0x00,0x7c,0x05,0x12,0x25,0x26,0x22,0x7c,0x05,0x12,0x25,0xbf,
+0x22,0xb4,0x20,0x02,0x80,0x03,0xd3,0x40,0x00,0x80,0x00,0x12,0x2f,0xff,0x22,0x75,
+0x43,0x00,0x90,0xff,0x83,0xe0,0x54,0x0f,0xd3,0x95,0x43,0x40,0x24,0xe5,0x43,0x24,
+0xf0,0xf5,0x82,0xe4,0x34,0xfe,0xf5,0x83,0xe0,0xad,0x6a,0xae,0x69,0xaf,0x68,0x12,
+0x03,0x0f,0x05,0x43,0x0d,0xed,0x70,0x01,0x0e,0x8d,0x6a,0x8e,0x69,0x8f,0x68,0x80,
+0xd1,0xe5,0x43,0x7d,0x00,0xfc,0xc3,0xe5,0x70,0x9c,0xf5,0x70,0xe5,0x6f,0x9d,0xf5,
+0x6f,0xe5,0x70,0x45,0x6f,0x60,0x06,0xe4,0x90,0xff,0x83,0xf0,0x22,0x90,0xff,0x82,
+0xe0,0x44,0x08,0xf0,0xe4,0xf5,0x6f,0x75,0x70,0x49,0x90,0xfc,0x35,0xe0,0xb4,0x05,
+0x02,0x80,0x03,0xd3,0x40,0x40,0x90,0xfc,0x36,0xe0,0xf5,0x43,0xb4,0x05,0x02,0x80,
+0x03,0xd3,0x40,0x0a,0xe4,0xff,0x04,0xfe,0x7c,0x0b,0x12,0x31,0xfb,0x22,0xb4,0x01,
+0x02,0x80,0x03,0xd3,0x40,0x0a,0xe4,0xff,0x04,0xfe,0x7c,0x09,0x12,0x31,0xfb,0x22,
+0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,0x43,0x7f,0x00,0xfe,0x7c,
+0x14,0x12,0x31,0xfb,0x22,0x22,0xb4,0x80,0x00,0x40,0x23,0xb4,0x82,0x00,0x50,0x1e,
+0x7c,0x35,0x7d,0xfc,0x12,0x17,0x7e,0x7d,0x00,0x8c,0x6c,0x8d,0x6b,0x90,0xfc,0x37,
+0xe0,0x60,0x05,0x12,0x2f,0xff,0x80,0x05,0x7c,0x00,0x12,0x30,0x24,0x22,0x22,0x90,
+0xff,0x83,0xe0,0x54,0x7f,0xf0,0x90,0xff,0x82,0xe0,0x44,0x08,0xf0,0x90,0xff,0x80,
+0xe0,0x44,0x08,0xf0,0x22,0x90,0xff,0x82,0xe0,0x44,0x08,0xf0,0x90,0xff,0x80,0xe0,
+0x44,0x08,0xf0,0x22,0x8c,0x23,0x7d,0x00,0x8c,0x70,0x8d,0x6f,0x75,0x6a,0x35,0x75,
+0x69,0xfc,0x75,0x68,0x01,0x12,0x30,0x39,0x22,0x90,0xff,0x83,0xe0,0x54,0x7f,0xf0,
+0xe5,0x70,0x64,0x49,0x45,0x6f,0x70,0x01,0x22,0xc3,0xe5,0x70,0x94,0x08,0xe5,0x6f,
+0x94,0x00,0x40,0x15,0x75,0x21,0x08,0xe5,0x21,0x7d,0x00,0xfc,0xc3,0xe5,0x70,0x9c,
+0xf5,0x70,0xe5,0x6f,0x9d,0xf5,0x6f,0x80,0x09,0x85,0x70,0x21,0xe4,0xf5,0x6f,0x75,
+0x70,0x49,0x75,0x22,0x00,0xe5,0x22,0xc3,0x95,0x21,0x50,0x26,0xad,0x6a,0xae,0x69,
+0xaf,0x68,0x12,0x01,0xe6,0xfc,0xe5,0x22,0x24,0xf8,0xf5,0x82,0xe4,0x34,0xfe,0xf5,
+0x83,0xec,0xf0,0x05,0x22,0x0d,0xed,0x70,0x01,0x0e,0x8d,0x6a,0x8e,0x69,0x8f,0x68,
+0x80,0xd3,0xe5,0x21,0x54,0x7f,0x90,0xff,0x81,0xf0,0x22,0x8c,0x48,0x7f,0x00,0xef,
+0x24,0xfd,0x40,0x19,0xe4,0xef,0x75,0xf0,0x07,0xa4,0x24,0x7f,0xf5,0x82,0xe4,0x34,
+0xf8,0xf5,0x83,0xe0,0x65,0x48,0x70,0x02,0xd3,0x22,0x0f,0x80,0xe2,0x8f,0x47,0xc3,
+0x22,0x85,0x72,0x70,0x85,0x71,0x6f,0x90,0xff,0x82,0xe0,0x54,0xf7,0xf0,0x90,0xff,
+0x83,0xe0,0x54,0x7f,0xf0,0x22,0xc0,0x00,0xc0,0x01,0xc0,0x02,0xc0,0x06,0xc0,0x07,
+0xe5,0x78,0x24,0x08,0xf8,0x86,0x06,0x53,0x06,0x7f,0x7c,0xff,0x12,0x31,0x5b,0x7c,
+0x00,0x7d,0x00,0xe5,0x7b,0x60,0x46,0xff,0x90,0xfd,0x95,0xe0,0x54,0x7f,0x6e,0x70,
+0x0f,0xc0,0x83,0xc0,0x82,0xa3,0xe0,0xfd,0xa3,0xe0,0xfc,0xa3,0x15,0x7b,0x80,0x07,
+0xa3,0xa3,0xa3,0xdf,0xe6,0x80,0x26,0xdf,0x06,0xd0,0x82,0xd0,0x83,0x80,0x1e,0xe0,
+0xf8,0xa3,0xe0,0xf9,0xa3,0xe0,0xfa,0xd0,0x82,0xd0,0x83,0xe8,0xf0,0xa3,0xe9,0xf0,
+0xa3,0xea,0xf0,0xa3,0xc0,0x83,0xc0,0x82,0xa3,0xa3,0xa3,0x80,0xda,0x12,0x31,0xf4,
+0xd0,0x07,0xd0,0x06,0xd0,0x02,0xd0,0x01,0xd0,0x00,0x22,0x85,0xa8,0x7a,0x75,0xa8,
+0x88,0xec,0x70,0x02,0x7c,0x3f,0x8c,0x79,0x22,0xe5,0x78,0x24,0x08,0xf8,0x76,0x00,
+0x12,0x32,0x48,0x80,0xfb,0xc0,0x00,0xc0,0x01,0xc0,0x02,0xc0,0x06,0xc0,0x07,0xae,
+0x04,0x7c,0xff,0x12,0x31,0x5b,0xe5,0x7b,0x60,0x42,0xff,0x90,0xfd,0x95,0xe0,0x54,
+0x7f,0x6e,0x70,0x0b,0xc0,0x83,0xc0,0x82,0xa3,0xa3,0xa3,0x15,0x7b,0x80,0x07,0xa3,
+0xa3,0xa3,0xdf,0xea,0x80,0x26,0xdf,0x06,0xd0,0x82,0xd0,0x83,0x80,0xd8,0xe0,0xf8,
+0xa3,0xe0,0xf9,0xa3,0xe0,0xfa,0xd0,0x82,0xd0,0x83,0xe8,0xf0,0xa3,0xe9,0xf0,0xa3,
+0xea,0xf0,0xa3,0xc0,0x83,0xc0,0x82,0xa3,0xa3,0xa3,0x80,0xda,0x78,0x08,0x08,0x79,
+0x18,0x09,0x7c,0x01,0xe6,0x54,0x7f,0x6e,0x70,0x06,0x76,0x00,0x77,0x00,0x80,0x06,
+0x08,0x09,0x0c,0xbc,0x08,0xee,0x12,0x31,0xf4,0xd0,0x07,0xd0,0x06,0xd0,0x02,0xd0,
+0x01,0xd0,0x00,0x22,0x75,0x79,0x00,0x85,0x7a,0xa8,0x22,0xc0,0xf0,0xc0,0x82,0xc0,
+0x83,0xc3,0xe5,0x7b,0x24,0xe8,0x50,0x05,0x12,0x32,0x48,0x80,0xf4,0xec,0x60,0x31,
+0x90,0x35,0x23,0xe4,0x93,0xc3,0x9c,0x40,0x28,0xc0,0x04,0x7c,0xff,0x12,0x31,0x5b,
+0xd0,0x04,0x43,0x04,0x80,0xe5,0x7b,0x75,0xf0,0x03,0xa4,0x24,0x95,0xf5,0x82,0xe4,
+0x34,0xfd,0xf5,0x83,0xec,0xf0,0xef,0xa3,0xf0,0xee,0xa3,0xf0,0x05,0x7b,0x12,0x31,
+0xf4,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0x22,0xc0,0x04,0x7c,0x20,0xd2,0x8c,0xd2,0x8d,
+0xd5,0x04,0xfd,0xd0,0x04,0x22,0x75,0xa8,0x00,0x75,0x88,0x00,0x75,0xb8,0x00,0x75,
+0xf0,0x00,0x75,0xd0,0x00,0xe4,0xf8,0x90,0x00,0x00,0xf6,0x08,0xb8,0x00,0xfb,0x02,
+0x00,0x00,0xc3,0xed,0x94,0x02,0x50,0x04,0x7d,0x03,0x7c,0xe8,0xec,0xf4,0xfc,0xed,
+0xf4,0xfd,0x0c,0xbc,0x00,0x01,0x0d,0x8c,0x7f,0x8d,0x7e,0x22,0xc3,0xec,0x94,0xbc,
+0xed,0x94,0x02,0x50,0x04,0x7d,0x07,0x7c,0xd0,0xec,0xf4,0xfc,0xed,0xf4,0xfd,0x0c,
+0xbc,0x00,0x01,0x0d,0x8c,0x7d,0x8d,0x7c,0x22,0xec,0x70,0x01,0x22,0xc0,0x00,0xe5,
+0x78,0x24,0x18,0xf8,0xa6,0x04,0xe5,0x78,0x24,0x08,0xf8,0xc6,0x54,0x7f,0xf6,0xe6,
+0x30,0xe7,0x03,0xd0,0x00,0x22,0x12,0x32,0x48,0x80,0xf4,0xc2,0x8c,0x85,0x7c,0x8c,
+0x85,0x7d,0x8a,0xd2,0x8c,0xc0,0xe0,0xc0,0xd0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,
+0x00,0xc0,0x01,0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0xc0,0x06,0xc0,0x07,0x12,
+0x1a,0xd1,0xe5,0x78,0x24,0x08,0xf8,0xe6,0x60,0x24,0xe5,0x78,0x24,0x10,0xf8,0xa6,
+0x81,0xe5,0x78,0x75,0xf0,0x21,0xa4,0x24,0x8d,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,
+0x78,0xae,0xe5,0x81,0x04,0xc3,0x98,0xf9,0xe6,0xf0,0x08,0xa3,0xd9,0xfa,0x74,0x08,
+0x25,0x78,0xf8,0x05,0x78,0x08,0xe6,0x54,0x80,0x70,0x0c,0xe5,0x78,0xb4,0x07,0xf3,
+0x78,0x08,0x75,0x78,0x00,0x80,0xef,0xe5,0x78,0x24,0x10,0xf8,0x86,0x81,0xe5,0x78,
+0x75,0xf0,0x21,0xa4,0x24,0x8d,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0x78,0xae,0xe5,
+0x81,0x04,0xc3,0x98,0xf9,0xe0,0xf6,0x08,0xa3,0xd9,0xfa,0xd0,0x07,0xd0,0x06,0xd0,
+0x05,0xd0,0x04,0xd0,0x03,0xd0,0x02,0xd0,0x01,0xd0,0x00,0xd0,0x83,0xd0,0x82,0xd0,
+0xf0,0xd0,0xd0,0xd0,0xe0,0x32,0xc0,0xe0,0xc0,0xd0,0xc0,0x00,0xc0,0x01,0xc0,0x02,
+0xc2,0x8e,0x85,0x7e,0x8d,0x85,0x7f,0x8b,0xd2,0x8e,0x78,0x19,0x79,0x09,0x7a,0x07,
+0xe7,0x70,0x04,0xa6,0x00,0x80,0x0b,0xe6,0x60,0x08,0x16,0xe6,0x70,0x04,0xe7,0x44,
+0x80,0xf7,0x08,0x09,0xda,0xea,0xe5,0x79,0x60,0x13,0x14,0xf5,0x79,0x70,0x0e,0xe5,
+0x78,0x24,0x08,0xf8,0x76,0x00,0x12,0x31,0xf4,0xd2,0x8c,0xd2,0x8d,0xd0,0x02,0xd0,
+0x01,0xd0,0x00,0xd0,0xd0,0xd0,0xe0,0x32,0x75,0x81,0xad,0x74,0x2a,0x90,0xff,0x93,
+0xf0,0x75,0x7f,0x30,0x75,0x7e,0xf8,0x75,0x7d,0x60,0x75,0x7c,0xf0,0x12,0x05,0x36,
+0x12,0x34,0x7c,0x12,0x17,0x34,0x90,0xff,0x93,0xe0,0x44,0x01,0xf0,0xb2,0xb3,0x12,
+0x34,0xa6,0x12,0x32,0x56,0x80,0xda,0x22,0xc0,0x00,0x7c,0x01,0xec,0x24,0x08,0xf8,
+0xe6,0x60,0x09,0x0c,0xbc,0x08,0xf5,0x12,0x32,0x48,0x80,0xee,0xd0,0x00,0x22,0xc0,
+0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x00,0xc0,0x06,0xc0,0x07,0xed,0x24,0x10,0xf8,0x76,
+0xbc,0xed,0x75,0xf0,0x21,0xa4,0x24,0x8d,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xc0,
+0x82,0xc0,0x83,0xa3,0xa3,0xe4,0x78,0x0d,0xf0,0xa3,0xd8,0xfc,0xec,0x54,0x7f,0x75,
+0xf0,0x02,0xa4,0x24,0xef,0xf5,0x82,0xe5,0xf0,0x34,0x34,0xf5,0x83,0xe4,0x93,0xfe,
+0x74,0x01,0x93,0xf5,0x82,0x8e,0x83,0xe4,0x93,0xfe,0x74,0x01,0x93,0xff,0xd0,0x83,
+0xd0,0x82,0xef,0xf0,0xa3,0xee,0xf0,0xed,0x24,0x08,0xf8,0xec,0x44,0x80,0xf6,0xd0,
+0x07,0xd0,0x06,0xd0,0x00,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0x22,0x75,0x78,0x00,0x75,
+0x7b,0x00,0x7a,0x08,0x79,0x18,0x78,0x08,0x76,0x00,0x77,0x00,0x08,0x09,0xda,0xf8,
+0xe4,0x78,0x08,0x74,0x80,0x44,0x7f,0xf6,0x74,0x01,0x44,0x10,0xf5,0x89,0x75,0xb8,
+0x08,0xd2,0xab,0xd2,0xa9,0x22,0x75,0x81,0xad,0xd2,0x8e,0xd2,0x8c,0xd2,0xaf,0xe5,
+0x7b,0x60,0x32,0xff,0x90,0xfd,0x95,0xe0,0x54,0x80,0x60,0x24,0x78,0x08,0x79,0x08,
+0xe0,0x54,0x7f,0xfa,0x7b,0x00,0xe6,0x54,0x7f,0xb5,0x02,0x02,0x7b,0xff,0x08,0xd9,
+0xf5,0xeb,0x70,0x0c,0xea,0xf0,0x12,0x33,0xf8,0xad,0x04,0xac,0x02,0x12,0x34,0x0f,
+0xa3,0xa3,0xa3,0xdf,0xd2,0x12,0x32,0x48,0x80,0xc5,0x7c,0x01,0x7d,0x00,0x22,0x04,
+0xf5,0x04,0xe9,0x04,0xed,0x04,0xe1,0x04,0xdd,0x04,0xd9,0x04,0xe5,0x04,0xf1,0x04,
+0x9d,0x04,0xa1,0x04,0xcd,0x04,0xd1,0x04,0x99,0x04,0x99,0x04,0x99,0x04,0xd5,0x04,
+0xb5,0x04,0xad,0x04,0xb1,0x04,0xa9,0x04,0xc1,0x04,0xbd,0x04,0xb9,0x04,0xc5,0x04,
+0xc9,0x04,0xa5,0x19,0x01,0x03,0x00,0x22,0x00,0x48,0x02,0x00,0x48,0x0e,0x30,0x14,
+0x20,0xc8,0x1a,0xd0,0x18,0x0a,0x0c,0x05,0x06,0x02,0x03,0x01,0x02,0x00,0x01,0xce,
+0x01,0x81,0x01,0x00,0x00,0xc0,0x00,0x80,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x10,
+0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x00,0x08,0x18,0x38,0x28,0x0c,0x05,0x10,
+0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x10,0x0a,0x02,0x00,0x00,0x00,0x00,
+0x00,0xfb,0xe0,0xfb,0xf2,0x09,0x02,0x27,0x00,0x01,0x02,0x00,0xa0,0x32,0x09,0x04,
+0x00,0x00,0x03,0xff,0x00,0x00,0x00,0x07,0x05,0x81,0x02,0x40,0x00,0x00,0x07,0x05,
+0x01,0x02,0x40,0x00,0x00,0x07,0x05,0x83,0x03,0x02,0x00,0x01,0x22,0x03,0x54,0x00,
+0x55,0x00,0x53,0x00,0x42,0x00,0x33,0x00,0x34,0x00,0x31,0x00,0x30,0x00,0x20,0x00,
+0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x00,0x00,
+0x00,0x00,
+};
+
+#endif /* ifndef _TI_FW_3410_H_ */
diff --git a/drivers/usb/serial/ti_fw_5052.h b/drivers/usb/serial/ti_fw_5052.h
new file mode 100644
index 00000000000000..6ccf40a097985f
--- /dev/null
+++ b/drivers/usb/serial/ti_fw_5052.h
@@ -0,0 +1,885 @@
+/* vi: ts=8 sw=8
+ *
+ * TI 5052 USB Serial Driver Firmware Header
+ *
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * 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.
+ */
+
+#ifndef _TI_FW_5052_H_
+#define _TI_FW_5052_H_
+
+/* firmware 9/18/04 */
+
+static unsigned char ti_fw_5052[] = {
+0xC1, 0x35, /* firmware image length excluding header, little endian */
+0x00, /* placeholder for checksum */
+
+0x02,0x00,0x1e,0x02,0x1b,0x32,0xff,0xff,0xff,0xff,0xff,0x02,0x32,0x6a,0xff,0xff,
+0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x02,0x33,0x15,0x75,0x81,
+0xc8,0x90,0xfe,0xf0,0x85,0x83,0xa0,0x12,0x34,0x7d,0xec,0x4d,0x60,0x6a,0x78,0xa5,
+0x80,0x03,0x76,0x00,0x18,0xb8,0x96,0xfa,0x78,0x79,0x80,0x03,0x76,0x00,0x18,0xb8,
+0x5f,0xfa,0x78,0x20,0x80,0x03,0x76,0x00,0x18,0xb8,0x20,0xfa,0x90,0xfe,0xe5,0xae,
+0x83,0xaf,0x82,0x90,0xfd,0x00,0x12,0x00,0xa1,0x60,0x05,0xe4,0xf0,0xa3,0x80,0xf6,
+0x90,0xfe,0xf0,0xa8,0x82,0x90,0xfe,0xf0,0xa9,0x82,0xe8,0xc3,0x99,0x50,0x05,0x76,
+0x00,0x08,0x80,0xf6,0x90,0x00,0xff,0x12,0x00,0xaa,0x90,0x01,0x03,0x12,0x00,0xaa,
+0x90,0x01,0x07,0x12,0x00,0xaa,0x90,0x01,0x0b,0x12,0x00,0xc8,0x90,0x01,0x11,0x12,
+0x00,0xc8,0x90,0x01,0x17,0x12,0x00,0xc8,0x75,0xd0,0x00,0x12,0x33,0x67,0x02,0x01,
+0x1d,0xef,0x65,0x82,0x70,0x03,0xee,0x65,0x83,0x22,0xe4,0x93,0xf8,0x74,0x01,0x93,
+0xf9,0x74,0x02,0x93,0xfe,0x74,0x03,0x93,0xf5,0x82,0x8e,0x83,0xe8,0x69,0x70,0x01,
+0x22,0xe4,0x93,0xf6,0xa3,0x08,0x80,0xf4,0xe4,0x93,0xfc,0x74,0x01,0x93,0xfd,0x74,
+0x02,0x93,0xfe,0x74,0x03,0x93,0xff,0x74,0x04,0x93,0xf8,0x74,0x05,0x93,0xf5,0x82,
+0x88,0x83,0x12,0x00,0xa1,0x70,0x01,0x22,0xe4,0x93,0xa3,0xa8,0x83,0xa9,0x82,0x8c,
+0x83,0x8d,0x82,0xf0,0xa3,0xac,0x83,0xad,0x82,0x88,0x83,0x89,0x82,0x80,0xe3,0x21,
+0x21,0x04,0x92,0x7a,0x7a,0x04,0x92,0xa6,0xa8,0x04,0x92,0xfe,0xf0,0x04,0x94,0x04,
+0x94,0xfb,0xfb,0x04,0x99,0x04,0x94,0xfb,0xfb,0x04,0xf9,0x04,0xf9,0x80,0xfe,0xd0,
+0xf0,0x30,0xf0,0x09,0x20,0xf3,0x03,0xf6,0x80,0x10,0xf7,0x80,0x0d,0x30,0xf1,0x09,
+0x20,0xf3,0x03,0xf2,0x80,0x04,0xf3,0x80,0x01,0xf0,0x20,0xf4,0x04,0xfc,0xd0,0xe0,
+0xcc,0x22,0xcc,0xc0,0xe0,0x12,0x01,0x5a,0x02,0x01,0x4b,0xbc,0x00,0x05,0xd0,0xf0,
+0xac,0xf0,0x22,0xc3,0x13,0xdc,0xfc,0x02,0x01,0x21,0xbf,0x00,0x09,0xed,0x25,0x82,
+0x75,0xf0,0x01,0xf8,0xe6,0x22,0xbf,0x01,0x0f,0xed,0x25,0x82,0xf5,0x82,0xee,0x35,
+0x83,0xf5,0x83,0x75,0xf0,0x04,0xe0,0x22,0xed,0x25,0x82,0x75,0xf0,0x02,0xf8,0xe2,
+0x22,0xd0,0x83,0xd0,0x82,0xf5,0xf0,0xc3,0xe4,0x93,0xa3,0xc5,0xf0,0x95,0xf0,0xc0,
+0xe0,0xc3,0xd0,0xf0,0xe4,0x93,0xa3,0x95,0xf0,0x40,0x12,0xa3,0xa3,0xc3,0xe5,0xf0,
+0x33,0x50,0x02,0x05,0x83,0x25,0x82,0xf5,0x82,0x50,0x02,0x05,0x83,0x74,0x01,0x93,
+0xc0,0xe0,0xe4,0x93,0xc0,0xe0,0x22,0xd0,0x83,0xd0,0x82,0xf5,0xf0,0xe4,0x93,0x70,
+0x09,0x74,0x01,0x93,0x70,0x04,0xa3,0xa3,0x80,0x0c,0x74,0x02,0x93,0x65,0xf0,0x60,
+0x05,0xa3,0xa3,0xa3,0x80,0xe7,0x74,0x01,0x93,0xc0,0xe0,0xe4,0x93,0xc0,0xe0,0x22,
+0x12,0x02,0x5b,0x02,0x01,0xf2,0x12,0x02,0xaf,0x02,0x01,0xf2,0x12,0x02,0xd3,0x02,
+0x01,0xf2,0x30,0xe0,0x07,0x20,0xe3,0x02,0xe6,0x22,0xe7,0x22,0x30,0xe1,0x07,0x20,
+0xe3,0x02,0xe2,0x22,0xe3,0x22,0x30,0xe2,0x02,0xe0,0x22,0xe4,0x93,0x22,0x12,0x02,
+0xd3,0x02,0x02,0x1a,0x12,0x02,0xaf,0x02,0x02,0x1a,0xab,0xf0,0x12,0x02,0x24,0xcb,
+0xc5,0xf0,0xcb,0x22,0x30,0xe0,0x10,0x20,0xe3,0x06,0xe6,0xf5,0xf0,0x08,0xe6,0x22,
+0xe7,0xf5,0xf0,0x09,0xe7,0x19,0x22,0x30,0xe1,0x10,0x20,0xe3,0x06,0xe2,0xf5,0xf0,
+0x08,0xe2,0x22,0xe3,0xf5,0xf0,0x09,0xe3,0x19,0x22,0x30,0xe2,0x06,0xe0,0xf5,0xf0,
+0xa3,0xe0,0x22,0xe4,0x93,0xf5,0xf0,0x74,0x01,0x93,0x22,0xbb,0x00,0x03,0x74,0x09,
+0x22,0xbb,0x01,0x07,0x89,0x82,0x8a,0x83,0x74,0x04,0x22,0xbb,0x02,0x07,0x89,0x82,
+0x8a,0x83,0x74,0x10,0x22,0x74,0x0a,0x22,0x02,0x02,0x7b,0xbb,0x00,0x07,0xe9,0x25,
+0x82,0xf8,0x74,0x01,0x22,0xbb,0x01,0x0d,0xe9,0x25,0x82,0xf5,0x82,0xea,0x35,0x83,
+0xf5,0x83,0x74,0x04,0x22,0xbb,0x02,0x0d,0xe9,0x25,0x82,0xf5,0x82,0xea,0x35,0x83,
+0xf5,0x83,0x74,0x10,0x22,0xe9,0x25,0x82,0xf8,0x74,0x02,0x22,0x02,0x02,0xaf,0xbf,
+0x00,0x05,0xed,0xf8,0x74,0x01,0x22,0xbf,0x01,0x07,0x8d,0x82,0x8e,0x83,0x74,0x04,
+0x22,0xbf,0x02,0x07,0x8d,0x82,0x8e,0x83,0x74,0x10,0x22,0xed,0xf8,0x74,0x02,0x22,
+0x02,0x02,0xd3,0xbf,0x00,0x07,0xed,0x25,0x82,0xf8,0x74,0x01,0x22,0xbf,0x01,0x0d,
+0xed,0x25,0x82,0xf5,0x82,0xee,0x35,0x83,0xf5,0x83,0x74,0x04,0x22,0xbf,0x02,0x0d,
+0xed,0x25,0x82,0xf5,0x82,0xee,0x35,0x83,0xf5,0x83,0x74,0x10,0x22,0xed,0x25,0x82,
+0xf8,0x74,0x02,0x22,0x02,0x03,0x07,0xc0,0xe0,0x12,0x02,0x5b,0x02,0x03,0x1f,0xc0,
+0xe0,0x12,0x02,0xaf,0x02,0x03,0x1f,0xc0,0xe0,0x12,0x02,0xd3,0x02,0x03,0x1f,0x30,
+0xe0,0x0b,0x20,0xe3,0x04,0xd0,0xe0,0xf6,0x22,0xd0,0xe0,0xf7,0x22,0x30,0xe1,0x0b,
+0x20,0xe3,0x04,0xd0,0xe0,0xf2,0x22,0xd0,0xe0,0xf3,0x22,0xd0,0xe0,0xf0,0x22,0xc9,
+0xcd,0xc9,0xca,0xce,0xca,0xcb,0xcf,0xcb,0x12,0x03,0x52,0xed,0xf9,0xee,0xfa,0xef,
+0xfb,0x22,0xbb,0x00,0x2f,0xbf,0x00,0x0a,0xfa,0xed,0xf8,0xe7,0xf6,0x08,0x09,0xda,
+0xfa,0x22,0xbf,0x01,0x12,0x8d,0x82,0x8e,0x83,0xf8,0x02,0x03,0x6f,0x09,0xa3,0xe7,
+0xf0,0xd8,0xfa,0x22,0x02,0x03,0x7a,0xfa,0xed,0xf8,0xe7,0xf2,0x08,0x09,0xda,0xfa,
+0x22,0x02,0x03,0x84,0xbb,0x01,0x4d,0xbf,0x00,0x14,0x89,0x82,0x8a,0x83,0xf9,0xed,
+0xf8,0x02,0x03,0x96,0x08,0xa3,0xe0,0xf6,0xd9,0xfa,0x22,0x02,0x03,0xa7,0xbf,0x01,
+0x22,0x8d,0x82,0x8e,0x83,0xfb,0x08,0xc9,0xc5,0x82,0xc9,0xca,0xc5,0x83,0xca,0xe0,
+0xa3,0xc9,0xc5,0x82,0xc9,0xca,0xc5,0x83,0xca,0xf0,0xa3,0xdb,0xea,0xd8,0xe8,0x22,
+0x02,0x03,0xca,0x8d,0x82,0x8e,0x83,0xf9,0xed,0xf8,0xe0,0xf2,0x08,0xa3,0xd9,0xfa,
+0x22,0x02,0x03,0xd4,0xbb,0x02,0x4d,0xbf,0x00,0x12,0x89,0x82,0x8a,0x83,0xf9,0xed,
+0xf8,0x02,0x03,0xe6,0x08,0xa3,0xe4,0x93,0xf6,0xd9,0xf9,0x22,0xbf,0x01,0x23,0x8d,
+0x82,0x8e,0x83,0xfb,0x08,0xc9,0xc5,0x82,0xc9,0xca,0xc5,0x83,0xca,0xe4,0x93,0xa3,
+0xc9,0xc5,0x82,0xc9,0xca,0xc5,0x83,0xca,0xf0,0xa3,0xdb,0xe9,0xd8,0xe7,0x22,0x02,
+0x04,0x19,0x89,0x82,0x8a,0x83,0xf9,0xed,0xf8,0xe4,0x93,0xf2,0x08,0xa3,0xd9,0xf9,
+0x22,0x02,0x04,0x2a,0xbf,0x00,0x0d,0xfa,0xed,0xf8,0xe3,0xf6,0x08,0x09,0xda,0xfa,
+0x22,0x02,0x04,0x34,0xbf,0x01,0x12,0x8d,0x82,0x8e,0x83,0xf8,0x02,0x04,0x41,0x09,
+0xa3,0xe3,0xf0,0xd8,0xfa,0x22,0x02,0x04,0x4c,0xfa,0xed,0xf8,0xe3,0xf2,0x08,0x09,
+0xda,0xfa,0x22,0x02,0x04,0x56,0xe6,0xfb,0x08,0xe6,0xfa,0x08,0xe6,0xf9,0x04,0xf6,
+0x18,0x70,0x01,0x06,0x22,0xe6,0xff,0x08,0xe6,0xfe,0x08,0xe6,0xfd,0x22,0xef,0xf0,
+0xa3,0xee,0xf0,0xa3,0xed,0xf0,0x22,0xeb,0xf0,0xa3,0xea,0xf0,0xa3,0xe9,0xf0,0x22,
+0xe0,0xff,0xa3,0xe0,0xfe,0xa3,0xe0,0xfd,0x22,0xe0,0xfb,0xa3,0xe0,0xfa,0xa3,0xe0,
+0xf9,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0xf9,0x00,0x5b,0x05,0x73,0x00,
+0x26,0x05,0x9a,0x00,0x33,0x0a,0x0b,0x00,0x5b,0x0a,0x77,0x00,0x60,0x15,0x52,0x00,
+0x5b,0x0c,0xfb,0x00,0x5b,0x09,0xab,0x00,0x5b,0x09,0xe2,0x00,0x5b,0x0d,0xc2,0x00,
+0x5b,0x0b,0xf3,0x00,0x5b,0x0a,0x1e,0x00,0x5b,0x0a,0x53,0x00,0x5b,0x17,0x4a,0x00,
+0x33,0x17,0x60,0x00,0x34,0x1e,0x4d,0x00,0x43,0x1e,0xf0,0x00,0x44,0x20,0x5d,0x00,
+0x44,0x20,0x4b,0x00,0x47,0x1f,0x17,0x00,0x47,0x1f,0xbc,0x00,0x4d,0x20,0x0d,0x00,
+0x4f,0x1f,0x39,0x00,0x58,0x31,0xf5,0x00,0x5b,0x7c,0xcc,0x7d,0xff,0x12,0x1c,0xfe,
+0x22,0x74,0x90,0x90,0xff,0x91,0xf0,0x90,0xff,0xfc,0xe0,0x20,0xe7,0x2d,0xc2,0xaf,
+0xae,0x59,0xaf,0x58,0x75,0x5a,0x20,0xe5,0x5a,0x14,0xc5,0x5a,0x60,0x19,0xe4,0xfe,
+0x7f,0x05,0xee,0x4f,0xce,0x24,0xff,0xce,0xcf,0x34,0xff,0xcf,0x60,0x07,0xe4,0x90,
+0xff,0x92,0xf0,0x80,0xed,0x80,0xe0,0x8e,0x59,0x8f,0x58,0x22,0x12,0x05,0x01,0x7d,
+0x07,0x7c,0xb7,0x12,0x32,0x11,0x7d,0x0f,0x7c,0x6e,0x12,0x32,0x2b,0x78,0x97,0x7a,
+0x06,0xe4,0xf6,0x08,0xda,0xfc,0x7a,0x06,0x12,0x05,0xcf,0x7c,0x03,0x12,0x0e,0x57,
+0x7c,0x04,0x12,0x0e,0x57,0x12,0x21,0x8b,0xe4,0xfe,0xff,0x7c,0x0f,0x12,0x31,0x9a,
+0xd2,0xa8,0x22,0x12,0x30,0x85,0xe4,0x90,0xfd,0x40,0xf0,0x90,0xff,0xf0,0xe0,0x30,
+0xe4,0x08,0x74,0x01,0x90,0xfd,0x41,0xf0,0x80,0x05,0xe4,0x90,0xfd,0x41,0xf0,0x7d,
+0x0a,0x7c,0x00,0x12,0x24,0xb1,0x12,0x31,0x08,0x22,0x12,0x30,0x85,0x90,0xfd,0x41,
+0xe0,0x14,0x70,0x0e,0x90,0xff,0xf0,0xe0,0x44,0x10,0xf0,0x7c,0x00,0x12,0x25,0x4a,
+0x80,0x19,0x90,0xfd,0x41,0xe0,0x70,0x0e,0x90,0xff,0xf0,0xe0,0x54,0xef,0xf0,0x7c,
+0x00,0x12,0x25,0x4a,0x80,0x05,0x7c,0x17,0x12,0x25,0x4a,0x12,0x31,0x08,0x22,0x90,
+0xff,0xf0,0xe0,0x54,0xab,0xf0,0x90,0xff,0xf0,0xe0,0x44,0x20,0xf0,0x22,0x8c,0x37,
+0x8d,0x36,0x78,0x7c,0xed,0xf6,0x08,0xec,0xf6,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,
+0x00,0x05,0x12,0x01,0xec,0x78,0x7a,0xf6,0x78,0x7c,0xe6,0xfd,0x08,0xe6,0xfc,0xed,
+0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x04,0x12,0x01,0xec,0x54,0x0f,0xfc,0x7d,0x7a,
+0x12,0x17,0x9d,0x78,0x7a,0xe6,0x70,0x0d,0xad,0x3a,0xae,0x39,0xaf,0x38,0xe4,0x12,
+0x03,0x0f,0x7c,0x08,0x22,0x90,0xff,0xf0,0xe0,0x54,0xfe,0xf0,0x90,0xff,0xf0,0xe0,
+0x54,0xfd,0xf0,0x80,0x1e,0x78,0x7c,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,
+0x7f,0x01,0x90,0x00,0x08,0x12,0x02,0x0e,0x25,0xe0,0x44,0x01,0x90,0xff,0xf3,0xf0,
+0x02,0x06,0xdb,0x78,0x7c,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,
+0x90,0x00,0x06,0x12,0x02,0x0e,0x54,0xfe,0x90,0xff,0xf3,0xf0,0x80,0x2b,0x78,0x7c,
+0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x08,0x12,0x02,
+0x0e,0xfa,0xeb,0x90,0xff,0xf1,0xf0,0x12,0x08,0xca,0x40,0x0d,0xad,0x3a,0xae,0x39,
+0xaf,0x38,0xe4,0x12,0x03,0x0f,0x7c,0x18,0x22,0x78,0x7c,0xe6,0xfd,0x08,0xe6,0xfc,
+0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x08,0x12,0x02,0x0e,0x90,0xff,0xf1,0xf0,
+0x12,0x08,0xca,0x40,0x0d,0xad,0x3a,0xae,0x39,0xaf,0x38,0xe4,0x12,0x03,0x0f,0x7c,
+0x18,0x22,0x78,0x7c,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,
+0x00,0x06,0x12,0x02,0x0e,0x44,0x01,0x90,0xff,0xf3,0xf0,0x78,0x7d,0xe6,0x24,0x03,
+0xf6,0x18,0xe6,0x34,0x00,0xf6,0x78,0x7a,0xe6,0x24,0xfe,0x50,0x09,0x90,0xff,0xf0,
+0xe0,0x54,0xfd,0xf0,0x80,0x07,0x90,0xff,0xf0,0xe0,0x44,0x02,0xf0,0xe4,0x90,0xff,
+0xf1,0xf0,0x78,0x7b,0x76,0x00,0x78,0x7a,0xe6,0x24,0xff,0xfc,0xe4,0x34,0xff,0xfd,
+0x78,0x7b,0xe6,0x7f,0x00,0xfe,0xec,0xd3,0x9e,0xef,0x64,0x80,0xcd,0x64,0x80,0x9d,
+0x40,0x2f,0x12,0x08,0xaf,0x40,0x0f,0x78,0x7b,0xe6,0xad,0x3a,0xae,0x39,0xaf,0x38,
+0x12,0x03,0x0f,0x7c,0x18,0x22,0x90,0xff,0xf2,0xe0,0xfc,0x78,0x7c,0x86,0x83,0x08,
+0x86,0x82,0xec,0xf0,0x78,0x7b,0x06,0xa3,0x78,0x7c,0xa6,0x83,0x08,0xa6,0x82,0x80,
+0xb5,0x12,0x08,0xaf,0x40,0x0f,0x78,0x7b,0xe6,0xad,0x3a,0xae,0x39,0xaf,0x38,0x12,
+0x03,0x0f,0x7c,0x18,0x22,0x90,0xff,0xf2,0xe0,0xfc,0x78,0x7c,0x86,0x83,0x08,0x86,
+0x82,0xec,0xf0,0x78,0x7a,0xe6,0xad,0x3a,0xae,0x39,0xaf,0x38,0x12,0x03,0x0f,0x7c,
+0x00,0x22,0x8c,0x37,0x8d,0x36,0x78,0x7c,0xed,0xf6,0x08,0xec,0xf6,0xed,0xfe,0xec,
+0xfd,0x7f,0x01,0x90,0x00,0x05,0x12,0x01,0xec,0x78,0x7b,0xf6,0x78,0x7c,0xe6,0xfd,
+0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x04,0x12,0x01,0xec,0x54,
+0x0f,0xfc,0x7d,0x7b,0x12,0x17,0x9d,0x78,0x7b,0xe6,0x70,0x03,0x7c,0x08,0x22,0x90,
+0xff,0xf0,0xe0,0x54,0xfe,0xf0,0x90,0xff,0xf0,0xe0,0x54,0xfd,0xf0,0x80,0x1b,0x78,
+0x7c,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x08,0x12,
+0x02,0x0e,0x25,0xe0,0x90,0xff,0xf3,0xf0,0x80,0x5b,0x78,0x7c,0xe6,0xfd,0x08,0xe6,
+0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x90,0x00,0x06,0x12,0x02,0x0e,0x54,0xfe,0x90,
+0xff,0xf3,0xf0,0x80,0x21,0x78,0x7c,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,0xfd,
+0x7f,0x01,0x90,0x00,0x08,0x12,0x02,0x0e,0xfa,0xeb,0x90,0xff,0xf1,0xf0,0x12,0x08,
+0xca,0x40,0x03,0x7c,0x18,0x22,0x78,0x7c,0xe6,0xfd,0x08,0xe6,0xfc,0xed,0xfe,0xec,
+0xfd,0x7f,0x01,0x90,0x00,0x08,0x12,0x02,0x0e,0x90,0xff,0xf1,0xf0,0x12,0x08,0xca,
+0x40,0x03,0x7c,0x18,0x22,0x78,0x7d,0xe6,0x24,0x0a,0xf6,0x18,0xe6,0x34,0x00,0xf6,
+0x78,0x7a,0x76,0x00,0x78,0x7b,0xe6,0x24,0xff,0xfc,0xe4,0x34,0xff,0xfd,0x78,0x7a,
+0xe6,0x7f,0x00,0xfe,0xec,0xd3,0x9e,0xef,0x64,0x80,0xcd,0x64,0x80,0x9d,0x40,0x21,
+0x78,0x7c,0x86,0x83,0x08,0x86,0x82,0xe0,0x90,0xff,0xf1,0xf0,0x12,0x08,0xca,0x40,
+0x03,0x7c,0x18,0x22,0x78,0x7a,0x06,0x78,0x7d,0x06,0xe6,0x18,0x70,0x01,0x06,0x80,
+0xc3,0x90,0xff,0xf0,0xe0,0x44,0x01,0xf0,0x78,0x7c,0x86,0x83,0x08,0x86,0x82,0xe0,
+0x90,0xff,0xf1,0xf0,0x12,0x08,0xca,0x40,0x03,0x7c,0x18,0x22,0x7c,0x00,0x22,0x90,
+0xff,0xf0,0xe0,0x20,0xe7,0x12,0x90,0xff,0xf0,0xe0,0x30,0xe5,0x09,0x90,0xff,0xf0,
+0xe0,0x44,0x20,0xf0,0xc3,0x22,0x80,0xe7,0xd3,0x22,0x90,0xff,0xf0,0xe0,0x20,0xe3,
+0x12,0x90,0xff,0xf0,0xe0,0x30,0xe5,0x09,0x90,0xff,0xf0,0xe0,0x44,0x20,0xf0,0xc3,
+0x22,0x80,0xe7,0xd3,0x22,0x8c,0x42,0x8d,0x41,0x7c,0x00,0xed,0x54,0xf0,0xfd,0xec,
+0x70,0x03,0xed,0x64,0x30,0x70,0x05,0x75,0x3e,0x03,0x80,0x03,0x75,0x3e,0x04,0xac,
+0x3e,0x12,0x0f,0x7c,0x75,0x83,0x00,0x85,0x83,0x40,0xe5,0x41,0x54,0x0f,0xf5,0x3f,
+0xe5,0x40,0x70,0x04,0xe5,0x3f,0x64,0x03,0x70,0x35,0xe5,0x3e,0x24,0xfd,0x75,0xf0,
+0x0a,0xa4,0x24,0x0a,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0xe0,0x30,0xe6,0x05,0x12,
+0x10,0x67,0x80,0x19,0xe5,0x3e,0x24,0x97,0xf8,0xc6,0x54,0xfb,0xf6,0x78,0xa3,0xe6,
+0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0x74,0x0f,0xf0,0x80,0x59,0xe5,
+0x40,0x70,0x04,0xe5,0x3f,0x64,0x04,0x70,0x48,0xe5,0x3e,0x24,0xfd,0x75,0xf0,0x0a,
+0xa4,0x24,0x0a,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0xe0,0x30,0xe5,0x07,0xac,0x42,
+0xad,0x41,0x12,0x1c,0x93,0xe5,0x42,0x30,0xe2,0x15,0x78,0xa7,0xe6,0x30,0xe0,0x0f,
+0x78,0xa7,0xe6,0x30,0xe1,0x09,0xe4,0xff,0x04,0xfe,0x7c,0x04,0x12,0x31,0x9a,0x78,
+0xa3,0xe6,0x24,0x06,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0x74,0x0f,0xf0,0x80,
+0x07,0xe4,0xfc,0x7d,0xee,0x12,0x1c,0x93,0xc2,0x03,0x22,0x12,0x30,0x85,0x12,0x0f,
+0x7c,0x78,0xa3,0xe6,0x24,0x06,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x90,
+0xfd,0x40,0xf0,0x78,0xa3,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,
+0xe0,0x90,0xfd,0x41,0xf0,0xc2,0x03,0x7d,0x02,0x7c,0x00,0x12,0x24,0xb1,0x12,0x31,
+0x08,0x22,0x12,0x30,0x85,0x78,0x8f,0xec,0xf6,0xec,0x24,0x97,0xf8,0xe6,0x30,0xe1,
+0x07,0x7c,0x13,0x12,0x25,0x4a,0x80,0x0f,0x90,0xfd,0x41,0xe0,0xfd,0x78,0x8f,0xe6,
+0xfc,0x12,0x13,0xfd,0x12,0x25,0x4a,0x12,0x31,0x08,0x22,0x12,0x30,0x85,0x78,0x8f,
+0xec,0xf6,0x7d,0x00,0x12,0x0f,0x0b,0x12,0x25,0x4a,0x12,0x31,0x08,0x22,0x12,0x30,
+0x85,0x78,0x8f,0xec,0xf6,0xec,0x24,0x97,0xf8,0xe6,0x30,0xe2,0x07,0x7c,0x13,0x12,
+0x25,0x4a,0x80,0x1b,0x78,0x8f,0xe6,0x24,0x97,0xf8,0xe6,0x20,0xe1,0x07,0x7c,0x12,
+0x12,0x25,0x4a,0x80,0x0a,0x78,0x8f,0xe6,0xfc,0x12,0x14,0x21,0x12,0x25,0x4a,0x12,
+0x31,0x08,0x22,0x12,0x30,0x85,0x78,0x8f,0xec,0xf6,0xec,0x24,0x97,0xf8,0xe6,0x20,
+0xe2,0x07,0x7c,0x11,0x12,0x25,0x4a,0x80,0x0a,0x78,0x8f,0xe6,0xfc,0x12,0x15,0x22,
+0x12,0x25,0x4a,0x12,0x31,0x08,0x22,0x12,0x30,0x85,0x78,0x8f,0xec,0xf6,0x12,0x0f,
+0x7c,0x78,0xa3,0xe6,0x24,0x09,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x90,
+0xfd,0x47,0xf0,0x78,0xa3,0xe6,0x24,0x0a,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,
+0xe0,0x90,0xfd,0x48,0xf0,0x78,0xa3,0xe6,0x24,0x03,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0xfc,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xe0,0xf5,0x5c,0x78,0xa3,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xe0,0xf5,0x5d,0x8c,0x5b,0xe4,0xec,0x33,0x33,0x54,0x01,0x78,0x8f,0xf6,0x60,
+0x08,0xe5,0x5c,0x30,0xe1,0x03,0x78,0x8f,0x06,0x78,0x8f,0xe6,0x90,0xfd,0x49,0xf0,
+0x78,0xa1,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xfd,0xa3,
+0xe0,0x54,0x0c,0xfc,0xed,0x54,0xe6,0x8c,0x5f,0xf5,0x5e,0xe5,0x5b,0x30,0xe5,0x03,
+0x43,0x5f,0x01,0xe5,0x5c,0x20,0xe5,0x0e,0xe5,0x5b,0x54,0x7f,0x70,0x08,0xe5,0x5b,
+0x20,0xe7,0x03,0x43,0x5f,0x02,0xe5,0x5b,0x30,0xe3,0x03,0x43,0x5f,0x10,0xe5,0x5b,
+0x30,0xe2,0x03,0x43,0x5f,0x20,0xe5,0x5b,0x54,0x03,0x60,0x03,0x43,0x5f,0x40,0xe5,
+0x5b,0x30,0xe1,0x03,0x43,0x5f,0x80,0xe5,0x5b,0x30,0xe4,0x03,0x43,0x5e,0x01,0xe5,
+0x5b,0x30,0xe6,0x03,0x43,0x5e,0x08,0xe5,0x5c,0x20,0xe4,0x0e,0xe5,0x5b,0x54,0x7f,
+0x70,0x08,0xe5,0x5b,0x20,0xe7,0x03,0x43,0x5e,0x10,0x53,0x5f,0xfb,0x53,0x5e,0xf9,
+0xad,0x5e,0xe5,0x5f,0x90,0xfd,0x42,0xcd,0xf0,0xa3,0xcd,0xf0,0xe5,0x5d,0x30,0xe3,
+0x0d,0xe5,0x5d,0x54,0x30,0xc4,0x54,0x0f,0x90,0xfd,0x45,0xf0,0x80,0x05,0xe4,0x90,
+0xfd,0x45,0xf0,0xe5,0x5d,0x54,0x03,0x90,0xfd,0x44,0xf0,0xe5,0x5d,0x54,0x04,0xc3,
+0x13,0x90,0xfd,0x46,0xf0,0x90,0xfd,0x44,0xe0,0x70,0x0e,0x7d,0x3d,0x7e,0xfd,0x7f,
+0x01,0x74,0x01,0x90,0x00,0x09,0x12,0x01,0x42,0x78,0xa3,0xe6,0x24,0x08,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x7c,0x00,0xfd,0x78,0xa3,0xe6,0x24,0x07,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x7f,0x00,0x4c,0xfe,0xef,0x4d,0x90,0xfd,
+0x40,0xf0,0xa3,0xce,0xf0,0xce,0xc2,0x03,0x7d,0x0a,0x7c,0x00,0x12,0x24,0xb1,0x12,
+0x31,0x08,0x22,0x12,0x30,0x85,0x78,0x8f,0xec,0xf6,0x78,0x94,0x76,0x01,0x08,0x76,
+0xfd,0x08,0x76,0x40,0x78,0x91,0x76,0x0c,0x78,0x94,0x12,0x04,0x65,0x12,0x02,0x14,
+0x78,0x92,0xcb,0xf6,0xcb,0x08,0xf6,0x7f,0x00,0xef,0x24,0xeb,0x40,0x1f,0xe4,0xef,
+0x25,0xe0,0x90,0x34,0xbf,0xfd,0x93,0xcd,0x04,0x93,0x78,0x93,0x66,0x70,0x03,0xed,
+0x18,0x66,0x70,0x06,0x78,0x91,0x76,0x00,0x80,0x03,0x0f,0x80,0xdc,0x78,0x90,0xef,
+0xf6,0x78,0x94,0x12,0x04,0x65,0x90,0x00,0x02,0x12,0x02,0x0e,0x78,0x92,0xcb,0xf6,
+0xcb,0x08,0xf6,0x54,0x04,0xcb,0x54,0x06,0x4b,0x60,0x04,0x78,0x91,0x76,0x0b,0x78,
+0x93,0xe6,0x30,0xe3,0x13,0x78,0x94,0x12,0x04,0x65,0x90,0x00,0x05,0x12,0x01,0xec,
+0x24,0xfb,0x50,0x04,0x78,0x91,0x76,0x0d,0x78,0x93,0xe6,0x54,0xc0,0x7d,0x00,0x64,
+0xc0,0x4d,0x70,0x04,0x78,0x91,0x76,0x0b,0x78,0x94,0x12,0x04,0x65,0x90,0x00,0x04,
+0x12,0x01,0xec,0x24,0xfc,0x50,0x04,0x78,0x91,0x76,0x0f,0x78,0x94,0x12,0x04,0x65,
+0x90,0x00,0x06,0x12,0x01,0xec,0x24,0xfd,0x50,0x04,0x78,0x91,0x76,0x0e,0x78,0x94,
+0x12,0x04,0x65,0x90,0x00,0x09,0x12,0x01,0xec,0x24,0xfd,0x50,0x04,0x78,0x91,0x76,
+0x0a,0x78,0x91,0xe6,0x70,0x2a,0x78,0x8f,0xe6,0xfc,0x12,0x0f,0x7c,0x78,0x94,0x12,
+0x04,0x65,0x78,0xa1,0xe6,0xf9,0x78,0xa0,0xe6,0xfa,0x7b,0x01,0x74,0x0a,0x78,0x00,
+0x12,0x03,0x3f,0xc2,0x03,0x78,0x8f,0xe6,0xfc,0x12,0x11,0x23,0x78,0x91,0xec,0xf6,
+0x78,0x91,0xe6,0xfc,0x12,0x25,0x4a,0x12,0x31,0x08,0x22,0x12,0x30,0x85,0x78,0x8f,
+0xec,0xf6,0x12,0x0f,0x7c,0x78,0x8f,0xe6,0x24,0xfd,0x75,0xf0,0x0a,0xa4,0x24,0x1c,
+0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0xac,0x82,0xad,0x83,0x78,0xa0,0x86,0x83,0x08,
+0x86,0x82,0xec,0xf9,0xed,0xfa,0x7b,0x0a,0x78,0x01,0x12,0x03,0xa7,0xc2,0x03,0x78,
+0x8f,0xe6,0xfc,0x12,0x11,0x23,0x12,0x31,0x08,0x22,0x8d,0x2b,0x8c,0x2a,0xed,0x60,
+0x40,0x75,0x27,0x01,0x75,0x29,0x48,0x75,0x28,0xff,0xe5,0x2a,0x24,0xfd,0xfc,0xe4,
+0x34,0xff,0xfd,0xec,0x7c,0x03,0x25,0xe0,0xcd,0x33,0xcd,0xdc,0xf9,0xfc,0xe5,0x29,
+0x2c,0xf5,0x29,0xe5,0x28,0x3d,0xf5,0x28,0xad,0x29,0xae,0x28,0xaf,0x27,0x74,0x80,
+0x90,0x00,0x06,0x12,0x03,0x17,0x74,0x80,0x90,0x00,0x02,0x12,0x03,0x17,0x12,0x0f,
+0xd3,0xe5,0x2b,0x14,0x60,0x3b,0x75,0x27,0x01,0x75,0x29,0x08,0x75,0x28,0xff,0xe5,
+0x2a,0x24,0xfd,0xfc,0xe4,0x34,0xff,0xfd,0xec,0x7c,0x03,0x25,0xe0,0xcd,0x33,0xcd,
+0xdc,0xf9,0xfc,0xe5,0x29,0x2c,0xf5,0x29,0xe5,0x28,0x3d,0xf5,0x28,0xad,0x29,0xae,
+0x28,0xaf,0x27,0xe4,0x90,0x00,0x06,0x12,0x03,0x17,0xe4,0x90,0x00,0x02,0x12,0x03,
+0x17,0x22,0x12,0x30,0x85,0x78,0x8f,0xec,0xf6,0xec,0x24,0x97,0xf8,0xe6,0x30,0xe2,
+0x09,0x78,0x8f,0xe6,0xfc,0x12,0x15,0x22,0xd2,0x00,0x78,0x8f,0xe6,0xfc,0x12,0x0f,
+0x7c,0x78,0x90,0x76,0x00,0x90,0xfd,0x41,0xe0,0x30,0xe7,0x04,0x78,0x90,0x76,0x01,
+0x78,0x90,0xe6,0xfd,0x78,0x8f,0xe6,0xfc,0x12,0x0d,0x3a,0xc2,0x03,0x30,0x00,0x07,
+0x78,0x8f,0xe6,0xfc,0x12,0x14,0x21,0x7c,0x00,0x12,0x25,0x4a,0x12,0x31,0x08,0x22,
+0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x44,0x01,
+0xf0,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x30,
+0xe0,0x02,0x80,0xed,0x78,0xa3,0xe6,0x24,0x0b,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xe0,0x54,0xf8,0xf0,0x78,0xa3,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x44,0x80,0xf0,0x22,0xc2,0x03,0x8c,0x58,0x12,0x0f,0x7c,0x78,0xa0,
+0x86,0x83,0x08,0x86,0x82,0x79,0xee,0x7a,0x34,0x7b,0x0a,0x78,0x01,0x12,0x03,0xf5,
+0x12,0x0e,0x10,0xac,0x58,0x7d,0x02,0x12,0x0d,0x3a,0xc2,0x03,0xac,0x58,0x12,0x11,
+0x23,0x22,0x8d,0x53,0x8e,0x52,0x8f,0x51,0x8c,0x50,0x12,0x0f,0x7c,0x75,0x4f,0x00,
+0x78,0xa3,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x20,0xe4,
+0x16,0xe5,0x4f,0x24,0xf6,0x40,0x10,0x05,0x4f,0xc2,0x03,0x7c,0x18,0x12,0x32,0x48,
+0xac,0x50,0x12,0x0f,0x7c,0x80,0xd9,0x78,0xa3,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xe0,0x20,0xe4,0x05,0xc2,0x03,0x7c,0x02,0x22,0x78,0xa3,0xe6,
+0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0x0f,0x60,0x16,0x78,
+0xa3,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0x0f,0xf0,
+0xc2,0x03,0x7c,0x01,0x22,0x78,0xa2,0x86,0x83,0x08,0x86,0x82,0xe0,0xad,0x53,0xae,
+0x52,0xaf,0x51,0x12,0x03,0x0f,0xc2,0x03,0x7c,0x00,0x22,0x8d,0x31,0x8c,0x30,0x12,
+0x15,0x22,0xe5,0x31,0x60,0x20,0xe5,0x30,0xb4,0x03,0x0c,0x7c,0x01,0x12,0x24,0x7c,
+0x7c,0x81,0x12,0x24,0x7c,0x80,0x0f,0xe5,0x30,0xb4,0x04,0x0a,0x7c,0x02,0x12,0x24,
+0x7c,0x7c,0x82,0x12,0x24,0x7c,0xac,0x30,0x12,0x0f,0x7c,0xe5,0x31,0x60,0x1a,0x78,
+0xa4,0x86,0x83,0x08,0x86,0x82,0xe0,0x54,0xe7,0xf0,0xa3,0xa3,0xa3,0xa3,0xe0,0x54,
+0xe7,0xf0,0xac,0x30,0x7d,0x02,0x12,0x0d,0x3a,0x78,0xa0,0x86,0x83,0x08,0x86,0x82,
+0x79,0xf8,0x7a,0x34,0x7b,0x0a,0x78,0x01,0x12,0x03,0xf5,0xc2,0x03,0xe5,0x30,0x24,
+0x97,0xf8,0xc6,0x54,0xfd,0xf6,0xac,0x30,0x12,0x11,0x23,0x22,0x8c,0x26,0x30,0x03,
+0x05,0x12,0x31,0xe7,0x80,0xf8,0x7c,0x0a,0x12,0x30,0xfa,0xd2,0x03,0xe5,0x26,0x24,
+0xfd,0x78,0x9d,0xf6,0x70,0x09,0x78,0xa4,0x76,0xff,0x08,0x76,0xe0,0x80,0x07,0x78,
+0xa4,0x76,0xff,0x08,0x76,0xe2,0x78,0x9d,0xe6,0x75,0xf0,0x10,0xa4,0xad,0xf0,0xfc,
+0x24,0xa0,0x78,0xa3,0xf6,0xed,0x34,0xff,0x18,0xf6,0x78,0x9d,0xe6,0x75,0xf0,0x0a,
+0xa4,0x24,0x08,0xfc,0xe4,0x34,0xfd,0xfd,0x78,0xa0,0xed,0xf6,0x08,0xec,0xf6,0x12,
+0x31,0x93,0x22,0x78,0xa3,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,
+0xe0,0x30,0xe7,0x22,0x78,0xa3,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xe0,0x54,0x7f,0xf0,0x78,0xa3,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x44,0x80,0xf0,0x22,0x78,0xa4,0x86,0x83,0x08,0x86,0x82,0xe0,0x54,
+0x7f,0xf0,0xad,0x83,0xe5,0x82,0x24,0x04,0xfc,0xe4,0x3d,0x8c,0x82,0xf5,0x83,0xe0,
+0x54,0x7f,0xf0,0x78,0xa3,0xe6,0x24,0x0b,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,
+0xe0,0x54,0xf8,0xf0,0x78,0xa5,0xe6,0x24,0x01,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xe0,0x44,0x03,0xf0,0x78,0xa5,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x44,0x03,0xf0,0x78,0xa3,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0x74,0x0f,0xf0,0x22,0x78,0xa4,0x86,0x83,0x08,0x86,0x82,0xe0,0x54,
+0x3f,0xf0,0xad,0x83,0xe5,0x82,0x24,0x04,0xfc,0xe4,0x3d,0x8c,0x82,0xf5,0x83,0xe0,
+0x54,0x3f,0xf0,0x78,0x9d,0xe6,0x24,0x9e,0xf8,0xe6,0xfc,0x78,0xa5,0xe6,0x24,0x01,
+0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x78,0x9d,0xe6,0x24,0x9e,0xf8,
+0xe6,0xfc,0x78,0xa5,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,
+0xf0,0x78,0xa3,0xe6,0x24,0x0b,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,
+0xfb,0x44,0x02,0xf5,0x26,0x78,0xa1,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x30,0xe5,0x03,0x43,0x26,0x01,0x78,0xa3,0xe6,0x24,0x05,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x30,0xe0,0x03,0x12,0x0f,0xd3,0xe5,0x26,0xfc,
+0x78,0xa3,0xe6,0x24,0x0b,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x78,
+0xa3,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0x74,0x0f,0xf0,0x78,
+0xa4,0x86,0x83,0x08,0x86,0x82,0xe0,0x44,0x80,0xf0,0xa3,0xa3,0xa3,0xa3,0xe0,0x44,
+0x80,0xf0,0x22,0x8c,0x2a,0x12,0x0f,0x7c,0x78,0xa1,0xe6,0x24,0x08,0xf5,0x82,0x18,
+0xe6,0x34,0x00,0xf5,0x83,0xe0,0xfc,0x78,0xa3,0xe6,0x24,0x0a,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xec,0xf0,0x78,0xa1,0xe6,0x24,0x07,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xe0,0xfc,0x78,0xa3,0xe6,0x24,0x09,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xec,0xf0,0x78,0xa0,0x86,0x83,0x08,0x86,0x82,0xe0,0xfd,0xa3,0xe0,0xfc,
+0xed,0xfe,0x78,0xa3,0xe6,0x24,0x08,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xee,
+0xf0,0xec,0xfe,0x78,0xa3,0xe6,0x24,0x07,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,
+0xee,0xf0,0x8c,0x29,0x8d,0x28,0xc3,0xec,0x94,0x02,0xed,0x94,0x06,0x40,0x05,0x75,
+0x27,0x7c,0x80,0x33,0xd3,0xe5,0x29,0x94,0x81,0xe5,0x28,0x94,0x01,0x40,0x05,0x75,
+0x27,0x3c,0x80,0x23,0xd3,0xe5,0x29,0x94,0xc0,0xe5,0x28,0x94,0x00,0x40,0x05,0x75,
+0x27,0x18,0x80,0x13,0xd3,0xe5,0x29,0x94,0x30,0xe5,0x28,0x94,0x00,0x40,0x05,0x75,
+0x27,0x0c,0x80,0x03,0x75,0x27,0x08,0xaf,0x27,0xe4,0xef,0x54,0x7c,0x44,0x83,0xff,
+0x8f,0x27,0xe5,0x27,0xfc,0x78,0xa5,0xe6,0x24,0x01,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xec,0xf0,0xe5,0x27,0xfc,0x78,0xa5,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xec,0xf0,0xe5,0x27,0xfc,0x78,0x9d,0xe6,0x24,0x9e,0xf8,0xec,
+0xf6,0x78,0xa3,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xf5,
+0x27,0x78,0xa1,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,0xe0,
+0x30,0xe3,0x17,0x53,0x27,0xc7,0x78,0xa1,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xe0,0x90,0x34,0xe9,0x93,0x42,0x27,0x78,0xa1,0xe6,0x24,0x02,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x30,0xe7,0x05,0x43,0x27,0x40,0x80,0x03,
+0x53,0x27,0xbf,0x53,0x27,0xfb,0x78,0xa1,0xe6,0x24,0x06,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xe0,0x60,0x03,0x43,0x27,0x04,0x53,0x27,0xfc,0x78,0xa1,0xe6,0x24,
+0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x42,0x27,0x43,0x27,0x80,0xe5,
+0x27,0xfc,0x78,0xa3,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,
+0xf0,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xf5,
+0x27,0x78,0xa1,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,0xe0,
+0x30,0xe1,0x05,0x53,0x27,0xdf,0x80,0x03,0x43,0x27,0x20,0x78,0xa1,0xe6,0x24,0x02,
+0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x30,0xe4,0x05,0x53,0x27,0xef,0x80,
+0x03,0x43,0x27,0x10,0x78,0xa1,0xe6,0x24,0x09,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xe0,0xb4,0x02,0x03,0x43,0x27,0x02,0xe5,0x27,0xfc,0x78,0xa3,0xe6,0x24,0x04,
+0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x78,0xa3,0xe6,0x24,0x03,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xf5,0x27,0x78,0xa1,0xe6,0x24,0x09,0xf5,
+0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x70,0x05,0x53,0x27,0x7f,0x80,0x03,0x43,
+0x27,0x80,0x78,0xa1,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,
+0xe0,0x30,0xe0,0x05,0x43,0x27,0x20,0x80,0x03,0x53,0x27,0xdf,0x78,0xa1,0xe6,0x24,
+0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x30,0xe3,0x05,0x43,0x27,0x40,
+0x80,0x03,0x53,0x27,0xbf,0x78,0xa1,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x30,0xe0,0x05,0x43,0x27,0x10,0x80,0x03,0x53,0x27,0xef,0x78,0xa1,
+0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,0xe0,0x30,0xe4,0x05,
+0x43,0x27,0x08,0x80,0x03,0x53,0x27,0xf7,0x78,0xa1,0xe6,0x24,0x02,0xf5,0x82,0x18,
+0xe6,0x34,0x00,0xf5,0x83,0xa3,0xe0,0x30,0xe5,0x05,0x43,0x27,0x04,0x80,0x03,0x53,
+0x27,0xfb,0x78,0xa1,0xe6,0x24,0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,
+0xe0,0x30,0xe6,0x05,0x43,0x27,0x01,0x80,0x03,0x53,0x27,0xfe,0x78,0xa1,0xe6,0x24,
+0x02,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xa3,0xe0,0x30,0xe7,0x05,0x43,0x27,
+0x02,0x80,0x03,0x53,0x27,0xfd,0xe5,0x27,0xfc,0x78,0xa3,0xe6,0x24,0x03,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0xc2,0x03,0x7c,0x00,0x22,0x8d,0x27,0x8c,
+0x26,0xed,0x54,0x03,0x14,0x60,0x03,0x7c,0x10,0x22,0xe5,0x27,0x54,0x7c,0x24,0xfc,
+0x40,0x03,0x7c,0x0b,0x22,0xe5,0x26,0x24,0x97,0xf8,0xc6,0x44,0x02,0xf6,0x7c,0x00,
+0x22,0x8c,0x30,0x12,0x0f,0x7c,0xe5,0x30,0x24,0x97,0xf8,0xe6,0x20,0xe2,0x4f,0xac,
+0x30,0x7d,0x02,0x12,0x0d,0x3a,0xe5,0x30,0x24,0xfe,0x44,0x28,0xfc,0x78,0xa4,0x86,
+0x83,0x08,0x86,0x82,0xec,0xf0,0xaf,0x83,0xe5,0x82,0x24,0x04,0xfe,0xe4,0x3f,0xff,
+0xec,0x8e,0x82,0x8f,0x83,0xf0,0x7c,0x03,0x8c,0x2c,0xe5,0x2c,0xfc,0x78,0xa5,0xe6,
+0x24,0x01,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0xe5,0x2c,0xfc,0x78,
+0xa5,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xec,0xf0,0x75,0x2d,
+0x01,0x75,0x2f,0x48,0x75,0x2e,0xff,0xe5,0x30,0x24,0xfd,0xfc,0xe4,0x34,0xff,0xfd,
+0xec,0x7c,0x03,0x25,0xe0,0xcd,0x33,0xcd,0xdc,0xf9,0xfc,0xe5,0x2f,0x2c,0xf5,0x2f,
+0xe5,0x2e,0x3d,0xf5,0x2e,0x78,0xa5,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x54,0xe7,0xf5,0x2c,0xad,0x2f,0xae,0x2e,0xaf,0x2d,0xe4,0x90,0x00,
+0x02,0x12,0x03,0x17,0xe4,0x90,0x00,0x06,0x12,0x03,0x17,0x12,0x01,0xe6,0x30,0xe5,
+0x03,0x43,0x2c,0x10,0xe5,0x2c,0xfc,0x78,0xa5,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xec,0xf0,0x12,0x10,0x67,0x78,0xa3,0xe6,0x24,0x06,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0xc2,0x03,0xfc,0xe5,0x30,0x24,0x97,0xf8,0xc6,
+0x44,0x04,0xf6,0x8c,0x2c,0xe5,0x30,0x54,0x0f,0xc4,0x54,0xf0,0x7e,0x00,0xff,0xee,
+0xef,0x44,0x04,0x7d,0x00,0xff,0xec,0x4e,0xfc,0xed,0x4f,0xfd,0x12,0x1c,0xfe,0x7c,
+0x00,0x22,0x8c,0x2f,0x12,0x0f,0x7c,0x12,0x10,0x07,0x78,0xa4,0x86,0x83,0x08,0x86,
+0x82,0xe0,0x54,0x08,0xf0,0xa3,0xa3,0xa3,0xa3,0xe0,0x54,0x08,0xf0,0xac,0x2f,0x7d,
+0x02,0x12,0x0d,0x3a,0xc2,0x03,0xe5,0x2f,0x24,0x97,0xf8,0xc6,0x54,0xfb,0xf6,0x7c,
+0x00,0x22,0x12,0x30,0x85,0x78,0x90,0xec,0xf6,0xec,0x24,0x97,0xf8,0xe6,0x30,0xe1,
+0x0a,0x7d,0x00,0x7c,0x13,0x12,0x24,0xb1,0x12,0x31,0x08,0x78,0x90,0xe6,0x24,0x97,
+0xf8,0xc6,0x44,0x01,0xf6,0x78,0x90,0xe6,0xfc,0x12,0x0f,0x7c,0x78,0x90,0xe6,0x24,
+0xfd,0x75,0xf0,0x0a,0xa4,0x24,0x1c,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0x78,0xa0,
+0xe6,0xfa,0x08,0xe6,0xf9,0x7b,0x0a,0x78,0x01,0x12,0x03,0xa7,0x78,0xa0,0x86,0x83,
+0x08,0x86,0x82,0x79,0xf8,0x7a,0x34,0x7b,0x0a,0x78,0x01,0x12,0x03,0xf5,0x12,0x0f,
+0xd3,0xc2,0x03,0x78,0x90,0xe6,0xfc,0x12,0x11,0x23,0x78,0x8f,0xec,0xf6,0xec,0x60,
+0x0a,0x7d,0x00,0x7c,0x08,0x12,0x24,0xb1,0x12,0x31,0x08,0x78,0x90,0xe6,0xfc,0x12,
+0x0f,0x7c,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,
+0x44,0x10,0x54,0xdf,0xfc,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xec,0xf0,0x78,0x8f,0xec,0xf6,0xc2,0x03,0x7c,0xc8,0x12,0x32,0x48,0x78,
+0x90,0xe6,0xfc,0x12,0x0f,0x7c,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,
+0x00,0xf5,0x83,0xe0,0x54,0xef,0xf0,0xc2,0x03,0x7c,0xc8,0x12,0x32,0x48,0x78,0x90,
+0xe6,0xfc,0x12,0x0f,0x7c,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,
+0xf5,0x83,0xe0,0x44,0x10,0xf0,0xc2,0x03,0x7c,0xc8,0x12,0x32,0x48,0x78,0x90,0xe6,
+0xfc,0x12,0x0f,0x7c,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,
+0x83,0xe0,0x44,0x20,0xf0,0xc2,0x03,0x7c,0xf0,0x12,0x32,0x48,0x78,0x90,0xe6,0xfc,
+0x12,0x0f,0x7c,0x78,0xa3,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,
+0xe0,0x30,0xe4,0x15,0xc2,0x03,0x78,0x90,0xe6,0x44,0x10,0x7f,0x00,0xfe,0x7c,0x07,
+0x12,0x31,0x9a,0x12,0x31,0x08,0x02,0x17,0x49,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,
+0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0xcf,0xf0,0xc2,0x03,0x7c,0xc8,0x12,0x32,
+0x48,0x78,0x90,0xe6,0xfc,0x12,0x0f,0x7c,0x78,0xa3,0xe6,0x24,0x04,0xf5,0x82,0x18,
+0xe6,0x34,0x00,0xf5,0x83,0xe0,0x44,0x30,0xf0,0xc2,0x03,0x7c,0xf0,0x12,0x32,0x48,
+0x78,0x90,0xe6,0xfc,0x12,0x0f,0x7c,0x78,0xa3,0xe6,0x24,0x05,0xf5,0x82,0x18,0xe6,
+0x34,0x00,0xf5,0x83,0xe0,0x30,0xe4,0x14,0xc2,0x03,0x78,0x90,0xe6,0x44,0x10,0x7f,
+0x00,0xfe,0x7c,0x07,0x12,0x31,0x9a,0x12,0x31,0x08,0x80,0x5d,0x78,0xa3,0xe6,0x24,
+0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0xef,0xf0,0x78,0xa3,0xe6,
+0x24,0x04,0xf5,0x82,0x18,0xe6,0x34,0x00,0xf5,0x83,0xe0,0x54,0xdf,0xf0,0x78,0x90,
+0xe6,0x24,0xfd,0x75,0xf0,0x0a,0xa4,0x24,0x1c,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,
+0xac,0x82,0xad,0x83,0x78,0xa0,0x86,0x83,0x08,0x86,0x82,0xec,0xf9,0xed,0xfa,0x7b,
+0x0a,0x78,0x01,0x12,0x03,0xa7,0xc2,0x03,0x78,0x90,0xe6,0xfc,0x12,0x11,0x23,0x7d,
+0x00,0x7c,0x0b,0x12,0x24,0xb1,0x12,0x31,0x08,0x22,0x12,0x30,0x85,0x90,0xff,0x91,
+0xe0,0x90,0xfd,0x41,0xf0,0x7d,0x02,0x7c,0x00,0x12,0x24,0xb1,0x12,0x31,0x08,0x22,
+0x12,0x30,0x85,0x90,0xfd,0x40,0xe0,0xf4,0xfc,0x90,0xff,0x91,0xe0,0x5c,0xf5,0x33,
+0x90,0xfd,0x41,0xe0,0xfc,0x90,0xfd,0x40,0xe0,0x5c,0x42,0x33,0xe5,0x33,0x90,0xff,
+0x91,0xf0,0x7c,0x00,0x12,0x25,0x4a,0x12,0x31,0x08,0x22,0x74,0x3c,0x90,0xfb,0xe8,
+0xf0,0x74,0x3e,0x90,0xfb,0xe8,0xf0,0xe4,0x90,0xfd,0x30,0xf0,0x22,0x8d,0x35,0x8c,
+0x34,0xec,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x02,0x80,0x28,0xb4,0x02,0x02,0x80,
+0x03,0xd3,0x40,0x08,0xa8,0x35,0xc6,0x25,0xe0,0xf6,0x80,0x18,0xb4,0x04,0x02,0x80,
+0x03,0xd3,0x40,0x0a,0xa8,0x35,0xc6,0x25,0xe0,0x25,0xe0,0xf6,0x80,0x06,0xa8,0x35,
+0x76,0x00,0x80,0x00,0x22,0x8c,0x3c,0x8d,0x3b,0xed,0xfe,0xec,0xfd,0x7f,0x01,0x75,
+0x60,0x06,0x75,0x61,0x00,0x90,0xfd,0x31,0x12,0x04,0x6e,0x12,0x01,0xe6,0xb4,0x80,
+0x02,0x80,0x06,0xd3,0x50,0x03,0x02,0x18,0x9e,0x90,0xfd,0x31,0x12,0x04,0x80,0x90,
+0x00,0x03,0x12,0x01,0xec,0x54,0xf0,0xb4,0x30,0x02,0x80,0x03,0xd3,0x40,0x5f,0x90,
+0xfd,0x31,0x12,0x04,0x80,0x90,0x00,0x08,0x12,0x02,0x0e,0xfa,0xfd,0xeb,0xfe,0x7f,
+0x01,0x90,0xfd,0x34,0x12,0x04,0x6e,0xee,0xcd,0x90,0x35,0x02,0xfc,0xe4,0x93,0xff,
+0x74,0x01,0x93,0xfe,0xf9,0xef,0xfa,0x7b,0x01,0xea,0xff,0xe9,0xfe,0xec,0xc3,0x9e,
+0xed,0x9f,0x40,0x25,0x90,0x35,0x04,0xe4,0x93,0xfd,0x74,0x01,0x93,0xfc,0xed,0xfe,
+0xec,0xfd,0x7f,0x01,0xee,0xcd,0xfc,0x90,0xfd,0x36,0xe0,0xd3,0x9c,0x90,0xfd,0x35,
+0xe0,0x9d,0x50,0x05,0x75,0x60,0x80,0x80,0x33,0x12,0x19,0xbc,0x80,0x2e,0xb4,0x60,
+0x02,0x80,0x03,0xd3,0x40,0x0b,0xac,0x3c,0xad,0x3b,0x12,0x07,0x82,0x8c,0x60,0x80,
+0x1b,0xb4,0x10,0x03,0xb3,0x40,0x10,0xc3,0xb4,0x20,0x03,0xb3,0x40,0x09,0xc3,0xb4,
+0x40,0x02,0x80,0x03,0xd3,0x40,0x00,0x75,0x60,0x81,0x80,0x00,0x80,0x75,0xb4,0x81,
+0x02,0x80,0x03,0xd3,0x40,0x6b,0x90,0xfd,0x31,0x12,0x04,0x80,0x90,0x00,0x03,0x12,
+0x01,0xec,0x54,0xf0,0xb4,0x30,0x02,0x80,0x03,0xd3,0x40,0x1d,0x90,0xfd,0x31,0x12,
+0x04,0x80,0x90,0x00,0x08,0x12,0x02,0x0e,0xfa,0xfd,0xeb,0xfe,0x7f,0x01,0x90,0xfd,
+0x37,0x12,0x04,0x6e,0x12,0x19,0x26,0x80,0x36,0xb4,0x60,0x02,0x80,0x03,0xd3,0x40,
+0x13,0x75,0x3a,0x61,0xe4,0xf5,0x39,0xf5,0x38,0xac,0x3c,0xad,0x3b,0x12,0x05,0xde,
+0x8c,0x60,0x80,0x1b,0xb4,0x10,0x03,0xb3,0x40,0x10,0xc3,0xb4,0x20,0x03,0xb3,0x40,
+0x09,0xc3,0xb4,0x40,0x02,0x80,0x03,0xd3,0x40,0x00,0x75,0x60,0x81,0x80,0x00,0x80,
+0x02,0x80,0x00,0xe5,0x60,0xfc,0x90,0xfd,0x31,0x12,0x04,0x80,0xec,0x90,0x00,0x02,
+0x12,0x03,0x17,0xac,0x61,0x22,0x90,0xfd,0x31,0x12,0x04,0x80,0x90,0x00,0x04,0x12,
+0x01,0xec,0x60,0x04,0x74,0x01,0x80,0x01,0xe4,0xa2,0xe0,0x92,0x01,0x90,0xfd,0x31,
+0x12,0x04,0x80,0xed,0x24,0x03,0xfd,0x50,0x01,0x0e,0x90,0xfd,0x34,0x12,0x04,0x6e,
+0x90,0xfd,0x31,0x12,0x04,0x80,0x90,0x00,0x05,0x12,0x01,0xec,0xf5,0x61,0x90,0x00,
+0x04,0x12,0x01,0xec,0x54,0x0f,0xfc,0x7d,0x61,0x12,0x17,0x9d,0xe5,0x61,0x70,0x04,
+0x75,0x60,0x08,0x22,0x75,0x60,0x00,0x78,0x7e,0x76,0x00,0x78,0x7e,0xe6,0xc3,0x95,
+0x61,0x50,0x38,0x90,0xfd,0x37,0x12,0x04,0x80,0x12,0x01,0xe6,0xfc,0x90,0xfd,0x34,
+0x12,0x04,0x80,0xec,0x12,0x03,0x0f,0x30,0x01,0x0e,0x90,0xfd,0x39,0xe0,0x04,0xf0,
+0x90,0xfd,0x38,0x70,0x03,0xe0,0x04,0xf0,0x78,0x7e,0x06,0x90,0xfd,0x36,0xe0,0x04,
+0xf0,0x90,0xfd,0x35,0x70,0x03,0xe0,0x04,0xf0,0x80,0xc0,0x22,0x90,0xfd,0x32,0xe0,
+0xfd,0xa3,0xe0,0xfc,0xed,0xfe,0xec,0xfd,0x7f,0x01,0xed,0x24,0x0a,0xfd,0x50,0x01,
+0x0e,0x90,0xfd,0x3a,0x12,0x04,0x6e,0x90,0xfd,0x31,0x12,0x04,0x80,0x90,0x00,0x04,
+0x12,0x01,0xec,0x54,0x0f,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x17,0x90,0xfd,0x3a,
+0x12,0x04,0x80,0x0d,0xed,0x70,0x01,0x0e,0x90,0xfd,0x37,0x12,0x04,0x6e,0x78,0x82,
+0x76,0x01,0x80,0x4e,0xb4,0x02,0x02,0x80,0x03,0xd3,0x40,0x19,0x90,0xfd,0x3a,0x12,
+0x04,0x80,0xed,0x24,0x02,0xfd,0x50,0x01,0x0e,0x90,0xfd,0x37,0x12,0x04,0x6e,0x78,
+0x82,0x76,0x02,0x80,0x2d,0xb4,0x04,0x02,0x80,0x03,0xd3,0x40,0x19,0x90,0xfd,0x3a,
+0x12,0x04,0x80,0xed,0x24,0x04,0xfd,0x50,0x01,0x0e,0x90,0xfd,0x37,0x12,0x04,0x6e,
+0x78,0x82,0x76,0x04,0x80,0x0c,0xb4,0x00,0x02,0x80,0x03,0xd3,0x40,0x00,0x75,0x60,
+0x08,0x22,0x90,0xfd,0x31,0x12,0x04,0x80,0x90,0x00,0x05,0x12,0x01,0xec,0xf5,0x61,
+0x78,0x7f,0x76,0x00,0x78,0x7f,0xe6,0xc3,0x95,0x61,0x40,0x03,0x02,0x1b,0x24,0x78,
+0x80,0x76,0x00,0x78,0x80,0xe6,0xc3,0x78,0x82,0x96,0x50,0x76,0x90,0xfd,0x34,0x12,
+0x04,0x80,0x12,0x01,0xe6,0xfc,0x90,0xfd,0x3a,0x12,0x04,0x89,0x12,0x01,0xe0,0xf4,
+0x5c,0xfc,0x12,0x01,0xe0,0xf8,0x90,0xfd,0x37,0x12,0x04,0x80,0xe8,0xc0,0xe0,0x12,
+0x01,0xe6,0xc8,0xd0,0xe0,0xc8,0x58,0x4c,0xfc,0x90,0xfd,0x34,0x12,0x04,0x80,0xec,
+0x12,0x03,0x0f,0x78,0x81,0xec,0xf6,0x90,0xfd,0x39,0xe0,0x04,0xf0,0x90,0xfd,0x38,
+0x70,0x03,0xe0,0x04,0xf0,0x09,0xe9,0x70,0x01,0x0a,0x90,0xfd,0x3a,0x12,0x04,0x77,
+0x90,0xfd,0x31,0x12,0x04,0x80,0x90,0x00,0x04,0x12,0x01,0xec,0x30,0xe4,0x0e,0x90,
+0xfd,0x36,0xe0,0x04,0xf0,0x90,0xfd,0x35,0x70,0x03,0xe0,0x04,0xf0,0x78,0x80,0x06,
+0x80,0x81,0x78,0x82,0xe6,0xfd,0xe4,0xfe,0xff,0xee,0xcd,0xfc,0x90,0xfd,0x39,0xe0,
+0x2c,0xf0,0x90,0xfd,0x38,0xe0,0x3d,0xf0,0x78,0x82,0xe6,0xfd,0xe4,0xfe,0xff,0xee,
+0xcd,0xfc,0x90,0xfd,0x3c,0xe0,0x2c,0xf0,0x90,0xfd,0x3b,0xe0,0x3d,0xf0,0x78,0x7f,
+0x06,0x02,0x1a,0x64,0x75,0x60,0x00,0x22,0xe5,0x3d,0x05,0x3d,0x04,0x70,0x02,0xb2,
+0xb0,0x22,0xc0,0xe0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0xd0,0xe8,0xc0,0xe0,0xe9,
+0xc0,0xe0,0xea,0xc0,0xe0,0xeb,0xc0,0xe0,0xec,0xc0,0xe0,0xed,0xc0,0xe0,0xee,0xc0,
+0xe0,0xef,0xc0,0xe0,0x90,0xff,0x92,0xe0,0x12,0x01,0xb7,0x1b,0x80,0x30,0x1b,0x80,
+0x32,0x1b,0x8f,0x38,0x1b,0xa1,0x3a,0x1b,0xb3,0x3e,0x1b,0xcb,0x44,0x1b,0xbf,0x46,
+0x1b,0xd7,0x50,0x1c,0x19,0x52,0x1b,0xf8,0x54,0x1c,0x3a,0x56,0x00,0x00,0x1c,0x5b,
+0x90,0xff,0x92,0xe0,0x7f,0x00,0xfe,0x7c,0x01,0x12,0x31,0x9a,0x02,0x1c,0x6b,0xe4,
+0xff,0x04,0xfe,0x7c,0x03,0x12,0x31,0x9a,0x74,0x20,0x90,0xff,0xfe,0xf0,0x02,0x1c,
+0x6b,0xe4,0xff,0x04,0xfe,0x7c,0x02,0x12,0x31,0x9a,0x74,0x40,0x90,0xff,0xfe,0xf0,
+0x02,0x1c,0x6b,0xe4,0xff,0x04,0xfe,0x7c,0x04,0x12,0x31,0x9a,0x02,0x1c,0x6b,0xe4,
+0xff,0x04,0xfe,0x7c,0x05,0x12,0x31,0x9a,0x02,0x1c,0x6b,0xe4,0xff,0x04,0xfe,0x7c,
+0x06,0x12,0x31,0x9a,0x02,0x1c,0x6b,0x90,0xff,0xa5,0xe0,0x7d,0x00,0x90,0xfd,0x00,
+0xcd,0xf0,0xa3,0xcd,0xf0,0x90,0xfd,0x01,0xe0,0xfc,0xf5,0x83,0x90,0xfd,0x00,0xe0,
+0x44,0x33,0xfd,0x12,0x1c,0xfe,0x80,0x73,0x90,0xff,0xb5,0xe0,0x7d,0x00,0x90,0xfd,
+0x02,0xcd,0xf0,0xa3,0xcd,0xf0,0x90,0xfd,0x03,0xe0,0xfc,0xf5,0x83,0x90,0xfd,0x02,
+0xe0,0x44,0x43,0xfd,0x12,0x1c,0xfe,0x80,0x52,0x90,0xff,0xa6,0xe0,0x7d,0x00,0x90,
+0xfd,0x04,0xcd,0xf0,0xa3,0xcd,0xf0,0x90,0xfd,0x05,0xe0,0xfc,0xf5,0x83,0x90,0xfd,
+0x04,0xe0,0x44,0x34,0xfd,0x12,0x1c,0xfe,0x80,0x31,0x90,0xff,0xb6,0xe0,0x7d,0x00,
+0x90,0xfd,0x06,0xcd,0xf0,0xa3,0xcd,0xf0,0x90,0xfd,0x07,0xe0,0xfc,0xf5,0x83,0x90,
+0xfd,0x06,0xe0,0x44,0x44,0xfd,0x12,0x1c,0xfe,0x80,0x10,0x90,0xff,0x92,0xe0,0x7d,
+0x00,0xfc,0xed,0x44,0xaa,0xfd,0x12,0x1c,0xfe,0x80,0x00,0xe4,0x90,0xff,0x92,0xf0,
+0xd0,0xe0,0xff,0xd0,0xe0,0xfe,0xd0,0xe0,0xfd,0xd0,0xe0,0xfc,0xd0,0xe0,0xfb,0xd0,
+0xe0,0xfa,0xd0,0xe0,0xf9,0xd0,0xe0,0xf8,0xd0,0xd0,0xd0,0x83,0xd0,0x82,0xd0,0xf0,
+0xd0,0xe0,0x32,0x05,0x81,0x05,0x81,0x05,0x81,0x05,0x81,0xa8,0x81,0x18,0x18,0x18,
+0xed,0xf6,0x08,0xec,0xf6,0x90,0xff,0x6a,0xe0,0x20,0xe7,0x02,0x80,0xf7,0x90,0xff,
+0x69,0xe0,0x7d,0x00,0xa8,0x81,0x18,0xcd,0xf6,0xcd,0x08,0xf6,0x7d,0x03,0xa8,0x81,
+0xe6,0x18,0xfc,0xe6,0xcc,0x25,0xe0,0xcc,0x33,0xcc,0xdd,0xf9,0xcc,0xf6,0xcc,0x08,
+0xf6,0xa8,0x81,0x18,0xe6,0x44,0xf8,0xf6,0xa8,0x81,0x18,0x18,0x18,0xe6,0xfd,0x08,
+0xe6,0xfc,0xa8,0x81,0x18,0x86,0x83,0x08,0x86,0x82,0xed,0xf0,0xa3,0xec,0xf0,0x74,
+0x02,0x90,0xff,0x6a,0xf0,0x15,0x81,0x15,0x81,0x15,0x81,0x15,0x81,0x22,0xe5,0x81,
+0x24,0x05,0xf5,0x81,0xe4,0xa8,0x81,0x18,0xf6,0xa8,0x81,0x18,0x18,0x18,0x18,0xed,
+0xf6,0x08,0xec,0xf6,0x90,0xfb,0xfd,0xe0,0x24,0xf8,0x50,0x03,0x02,0x1e,0x1f,0xe4,
+0xa8,0x81,0x18,0x18,0xf6,0xa8,0x81,0x18,0xe6,0xfe,0xa8,0x81,0x18,0x18,0x18,0x18,
+0xe6,0xfd,0x08,0xe6,0xfc,0x7f,0x00,0xef,0x24,0xf8,0x40,0x4d,0xe4,0xef,0x25,0xe0,
+0x24,0x85,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0xe0,0xfb,0xa3,0xe0,0x6c,0x70,0x03,
+0xfa,0xeb,0x6d,0x70,0x09,0x74,0x01,0xa8,0x81,0x18,0x18,0xf6,0x80,0x2b,0xe4,0xef,
+0x25,0xe0,0x24,0x85,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0x7a,0x00,0xe0,0x54,0xf0,
+0xcc,0xf8,0xcc,0xcd,0xf9,0xcd,0xfb,0x78,0x00,0xe9,0x54,0xf0,0xf9,0xea,0x68,0x70,
+0x02,0xeb,0x69,0x70,0x01,0x0e,0x0f,0x80,0xae,0xa8,0x81,0x18,0xee,0xf6,0xa8,0x81,
+0x18,0x18,0x18,0x18,0xed,0xf6,0x08,0xec,0xf6,0xa8,0x81,0xef,0xf6,0xa8,0x81,0x18,
+0x18,0xe6,0x70,0x79,0xa8,0x81,0x18,0xe6,0x24,0xf7,0x40,0x71,0xa8,0x81,0x18,0x18,
+0x18,0x18,0xe6,0x54,0x0f,0xa8,0x81,0xf6,0x64,0x04,0x60,0x17,0xa8,0x81,0xe6,0x64,
+0x03,0x60,0x10,0xa8,0x81,0x18,0x18,0x18,0x18,0xe6,0xfd,0x08,0xe6,0xfc,0x12,0x1c,
+0x93,0x80,0x4a,0x7c,0x0a,0x12,0x30,0xfa,0xa8,0x81,0x18,0x18,0x18,0x18,0xe6,0xfd,
+0x08,0xe6,0xfc,0x90,0xfb,0xfc,0xe0,0x25,0xe0,0x24,0x85,0xf5,0x82,0xe4,0x34,0xfd,
+0xf5,0x83,0xed,0xf0,0xa3,0xec,0xf0,0x90,0xfb,0xfc,0xe0,0xff,0xe4,0xef,0x04,0x54,
+0x07,0xff,0x90,0xfb,0xfc,0xf0,0x90,0xfb,0xfd,0xe0,0x04,0xf0,0x12,0x31,0x93,0x90,
+0xfb,0xfe,0xe0,0x70,0x08,0xe4,0xfe,0xff,0x7c,0x0f,0x12,0x31,0x9a,0x80,0x27,0x90,
+0xfb,0xff,0xe0,0x04,0xf0,0x54,0x3f,0x70,0x1d,0x90,0xfb,0xff,0xe0,0x44,0xfe,0x7d,
+0x00,0xfc,0x90,0xfb,0xfc,0xe0,0x25,0xe0,0x24,0x85,0xf5,0x82,0xe4,0x34,0xfd,0xf5,
+0x83,0xed,0xf0,0xa3,0xec,0xf0,0xe5,0x81,0x24,0xfb,0xf5,0x81,0x22,0x78,0x85,0x76,
+0x00,0x78,0x86,0x76,0x00,0x74,0x01,0x90,0xfb,0xfe,0xf0,0x12,0x30,0x85,0x90,0xfb,
+0xfd,0xe0,0x60,0x59,0x7c,0x0a,0x12,0x30,0xfa,0x90,0xfb,0xfb,0xe0,0x25,0xe0,0x24,
+0x85,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0xe0,0xfd,0xa3,0xe0,0xfc,0x90,0xfb,0xfb,
+0xe0,0x25,0xe0,0x24,0x85,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0xe4,0xf0,0xa3,0xf0,
+0x90,0xfb,0xfb,0xe0,0xff,0xe4,0xef,0x04,0x54,0x07,0xff,0x90,0xfb,0xfb,0xf0,0x90,
+0xfb,0xfd,0xe0,0x14,0xf0,0x78,0x83,0xed,0xf6,0x08,0xec,0xf6,0x12,0x31,0x93,0xb2,
+0xb3,0x78,0x83,0xe6,0xfd,0x08,0xe6,0xfc,0x12,0x08,0xe5,0x80,0xa1,0x12,0x31,0xe7,
+0x78,0x85,0x06,0xb6,0x00,0x11,0x78,0x85,0x76,0x00,0x78,0x86,0xe6,0xf4,0x04,0x04,
+0xa2,0xe0,0x92,0xb4,0x78,0x86,0xf6,0x80,0x85,0xe4,0x90,0xfb,0xfe,0xf0,0x90,0xfb,
+0xfd,0xe0,0x7d,0x00,0xfc,0xed,0x44,0xcf,0xfd,0x12,0x1c,0x93,0x12,0x31,0x08,0x22,
+0x12,0x30,0x85,0xe5,0x6a,0x64,0x49,0x45,0x69,0x60,0x15,0x90,0xff,0x83,0xe0,0x54,
+0x0f,0x7d,0x00,0xd3,0x95,0x6a,0xed,0x95,0x69,0x50,0x05,0x12,0x2e,0xce,0x80,0x03,
+0x12,0x2f,0x9e,0x12,0x31,0x08,0x22,0x12,0x30,0x85,0xe5,0x6a,0x64,0x49,0x45,0x69,
+0x60,0x05,0x12,0x2f,0xd8,0x80,0x0e,0x90,0xff,0x80,0xe0,0x44,0x08,0xf0,0x90,0xff,
+0x83,0xe0,0x54,0x7f,0xf0,0x12,0x31,0x08,0x22,0x12,0x30,0x85,0x8c,0x54,0xec,0x54,
+0xf0,0xb4,0x10,0x15,0x75,0x64,0x3d,0x75,0x63,0xfd,0x75,0x62,0x01,0xe5,0x64,0x24,
+0x03,0xf5,0x64,0xe5,0x63,0x34,0x00,0xf5,0x63,0xe4,0xf5,0x57,0xf5,0x56,0xe5,0x56,
+0xc3,0x94,0x01,0x50,0x27,0xe5,0x54,0x54,0x0f,0xfc,0xad,0x64,0xae,0x63,0xaf,0x62,
+0x12,0x0e,0x82,0x8c,0x55,0xec,0x60,0x02,0x80,0x12,0x05,0x64,0xe5,0x64,0x70,0x02,
+0x05,0x63,0x05,0x57,0xe5,0x57,0x70,0x02,0x05,0x56,0x80,0xd2,0xe5,0x54,0x54,0x0f,
+0x24,0x97,0xf8,0xc6,0x54,0xfe,0xf6,0xe5,0x54,0x54,0x0f,0x7f,0x00,0xfe,0x7c,0x12,
+0x12,0x31,0x9a,0xe5,0x55,0x14,0x70,0x09,0x7d,0x00,0x7c,0x09,0x12,0x24,0xb1,0x80,
+0x07,0xad,0x57,0x7c,0x00,0x12,0x24,0xb1,0x12,0x31,0x08,0x22,0x12,0x30,0x85,0x90,
+0xff,0xfc,0xe0,0x44,0x02,0xf0,0x90,0xff,0x00,0xe0,0x30,0xe7,0x13,0x90,0xff,0x83,
+0xe0,0x44,0x80,0xf0,0x43,0x67,0x80,0x90,0xff,0xfc,0xe0,0x44,0x01,0xf0,0x80,0x11,
+0x90,0xff,0x82,0xe0,0x44,0x08,0xf0,0x53,0x67,0x7f,0x90,0xff,0xfc,0xe0,0x54,0xfe,
+0xf0,0x90,0xff,0x81,0xe0,0x44,0x80,0xf0,0x12,0x25,0x64,0x90,0xff,0xfe,0xe0,0x44,
+0x05,0xf0,0x90,0xff,0xfc,0xe0,0x54,0xfd,0xf0,0x12,0x31,0x08,0x22,0x12,0x30,0x85,
+0x7c,0x01,0x12,0x32,0x48,0x78,0xa7,0xe6,0x44,0x02,0xf6,0x74,0xfe,0xfc,0x04,0xfd,
+0x12,0x1c,0xfe,0x90,0xff,0x6a,0xe0,0x30,0xe7,0x02,0x80,0xf7,0xe4,0xf5,0x4e,0x75,
+0x4d,0x10,0xac,0x4e,0xad,0x4d,0xe5,0x4e,0x15,0x4e,0x70,0x02,0x15,0x4d,0xec,0x4d,
+0x60,0x02,0x80,0xee,0x43,0x87,0x01,0x12,0x31,0x08,0x22,0x12,0x30,0x85,0x7c,0x02,
+0x12,0x31,0x14,0x78,0xa7,0xe6,0x54,0xfd,0xf6,0x12,0x31,0x08,0x22,0x12,0x30,0x85,
+0x78,0xa7,0xe6,0x30,0xe0,0x2c,0x78,0xa7,0xe6,0x30,0xe1,0x26,0x78,0xa7,0xe6,0xfc,
+0xf5,0x83,0x18,0xe6,0x44,0xf0,0xfd,0x12,0x1c,0x93,0x90,0xff,0xfc,0xe0,0x44,0x20,
+0xf0,0x7c,0x02,0x12,0x32,0x48,0x78,0xa7,0xe6,0x54,0xfd,0xf6,0x74,0x1a,0x90,0xff,
+0xfe,0xf0,0x78,0xa7,0xe6,0xfc,0xf5,0x83,0x18,0xe6,0x44,0xf1,0xfd,0x12,0x1c,0x93,
+0x12,0x31,0x08,0x22,0x75,0x67,0x00,0x75,0x68,0x00,0xe4,0xf5,0x66,0xf5,0x65,0xe4,
+0xf5,0x69,0x75,0x6a,0x49,0x74,0x84,0x90,0xff,0x82,0xf0,0x74,0x84,0x90,0xff,0x80,
+0xf0,0x74,0x80,0x90,0xff,0x68,0xf0,0x74,0x80,0x90,0xff,0x6a,0xf0,0xad,0x46,0xaf,
+0x45,0x7e,0x00,0xee,0x24,0xfc,0x50,0x03,0x02,0x21,0x6a,0xe4,0xee,0x75,0xf0,0x07,
+0xa4,0x24,0x3f,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xe0,0xff,0xe4,0xef,0x54,0x80,
+0xfd,0xe4,0xef,0x54,0x0f,0x14,0xff,0xed,0x60,0x38,0xe4,0xef,0x75,0xf0,0x08,0xa4,
+0x24,0x48,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0x74,0x90,0xf0,0xe4,0xef,0x75,0xf0,
+0x08,0xa4,0x24,0x4a,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0x74,0x80,0xf0,0xe4,0xef,
+0x75,0xf0,0x08,0xa4,0x24,0x4e,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0x74,0x80,0xf0,
+0x80,0x34,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x08,0xf5,0x82,0xe4,0x34,0xff,0xf5,
+0x83,0x74,0x90,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x0a,0xf5,0x82,0xe4,0x34,
+0xff,0xf5,0x83,0xe4,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x0e,0xf5,0x82,0xe4,
+0x34,0xff,0xf5,0x83,0xe4,0xf0,0x0e,0x02,0x20,0xd3,0x8d,0x46,0x8e,0x44,0x8f,0x45,
+0x74,0x7f,0x90,0xff,0xfd,0xf0,0x74,0x90,0x90,0xff,0xfc,0xf0,0x90,0xfc,0x19,0xe0,
+0x30,0xe6,0x07,0x90,0xff,0xfc,0xe0,0x44,0x04,0xf0,0x22,0x90,0xfc,0x0d,0xe0,0x14,
+0x70,0x04,0x90,0xfc,0x0c,0xe0,0x70,0x39,0x90,0xfc,0x00,0x79,0x06,0x7a,0x35,0x7b,
+0x12,0x78,0x01,0x12,0x03,0xf5,0x7f,0x00,0xef,0x33,0x40,0x15,0xef,0x90,0x35,0x4d,
+0x93,0xfc,0xef,0x24,0x80,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xec,0xf0,0x0f,0x80,
+0xe7,0x8f,0x59,0x90,0xfc,0x2b,0x79,0x18,0x7a,0x35,0x7b,0x35,0x78,0x01,0x12,0x03,
+0xf5,0xe4,0x90,0xff,0xff,0xf0,0x74,0x51,0x90,0xff,0xfa,0xf0,0x74,0x04,0x90,0xff,
+0xfb,0xf0,0x74,0x53,0x90,0xff,0xf8,0xf0,0x74,0x51,0x90,0xff,0xf9,0xf0,0x74,0x55,
+0x90,0xff,0xf7,0xf0,0x74,0x93,0x90,0xff,0xf6,0xf0,0x74,0x32,0x90,0xff,0xf5,0xf0,
+0x75,0x64,0x3d,0x75,0x63,0xfd,0x75,0x62,0x01,0xe4,0x90,0xff,0x83,0xf0,0x74,0x80,
+0x90,0xff,0x81,0xf0,0x75,0x58,0x04,0xe5,0x58,0x75,0xf0,0x07,0xa4,0x24,0x3f,0xf5,
+0x82,0xe4,0x34,0xfc,0xf5,0x83,0xe0,0x78,0x89,0xf6,0xfc,0x54,0x0f,0x14,0xfc,0x78,
+0x89,0xec,0xf6,0xe5,0x58,0x75,0xf0,0x07,0xa4,0x24,0x41,0xf5,0x82,0xe4,0x34,0xfc,
+0xf5,0x83,0xe0,0x78,0x8c,0x76,0xf8,0x08,0x76,0x00,0xfc,0x78,0x89,0xe6,0x75,0xf0,
+0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0x78,0x89,0xe6,
+0x75,0xf0,0x08,0xa4,0x24,0x4f,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xec,0xf0,0x78,
+0x8c,0xe6,0xff,0x08,0xe6,0x7e,0x03,0xcf,0xc3,0x13,0xcf,0x13,0xde,0xf9,0xfe,0x78,
+0x89,0xe6,0x75,0xf0,0x08,0xa4,0x24,0x49,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xee,
+0xf0,0x78,0x89,0xe6,0x75,0xf0,0x08,0xa4,0x24,0x4a,0xf5,0x82,0xe4,0x34,0xff,0xf5,
+0x83,0x74,0x80,0xf0,0x78,0x8a,0xec,0xf6,0x7d,0x00,0x78,0x8d,0xe6,0x2c,0xf6,0x18,
+0xe6,0x3d,0xf6,0x78,0x8c,0xe6,0xfd,0x08,0xe6,0x7c,0x03,0xcd,0xc3,0x13,0xcd,0x13,
+0xdc,0xf9,0xfc,0x78,0x89,0xe6,0x75,0xf0,0x08,0xa4,0x24,0x4d,0xf5,0x82,0xe4,0x34,
+0xff,0xf5,0x83,0xec,0xf0,0x78,0x89,0xe6,0x75,0xf0,0x08,0xa4,0x24,0x4e,0xf5,0x82,
+0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0x78,0x8c,0xe6,0xfd,0x08,0xe6,0xfc,0x78,0x89,
+0xe6,0xff,0x7e,0x00,0xee,0x24,0xfc,0x50,0x03,0x02,0x24,0x6b,0xe4,0xee,0x75,0xf0,
+0x07,0xa4,0x24,0x3f,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xe0,0xff,0xe4,0xef,0x54,
+0x80,0xfa,0xe4,0xef,0x54,0x0f,0x14,0xff,0xe4,0xee,0x75,0xf0,0x07,0xa4,0x24,0x41,
+0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xe0,0x78,0x8a,0xf6,0xee,0x75,0xf0,0x80,0xa4,
+0x24,0x08,0xf8,0xe5,0xf0,0x34,0xf8,0xf9,0xe8,0xfc,0xe9,0xfd,0x8a,0x59,0xea,0x70,
+0x03,0x02,0x23,0xd8,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,0x34,
+0xff,0xf5,0x83,0xe4,0xf0,0x78,0x8a,0xe6,0xfa,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,
+0x4f,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xea,0xf0,0xed,0xfb,0xec,0x7a,0x03,0xcb,
+0xc3,0x13,0xcb,0x13,0xda,0xf9,0xfa,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x49,0xf5,
+0x82,0xe4,0x34,0xff,0xf5,0x83,0xea,0xf0,0x78,0x8a,0xe6,0x7b,0x00,0xfa,0xec,0x2a,
+0xfc,0xed,0x3b,0xfd,0xfb,0xec,0x7a,0x03,0xcb,0xc3,0x13,0xcb,0x13,0xda,0xf9,0xfa,
+0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x4d,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xea,
+0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x4a,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,
+0x74,0x80,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x4e,0xf5,0x82,0xe4,0x34,0xff,
+0xf5,0x83,0x74,0x80,0xf0,0x02,0x24,0x67,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x08,
+0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0x78,0x8a,0xe6,0xfa,0xe4,0xef,0x75,
+0xf0,0x08,0xa4,0x24,0x0f,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xea,0xf0,0xed,0xfb,
+0xec,0x7a,0x03,0xcb,0xc3,0x13,0xcb,0x13,0xda,0xf9,0xfa,0xe4,0xef,0x75,0xf0,0x08,
+0xa4,0x24,0x09,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xea,0xf0,0x78,0x8a,0xe6,0x7b,
+0x00,0xfa,0xec,0x2a,0xfc,0xed,0x3b,0xfd,0xfb,0xec,0x7a,0x03,0xcb,0xc3,0x13,0xcb,
+0x13,0xda,0xf9,0xfa,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x0d,0xf5,0x82,0xe4,0x34,
+0xff,0xf5,0x83,0xea,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x0a,0xf5,0x82,0xe4,
+0x34,0xff,0xf5,0x83,0xe4,0xf0,0xe4,0xef,0x75,0xf0,0x08,0xa4,0x24,0x0e,0xf5,0x82,
+0xe4,0x34,0xff,0xf5,0x83,0xe4,0xf0,0x0e,0x02,0x22,0xf4,0x8e,0x58,0x78,0x8c,0xed,
+0xf6,0x08,0xec,0xf6,0x78,0x89,0xef,0xf6,0x12,0x20,0xa4,0x22,0x8c,0x26,0xec,0x30,
+0xe7,0x18,0xe5,0x26,0x54,0x0f,0x14,0x75,0xf0,0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,
+0x34,0xff,0xf5,0x83,0xe0,0x54,0xdf,0xf0,0x80,0x16,0xe5,0x26,0x54,0x0f,0x14,0x75,
+0xf0,0x08,0xa4,0x24,0x08,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x54,0xdf,0xf0,
+0x22,0xec,0x90,0xfd,0x3f,0xf0,0x8c,0x24,0xed,0x24,0x03,0xf5,0x25,0x7d,0x00,0xd3,
+0x95,0x6c,0xed,0x95,0x6b,0x40,0x03,0x85,0x6c,0x25,0xe5,0x25,0x24,0xb7,0x50,0x09,
+0x75,0x25,0x03,0x74,0x02,0x90,0xfd,0x3f,0xf0,0xac,0x25,0x12,0x2f,0xc3,0x22,0xe4,
+0xf5,0x66,0xf5,0x65,0x12,0x24,0xe8,0x22,0x90,0xfd,0x3d,0xe0,0x65,0x6d,0x60,0x0e,
+0x74,0x04,0x90,0xfd,0x3f,0xf0,0xe4,0xf5,0x65,0x75,0x66,0x03,0x80,0x46,0x7d,0x6d,
+0xe4,0xfe,0xff,0x79,0x3d,0x7a,0xfd,0x7b,0x01,0x74,0x05,0x78,0x00,0x12,0x03,0x3f,
+0xe5,0x66,0x24,0x03,0xf5,0x66,0xe5,0x65,0x34,0x00,0xf5,0x65,0xe5,0x66,0xd3,0x95,
+0x6c,0xe5,0x65,0x95,0x6b,0x40,0x06,0x85,0x6c,0x66,0x85,0x6b,0x65,0xd3,0xe5,0x66,
+0x94,0x48,0xe5,0x65,0x94,0x00,0x40,0x0c,0x74,0x02,0x90,0xfd,0x3f,0xf0,0xe4,0xf5,
+0x65,0x75,0x66,0x03,0xac,0x66,0x12,0x2f,0xc3,0x22,0xec,0x90,0xfd,0x3f,0xf0,0xe4,
+0xf5,0x66,0xf5,0x65,0x8c,0x32,0xec,0x60,0x05,0x12,0x2f,0xb4,0x80,0x05,0x7c,0x00,
+0x12,0x2f,0xc3,0x22,0x90,0xff,0x04,0xe0,0xf5,0x4a,0x90,0xff,0x06,0xe0,0xfd,0xa3,
+0xe0,0xed,0x7d,0x00,0xfc,0x7d,0x00,0xfc,0x90,0xff,0x06,0xe0,0xff,0xa3,0xe0,0x7e,
+0x00,0xff,0xe4,0xfe,0xec,0x4e,0xfc,0xed,0x4f,0xfd,0xc3,0xec,0x94,0x48,0xed,0x94,
+0x00,0x50,0x22,0x90,0xff,0x06,0xe0,0xfd,0xa3,0xe0,0xed,0x7d,0x00,0xfc,0x7d,0x00,
+0xfc,0x90,0xff,0x06,0xe0,0xff,0xa3,0xe0,0x7e,0x00,0xff,0xe4,0xfe,0xec,0x4e,0xfc,
+0xed,0x4f,0xfd,0x80,0x04,0xe4,0xfd,0x7c,0x48,0x8c,0x6c,0x8d,0x6b,0x90,0xff,0x02,
+0xe0,0xfd,0xa3,0xe0,0xed,0x7d,0x00,0xfc,0x7d,0x00,0xfc,0x90,0xff,0x02,0xe0,0xff,
+0xa3,0xe0,0x7e,0x00,0xff,0xe4,0xfe,0xec,0x4e,0xf5,0x4c,0xed,0x4f,0xf5,0x4b,0x75,
+0x64,0x3d,0x75,0x63,0xfd,0x75,0x62,0x01,0x7d,0x3d,0x7e,0xfd,0x7f,0x01,0x79,0x6d,
+0xe4,0xfa,0xfb,0x74,0x05,0x78,0x00,0x12,0x03,0x3f,0x75,0x49,0x00,0xe5,0x49,0x24,
+0xfe,0x40,0x19,0xad,0x64,0xae,0x63,0xaf,0x62,0xe4,0x12,0x03,0x0f,0x05,0x49,0x0d,
+0xed,0x70,0x01,0x0e,0x8d,0x64,0x8e,0x63,0x8f,0x62,0x80,0xe1,0x75,0x64,0x3d,0x75,
+0x63,0xfd,0x75,0x62,0x01,0x90,0xff,0x00,0xe0,0x54,0x60,0xb4,0x00,0x02,0x80,0x06,
+0xd3,0x50,0x03,0x02,0x2c,0x12,0xe5,0x4a,0x54,0x0f,0xf5,0x49,0xe5,0x4a,0x54,0x80,
+0xa2,0xe0,0x92,0x02,0x90,0xff,0x01,0xe0,0x12,0x01,0x81,0x00,0x0b,0x2c,0x0d,0x26,
+0x67,0x27,0x85,0x2c,0x0d,0x28,0x91,0x2c,0x0d,0x29,0x74,0x29,0xa8,0x2b,0x0f,0x2b,
+0x12,0x2b,0x52,0x2b,0xb6,0x2b,0xe4,0xe5,0x67,0x30,0xe7,0x0e,0xe5,0x4c,0x45,0x4b,
+0x70,0x08,0xe5,0x6c,0x64,0x02,0x45,0x6b,0x60,0x03,0x02,0x2c,0x0f,0x90,0xff,0x00,
+0xe0,0x54,0x1f,0xb4,0x00,0x02,0x80,0x03,0xd3,0x40,0x29,0xe5,0x4a,0x60,0x03,0x02,
+0x27,0x82,0xad,0x64,0xae,0x63,0xaf,0x62,0x74,0x01,0x12,0x03,0x0f,0x78,0xa7,0xe6,
+0x30,0xe0,0x0b,0xad,0x64,0xae,0x63,0xaf,0x62,0x74,0x02,0x12,0x03,0x0f,0x7c,0x02,
+0x12,0x2f,0xc3,0x22,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x1b,0xe5,0x67,0x20,0xe1,
+0x07,0xe5,0x4a,0x60,0x03,0x02,0x27,0x82,0xe5,0x4a,0x24,0xfe,0x50,0x03,0x02,0x27,
+0x82,0x7c,0x02,0x12,0x2f,0xc3,0x22,0xb4,0x02,0x02,0x80,0x06,0xd3,0x50,0x03,0x02,
+0x27,0x80,0xe5,0x67,0x20,0xe1,0x0d,0xe5,0x4a,0x60,0x09,0xe5,0x4a,0x64,0x80,0x60,
+0x03,0x02,0x27,0x82,0xac,0x4a,0x12,0x30,0x4a,0x40,0x03,0x02,0x27,0x82,0xe5,0x49,
+0x70,0x25,0x30,0x02,0x11,0x90,0xff,0x80,0xe0,0x54,0x08,0xad,0x64,0xae,0x63,0xaf,
+0x62,0x12,0x03,0x0f,0x80,0x0f,0x90,0xff,0x82,0xe0,0x54,0x08,0xad,0x64,0xae,0x63,
+0xaf,0x62,0x12,0x03,0x0f,0x80,0x3d,0x15,0x49,0x30,0x02,0x1d,0xe5,0x49,0x75,0xf0,
+0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x54,0x08,0xad,0x64,
+0xae,0x63,0xaf,0x62,0x12,0x03,0x0f,0x80,0x1b,0xe5,0x49,0x75,0xf0,0x08,0xa4,0x24,
+0x08,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x54,0x08,0xad,0x64,0xae,0x63,0xaf,
+0x62,0x12,0x03,0x0f,0xad,0x64,0xae,0x63,0xaf,0x62,0x12,0x01,0xe6,0x60,0x0b,0xad,
+0x64,0xae,0x63,0xaf,0x62,0x74,0x01,0x12,0x03,0x0f,0x7c,0x02,0x12,0x2f,0xc3,0x22,
+0x80,0x00,0x02,0x2c,0x0f,0xe5,0x67,0x20,0xe7,0x06,0xe5,0x6c,0x45,0x6b,0x60,0x03,
+0x02,0x2c,0x0f,0x90,0xff,0x00,0xe0,0x54,0x1f,0xb4,0x00,0x02,0x80,0x03,0xd3,0x40,
+0x1a,0xe5,0x4c,0x14,0x45,0x4b,0x70,0x04,0xe5,0x4a,0x60,0x03,0x02,0x28,0x8e,0x78,
+0xa7,0xe6,0x54,0xfe,0xf6,0x7c,0x00,0x12,0x2f,0xc3,0x22,0xb4,0x01,0x02,0x80,0x03,
+0xd3,0x40,0x2a,0xe5,0x67,0x20,0xe1,0x08,0xe5,0x67,0x20,0xe0,0x03,0x02,0x28,0x8e,
+0xe5,0x67,0x30,0xe0,0x04,0xe5,0x4a,0x70,0x0b,0xe5,0x67,0x30,0xe1,0x09,0xe5,0x4a,
+0x24,0xfe,0x50,0x03,0x02,0x28,0x8e,0x7c,0x00,0x12,0x2f,0xc3,0x22,0xb4,0x02,0x02,
+0x80,0x06,0xd3,0x50,0x03,0x02,0x28,0x8c,0xe5,0x4c,0x45,0x4b,0x60,0x03,0x02,0x28,
+0x8e,0xac,0x4a,0x12,0x30,0x4a,0x40,0x03,0x02,0x28,0x8e,0xe5,0x67,0x20,0xe1,0x07,
+0xe5,0x67,0x20,0xe0,0x02,0x80,0x77,0xe5,0x67,0x30,0xe0,0x06,0xe5,0x49,0x60,0x02,
+0x80,0x6c,0xe5,0x49,0x70,0x0f,0x90,0xff,0x82,0xe0,0x54,0xf7,0xf0,0x90,0xff,0x80,
+0xe0,0x54,0xf7,0xf0,0x22,0xe5,0x49,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x09,0x7d,
+0x01,0x7c,0x03,0x12,0x0f,0x0b,0x80,0x11,0xb4,0x02,0x02,0x80,0x03,0xd3,0x40,0x09,
+0x7d,0x01,0x7c,0x04,0x12,0x0f,0x0b,0x80,0x00,0x15,0x49,0x30,0x02,0x15,0xe5,0x49,
+0x75,0xf0,0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x54,0xf7,
+0xf0,0x80,0x13,0xe5,0x49,0x75,0xf0,0x08,0xa4,0x24,0x08,0xf5,0x82,0xe4,0x34,0xff,
+0xf5,0x83,0xe0,0x54,0xf7,0xf0,0x7c,0x00,0x12,0x2f,0xc3,0x22,0x80,0x00,0x02,0x2c,
+0x0f,0xe5,0x67,0x20,0xe7,0x06,0xe5,0x6c,0x45,0x6b,0x60,0x03,0x02,0x2c,0x0f,0x90,
+0xff,0x00,0xe0,0x54,0x1f,0xb4,0x00,0x02,0x80,0x03,0xd3,0x40,0x1a,0xe5,0x4c,0x14,
+0x45,0x4b,0x70,0x04,0xe5,0x4a,0x60,0x03,0x02,0x29,0x71,0x78,0xa7,0xe6,0x44,0x01,
+0xf6,0x7c,0x00,0x12,0x2f,0xc3,0x22,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x29,0xe5,
+0x67,0x20,0xe1,0x08,0xe5,0x67,0x20,0xe0,0x03,0x02,0x29,0x71,0xe5,0x67,0x30,0xe0,
+0x04,0xe5,0x49,0x70,0x0b,0xe5,0x67,0x30,0xe1,0x08,0xe5,0x49,0x24,0xfe,0x50,0x02,
+0x80,0x7f,0x7c,0x00,0x12,0x2f,0xc3,0x22,0xb4,0x02,0x02,0x80,0x03,0xd3,0x40,0x6f,
+0xe5,0x4c,0x45,0x4b,0x60,0x02,0x80,0x69,0xac,0x4a,0x12,0x30,0x4a,0x40,0x02,0x80,
+0x60,0xe5,0x67,0x20,0xe1,0x07,0xe5,0x67,0x20,0xe0,0x02,0x80,0x54,0xe5,0x49,0x70,
+0x14,0x30,0x02,0x09,0x90,0xff,0x80,0xe0,0x44,0x08,0xf0,0x80,0x07,0x90,0xff,0x82,
+0xe0,0x44,0x08,0xf0,0x22,0xe5,0x67,0x30,0xe1,0x33,0x15,0x49,0x30,0x02,0x15,0xe5,
+0x49,0x75,0xf0,0x08,0xa4,0x24,0x48,0xf5,0x82,0xe4,0x34,0xff,0xf5,0x83,0xe0,0x44,
+0x08,0xf0,0x80,0x13,0xe5,0x49,0x75,0xf0,0x08,0xa4,0x24,0x08,0xf5,0x82,0xe4,0x34,
+0xff,0xf5,0x83,0xe0,0x44,0x08,0xf0,0x7c,0x00,0x12,0x2f,0xc3,0x22,0x80,0x02,0x80,
+0x00,0x02,0x2c,0x0f,0xe5,0x67,0x20,0xe7,0x12,0xe5,0x6c,0x45,0x6b,0x70,0x0c,0xe5,
+0x4a,0x70,0x08,0x90,0xff,0x00,0xe0,0x54,0x1f,0x60,0x03,0x02,0x2c,0x0f,0xe5,0x4c,
+0x90,0xff,0xff,0xf0,0x90,0xff,0xff,0xe0,0x60,0x05,0x43,0x67,0x01,0x80,0x03,0x53,
+0x67,0xfe,0x7c,0x00,0x12,0x2f,0xc3,0x22,0xe5,0x67,0x30,0xe7,0x0e,0xe5,0x6c,0x45,
+0x6b,0x60,0x08,0x90,0xff,0x00,0xe0,0x54,0x1f,0x60,0x03,0x02,0x2c,0x0f,0xad,0x4b,
+0xe5,0x4c,0xed,0x7d,0x00,0xfc,0x7d,0x00,0xfc,0xbd,0x00,0x02,0x80,0x03,0x02,0x2b,
+0x0a,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x32,0xe5,0x4a,0x70,0x05,0xe5,0x4c,0xfc,
+0x60,0x03,0x02,0x2b,0x0c,0x75,0x64,0x00,0x75,0x63,0xfc,0x75,0x62,0x01,0xd3,0xe5,
+0x6c,0x94,0x12,0xe5,0x6b,0x94,0x00,0x40,0x06,0xe4,0xfd,0x7c,0x12,0x80,0x04,0xac,
+0x6c,0xad,0x6b,0x8c,0x6a,0x8d,0x69,0x12,0x2f,0xd8,0x22,0xb4,0x02,0x02,0x80,0x03,
+0xd3,0x40,0x59,0xe5,0x4a,0x60,0x03,0x02,0x2b,0x0c,0xe5,0x4c,0xfc,0x70,0x27,0x75,
+0x64,0x12,0x75,0x63,0xfc,0x75,0x62,0x01,0xd3,0xe5,0x6c,0x94,0x19,0xe5,0x6b,0x94,
+0x00,0x40,0x06,0xe4,0xfd,0x7c,0x19,0x80,0x04,0xac,0x6c,0xad,0x6b,0x8c,0x6a,0x8d,
+0x69,0x12,0x2f,0xd8,0x80,0x25,0x75,0x64,0x2b,0x75,0x63,0xfc,0x75,0x62,0x01,0xd3,
+0xe5,0x6c,0x94,0x35,0xe5,0x6b,0x94,0x00,0x40,0x06,0xe4,0xfd,0x7c,0x35,0x80,0x04,
+0xac,0x6c,0xad,0x6b,0x8c,0x6a,0x8d,0x69,0x12,0x2f,0xd8,0x22,0xb4,0x03,0x02,0x80,
+0x06,0xd3,0x50,0x03,0x02,0x2b,0x0a,0xe5,0x4c,0xf5,0x49,0x70,0x0f,0x90,0xff,0x04,
+0xe0,0xfd,0xa3,0xe0,0x4d,0x60,0x03,0x02,0x2b,0x0c,0x80,0x18,0x90,0xfc,0x82,0xe0,
+0xfd,0xa3,0xe0,0xfc,0x90,0xff,0x05,0xe0,0x6c,0x70,0x07,0x90,0xff,0x04,0xe0,0x6d,
+0x60,0x02,0x80,0x68,0xe4,0xf5,0x6a,0xf5,0x69,0x7f,0x00,0xe5,0x49,0x14,0xc5,0x49,
+0x60,0x0f,0xef,0x24,0x80,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xe0,0x2f,0xff,0x80,
+0xea,0x8f,0x4a,0xe5,0x4a,0x24,0x80,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xe0,0x7d,
+0x00,0xd3,0x95,0x6c,0xed,0x95,0x6b,0x40,0x06,0xac,0x6c,0xad,0x6b,0x80,0x0f,0xe5,
+0x4a,0x24,0x80,0xf5,0x82,0xe4,0x34,0xfc,0xf5,0x83,0xe0,0x7d,0x00,0xfc,0x8c,0x6a,
+0x8d,0x69,0xe5,0x4a,0x24,0x80,0xfc,0xe4,0x34,0xfc,0xfd,0xfe,0xec,0xfd,0x7f,0x01,
+0x8d,0x64,0x8e,0x63,0x8f,0x62,0x12,0x2f,0xd8,0x22,0x80,0x00,0x02,0x2c,0x0f,0x02,
+0x2c,0x0f,0xe5,0x67,0x30,0xe7,0x19,0xe5,0x6c,0x14,0x45,0x6b,0x70,0x12,0xe5,0x4a,
+0x70,0x0e,0xe5,0x4c,0x45,0x4b,0x70,0x08,0x90,0xff,0x00,0xe0,0x54,0x1f,0x60,0x03,
+0x02,0x2c,0x0f,0xe5,0x67,0x20,0xe0,0x08,0xe5,0x67,0x20,0xe1,0x03,0x02,0x2c,0x0f,
+0x75,0x64,0x68,0xe4,0xf5,0x63,0xf5,0x62,0xe4,0xf5,0x69,0x04,0xf5,0x6a,0x12,0x2f,
+0xd8,0x22,0xe5,0x67,0x20,0xe7,0x27,0xe5,0x6c,0x45,0x6b,0x70,0x21,0xe5,0x4a,0x70,
+0x1d,0xe5,0x4c,0x64,0x02,0x45,0x4b,0x60,0x0d,0xe5,0x4c,0x14,0x45,0x4b,0x60,0x06,
+0xe5,0x4c,0x45,0x4b,0x70,0x08,0x90,0xff,0x00,0xe0,0x54,0x1f,0x60,0x03,0x02,0x2c,
+0x0f,0xe5,0x67,0x20,0xe0,0x08,0xe5,0x67,0x20,0xe1,0x03,0x02,0x2c,0x0f,0x85,0x4c,
+0x68,0xe5,0x68,0x70,0x08,0x43,0x67,0x01,0x53,0x67,0xfd,0x80,0x13,0xe5,0x68,0x64,
+0x02,0x60,0x07,0xe5,0x68,0x14,0x60,0x02,0x80,0x65,0x53,0x67,0xfe,0x43,0x67,0x02,
+0x7c,0x00,0x12,0x2f,0xc3,0x22,0xe5,0x67,0x30,0xe7,0x1a,0xe5,0x6c,0x14,0x45,0x6b,
+0x70,0x13,0xe5,0x4a,0x70,0x0f,0xe5,0x4c,0x45,0x4b,0x70,0x09,0x90,0xff,0x00,0xe0,
+0x54,0x1f,0x14,0x60,0x02,0x80,0x38,0xe5,0x67,0x20,0xe1,0x02,0x80,0x31,0x7c,0x01,
+0x12,0x2f,0xc3,0x22,0xe5,0x67,0x20,0xe7,0x15,0xe5,0x6c,0x45,0x6b,0x70,0x0f,0xe5,
+0x4c,0x45,0x4b,0x70,0x09,0x90,0xff,0x00,0xe0,0x54,0x1f,0x14,0x60,0x02,0x80,0x0f,
+0xe5,0x67,0x20,0xe1,0x02,0x80,0x08,0x7c,0x00,0x12,0x2f,0xc3,0x22,0x80,0x00,0x02,
+0x2e,0xca,0xb4,0x40,0x02,0x80,0x06,0xd3,0x50,0x03,0x02,0x2e,0xc0,0x90,0xff,0x01,
+0xe0,0x90,0xfd,0x3d,0xf0,0xe5,0x4a,0x90,0xfd,0x3e,0xf0,0xe4,0x90,0xfd,0x3f,0xf0,
+0xe5,0x64,0x24,0x03,0xf5,0x64,0xe5,0x63,0x34,0x00,0xf5,0x63,0xad,0x4b,0xe5,0x4c,
+0x85,0x64,0x82,0x85,0x63,0x83,0xcd,0xf0,0xa3,0xcd,0xf0,0x90,0xff,0x01,0xe0,0x12,
+0x01,0xb7,0x2c,0x7d,0x01,0x2c,0xa3,0x02,0x2c,0xcd,0x03,0x2c,0xf7,0x04,0x2d,0x45,
+0x05,0x2d,0x82,0x06,0x2d,0xa8,0x07,0x2d,0xce,0x08,0x2d,0xf4,0x09,0x2e,0x1a,0x0b,
+0x2e,0x40,0x0c,0x2e,0x4f,0x80,0x2e,0x4f,0x81,0x00,0x00,0x2e,0xad,0xe5,0x67,0x20,
+0xe7,0x06,0x7c,0x05,0x12,0x25,0x4a,0x22,0x7d,0xb7,0x7e,0x34,0x7f,0x02,0x79,0x40,
+0x7a,0xfd,0x7b,0x01,0x74,0x08,0x78,0x00,0x12,0x03,0x3f,0x7d,0x08,0x7c,0x00,0x12,
+0x24,0xb1,0x22,0xe5,0x67,0x20,0xe7,0x06,0x7c,0x05,0x12,0x25,0x4a,0x22,0xe5,0x4a,
+0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,0x7c,
+0x10,0x12,0x31,0x9a,0x22,0x7d,0x00,0x7c,0x07,0x12,0x24,0xb1,0x22,0xe5,0x67,0x20,
+0xe7,0x06,0x7c,0x05,0x12,0x25,0x4a,0x22,0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,0xb4,
+0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,0x7c,0x11,0x12,0x31,0x9a,0x22,0x7d,
+0x00,0x7c,0x07,0x12,0x24,0xb1,0x22,0xe5,0x67,0x20,0xe7,0x06,0x7c,0x05,0x12,0x25,
+0x4a,0x22,0xe5,0x4a,0xb4,0x05,0x02,0x80,0x03,0xd3,0x40,0x0a,0xe4,0xff,0x04,0xfe,
+0x7c,0x0a,0x12,0x31,0x9a,0x22,0xb4,0x01,0x02,0x80,0x03,0xd3,0x40,0x0a,0xe4,0xff,
+0x04,0xfe,0x7c,0x08,0x12,0x31,0x9a,0x22,0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,
+0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,0x7c,0x13,0x12,0x31,0x9a,0x22,0x7d,0x00,0x7c,
+0x07,0x12,0x24,0xb1,0x22,0xe5,0x67,0x20,0xe7,0x34,0xd3,0xe5,0x6c,0x94,0x48,0xe5,
+0x6b,0x94,0x00,0x50,0x06,0xe5,0x6c,0x45,0x6b,0x70,0x06,0x7c,0x02,0x12,0x25,0x4a,
+0x22,0xe5,0x4a,0xb4,0x01,0x03,0xb3,0x40,0x0b,0xc3,0xb4,0x03,0x00,0x40,0x09,0xb4,
+0x06,0x00,0x50,0x04,0x12,0x30,0x70,0x22,0x7c,0x07,0x12,0x25,0x4a,0x22,0x12,0x24,
+0xe8,0x22,0xe5,0x67,0x20,0xe7,0x1d,0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,
+0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,0x7c,0x16,0x12,0x31,0x9a,0x22,0x7c,0x07,
+0x12,0x25,0x4a,0x22,0x12,0x24,0xe8,0x22,0xe5,0x67,0x20,0xe7,0x1d,0xe5,0x4a,0xb4,
+0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,0x7c,0x19,
+0x12,0x31,0x9a,0x22,0x7c,0x07,0x12,0x25,0x4a,0x22,0x12,0x24,0xe8,0x22,0xe5,0x67,
+0x20,0xe7,0x1d,0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,
+0x4a,0x7f,0x00,0xfe,0x7c,0x17,0x12,0x31,0x9a,0x22,0x7c,0x07,0x12,0x25,0x4a,0x22,
+0x12,0x24,0xe8,0x22,0xe5,0x67,0x20,0xe7,0x1d,0xe5,0x4a,0xb4,0x03,0x00,0x40,0x10,
+0xb4,0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,0x7c,0x18,0x12,0x31,0x9a,0x22,
+0x7c,0x07,0x12,0x25,0x4a,0x22,0x12,0x24,0xe8,0x22,0xe5,0x67,0x20,0xe7,0x1d,0xe5,
+0x4a,0xb4,0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,0x4a,0x7f,0x00,0xfe,
+0x7c,0x15,0x12,0x31,0x9a,0x22,0x7c,0x07,0x12,0x25,0x4a,0x22,0x12,0x24,0xe8,0x22,
+0xe5,0x67,0x20,0xe7,0x06,0x7c,0x07,0x12,0x25,0x4a,0x22,0x12,0x24,0xe8,0x22,0xe5,
+0x67,0x30,0xe7,0x20,0x90,0xff,0x00,0xe0,0x54,0x1f,0x70,0x10,0x90,0xff,0x01,0xe0,
+0xb4,0x80,0x05,0x12,0x24,0xdf,0x80,0x03,0x12,0x24,0xe8,0x22,0x7d,0x00,0x7c,0x05,
+0x12,0x24,0xb1,0x22,0x90,0xff,0x00,0xe0,0x54,0x1f,0x60,0x06,0x7c,0x05,0x12,0x25,
+0x4a,0x22,0xd3,0xe5,0x6c,0x94,0x48,0xe5,0x6b,0x94,0x00,0x50,0x0b,0xc3,0xe5,0x6c,
+0x94,0x07,0xe5,0x6b,0x94,0x00,0x50,0x06,0x7c,0x03,0x12,0x25,0x4a,0x22,0xe5,0x4a,
+0xb4,0x05,0x04,0x12,0x30,0x70,0x22,0x7c,0x07,0x12,0x25,0x4a,0x22,0xe5,0x67,0x30,
+0xe7,0x08,0x7d,0x00,0x7c,0x05,0x12,0x24,0xb1,0x22,0x7c,0x05,0x12,0x25,0x4a,0x22,
+0xb4,0x20,0x02,0x80,0x03,0xd3,0x40,0x00,0x80,0x00,0x12,0x2f,0x9e,0x22,0x75,0x43,
+0x00,0x90,0xff,0x83,0xe0,0x54,0x0f,0xd3,0x95,0x43,0x40,0x24,0xe5,0x43,0x24,0xf0,
+0xf5,0x82,0xe4,0x34,0xfe,0xf5,0x83,0xe0,0xad,0x64,0xae,0x63,0xaf,0x62,0x12,0x03,
+0x0f,0x05,0x43,0x0d,0xed,0x70,0x01,0x0e,0x8d,0x64,0x8e,0x63,0x8f,0x62,0x80,0xd1,
+0xe5,0x43,0x7d,0x00,0xfc,0xc3,0xe5,0x6a,0x9c,0xf5,0x6a,0xe5,0x69,0x9d,0xf5,0x69,
+0xe5,0x6a,0x45,0x69,0x60,0x06,0xe4,0x90,0xff,0x83,0xf0,0x22,0x90,0xff,0x82,0xe0,
+0x44,0x08,0xf0,0xe4,0xf5,0x69,0x75,0x6a,0x49,0x90,0xfd,0x3d,0xe0,0xb4,0x05,0x02,
+0x80,0x03,0xd3,0x40,0x40,0x90,0xfd,0x3e,0xe0,0xf5,0x43,0xb4,0x05,0x02,0x80,0x03,
+0xd3,0x40,0x0a,0xe4,0xff,0x04,0xfe,0x7c,0x0b,0x12,0x31,0x9a,0x22,0xb4,0x01,0x02,
+0x80,0x03,0xd3,0x40,0x0a,0xe4,0xff,0x04,0xfe,0x7c,0x09,0x12,0x31,0x9a,0x22,0xb4,
+0x03,0x00,0x40,0x10,0xb4,0x05,0x00,0x50,0x0b,0xe5,0x43,0x7f,0x00,0xfe,0x7c,0x14,
+0x12,0x31,0x9a,0x22,0x22,0xb4,0x80,0x00,0x40,0x23,0xb4,0x82,0x00,0x50,0x1e,0x7c,
+0x3d,0x7d,0xfd,0x12,0x17,0xd5,0x7d,0x00,0x8c,0x66,0x8d,0x65,0x90,0xfd,0x3f,0xe0,
+0x60,0x05,0x12,0x2f,0x9e,0x80,0x05,0x7c,0x00,0x12,0x2f,0xc3,0x22,0x22,0x90,0xff,
+0x83,0xe0,0x54,0x7f,0xf0,0x90,0xff,0x82,0xe0,0x44,0x08,0xf0,0x90,0xff,0x80,0xe0,
+0x44,0x08,0xf0,0x22,0x90,0xff,0x82,0xe0,0x44,0x08,0xf0,0x90,0xff,0x80,0xe0,0x44,
+0x08,0xf0,0x22,0x8c,0x23,0x7d,0x00,0x8c,0x6a,0x8d,0x69,0x75,0x64,0x3d,0x75,0x63,
+0xfd,0x75,0x62,0x01,0x12,0x2f,0xd8,0x22,0x90,0xff,0x83,0xe0,0x54,0x7f,0xf0,0xe5,
+0x6a,0x64,0x49,0x45,0x69,0x70,0x01,0x22,0xc3,0xe5,0x6a,0x94,0x08,0xe5,0x69,0x94,
+0x00,0x40,0x15,0x75,0x21,0x08,0xe5,0x21,0x7d,0x00,0xfc,0xc3,0xe5,0x6a,0x9c,0xf5,
+0x6a,0xe5,0x69,0x9d,0xf5,0x69,0x80,0x09,0x85,0x6a,0x21,0xe4,0xf5,0x69,0x75,0x6a,
+0x49,0x75,0x22,0x00,0xe5,0x22,0xc3,0x95,0x21,0x50,0x26,0xad,0x64,0xae,0x63,0xaf,
+0x62,0x12,0x01,0xe6,0xfc,0xe5,0x22,0x24,0xf8,0xf5,0x82,0xe4,0x34,0xfe,0xf5,0x83,
+0xec,0xf0,0x05,0x22,0x0d,0xed,0x70,0x01,0x0e,0x8d,0x64,0x8e,0x63,0x8f,0x62,0x80,
+0xd3,0xe5,0x21,0x54,0x7f,0x90,0xff,0x81,0xf0,0x22,0x8c,0x48,0x7f,0x00,0xef,0x24,
+0xfb,0x40,0x19,0xe4,0xef,0x75,0xf0,0x07,0xa4,0x24,0x3f,0xf5,0x82,0xe4,0x34,0xfc,
+0xf5,0x83,0xe0,0x65,0x48,0x70,0x02,0xd3,0x22,0x0f,0x80,0xe2,0x8f,0x47,0xc3,0x22,
+0x85,0x6c,0x6a,0x85,0x6b,0x69,0x90,0xff,0x82,0xe0,0x54,0xf7,0xf0,0x90,0xff,0x83,
+0xe0,0x54,0x7f,0xf0,0x22,0xc0,0x00,0xc0,0x01,0xc0,0x02,0xc0,0x06,0xc0,0x07,0xe5,
+0x72,0x24,0x08,0xf8,0x86,0x06,0x53,0x06,0x7f,0x7c,0xff,0x12,0x30,0xfa,0x7c,0x00,
+0x7d,0x00,0xe5,0x75,0x60,0x46,0xff,0x90,0xfe,0x9d,0xe0,0x54,0x7f,0x6e,0x70,0x0f,
+0xc0,0x83,0xc0,0x82,0xa3,0xe0,0xfd,0xa3,0xe0,0xfc,0xa3,0x15,0x75,0x80,0x07,0xa3,
+0xa3,0xa3,0xdf,0xe6,0x80,0x26,0xdf,0x06,0xd0,0x82,0xd0,0x83,0x80,0x1e,0xe0,0xf8,
+0xa3,0xe0,0xf9,0xa3,0xe0,0xfa,0xd0,0x82,0xd0,0x83,0xe8,0xf0,0xa3,0xe9,0xf0,0xa3,
+0xea,0xf0,0xa3,0xc0,0x83,0xc0,0x82,0xa3,0xa3,0xa3,0x80,0xda,0x12,0x31,0x93,0xd0,
+0x07,0xd0,0x06,0xd0,0x02,0xd0,0x01,0xd0,0x00,0x22,0x85,0xa8,0x74,0x75,0xa8,0x88,
+0xec,0x70,0x02,0x7c,0x3f,0x8c,0x73,0x22,0xe5,0x72,0x24,0x08,0xf8,0x76,0x00,0x12,
+0x31,0xe7,0x80,0xfb,0xc0,0x00,0xc0,0x01,0xc0,0x02,0xc0,0x06,0xc0,0x07,0xae,0x04,
+0x7c,0xff,0x12,0x30,0xfa,0xe5,0x75,0x60,0x42,0xff,0x90,0xfe,0x9d,0xe0,0x54,0x7f,
+0x6e,0x70,0x0b,0xc0,0x83,0xc0,0x82,0xa3,0xa3,0xa3,0x15,0x75,0x80,0x07,0xa3,0xa3,
+0xa3,0xdf,0xea,0x80,0x26,0xdf,0x06,0xd0,0x82,0xd0,0x83,0x80,0xd8,0xe0,0xf8,0xa3,
+0xe0,0xf9,0xa3,0xe0,0xfa,0xd0,0x82,0xd0,0x83,0xe8,0xf0,0xa3,0xe9,0xf0,0xa3,0xea,
+0xf0,0xa3,0xc0,0x83,0xc0,0x82,0xa3,0xa3,0xa3,0x80,0xda,0x78,0x08,0x08,0x79,0x18,
+0x09,0x7c,0x01,0xe6,0x54,0x7f,0x6e,0x70,0x06,0x76,0x00,0x77,0x00,0x80,0x06,0x08,
+0x09,0x0c,0xbc,0x08,0xee,0x12,0x31,0x93,0xd0,0x07,0xd0,0x06,0xd0,0x02,0xd0,0x01,
+0xd0,0x00,0x22,0x75,0x73,0x00,0x85,0x74,0xa8,0x22,0xc0,0xf0,0xc0,0x82,0xc0,0x83,
+0xc3,0xe5,0x75,0x24,0xe8,0x50,0x05,0x12,0x31,0xe7,0x80,0xf4,0xec,0x60,0x31,0x90,
+0x34,0xb6,0xe4,0x93,0xc3,0x9c,0x40,0x28,0xc0,0x04,0x7c,0xff,0x12,0x30,0xfa,0xd0,
+0x04,0x43,0x04,0x80,0xe5,0x75,0x75,0xf0,0x03,0xa4,0x24,0x9d,0xf5,0x82,0xe4,0x34,
+0xfe,0xf5,0x83,0xec,0xf0,0xef,0xa3,0xf0,0xee,0xa3,0xf0,0x05,0x75,0x12,0x31,0x93,
+0xd0,0x83,0xd0,0x82,0xd0,0xf0,0x22,0xc0,0x04,0x7c,0x20,0xd2,0x8c,0xd2,0x8d,0xd5,
+0x04,0xfd,0xd0,0x04,0x22,0x75,0xa8,0x00,0x75,0x88,0x00,0x75,0xb8,0x00,0x75,0xf0,
+0x00,0x75,0xd0,0x00,0xe4,0xf8,0x90,0x00,0x00,0xf6,0x08,0xb8,0x00,0xfb,0x02,0x00,
+0x00,0xc3,0xed,0x94,0x02,0x50,0x04,0x7d,0x03,0x7c,0xe8,0xec,0xf4,0xfc,0xed,0xf4,
+0xfd,0x0c,0xbc,0x00,0x01,0x0d,0x8c,0x79,0x8d,0x78,0x22,0xc3,0xec,0x94,0xbc,0xed,
+0x94,0x02,0x50,0x04,0x7d,0x07,0x7c,0xd0,0xec,0xf4,0xfc,0xed,0xf4,0xfd,0x0c,0xbc,
+0x00,0x01,0x0d,0x8c,0x77,0x8d,0x76,0x22,0xec,0x70,0x01,0x22,0xc0,0x00,0xe5,0x72,
+0x24,0x18,0xf8,0xa6,0x04,0xe5,0x72,0x24,0x08,0xf8,0xc6,0x54,0x7f,0xf6,0xe6,0x30,
+0xe7,0x03,0xd0,0x00,0x22,0x12,0x31,0xe7,0x80,0xf4,0xc2,0x8c,0x85,0x76,0x8c,0x85,
+0x77,0x8a,0xd2,0x8c,0xc0,0xe0,0xc0,0xd0,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x00,
+0xc0,0x01,0xc0,0x02,0xc0,0x03,0xc0,0x04,0xc0,0x05,0xc0,0x06,0xc0,0x07,0x12,0x1b,
+0x28,0xe5,0x72,0x24,0x08,0xf8,0xe6,0x60,0x24,0xe5,0x72,0x24,0x10,0xf8,0xa6,0x81,
+0xe5,0x72,0x75,0xf0,0x21,0xa4,0x24,0x95,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0x78,
+0xa8,0xe5,0x81,0x04,0xc3,0x98,0xf9,0xe6,0xf0,0x08,0xa3,0xd9,0xfa,0x74,0x08,0x25,
+0x72,0xf8,0x05,0x72,0x08,0xe6,0x54,0x80,0x70,0x0c,0xe5,0x72,0xb4,0x07,0xf3,0x78,
+0x08,0x75,0x72,0x00,0x80,0xef,0xe5,0x72,0x24,0x10,0xf8,0x86,0x81,0xe5,0x72,0x75,
+0xf0,0x21,0xa4,0x24,0x95,0xf5,0x82,0xe4,0x34,0xfd,0xf5,0x83,0x78,0xa8,0xe5,0x81,
+0x04,0xc3,0x98,0xf9,0xe0,0xf6,0x08,0xa3,0xd9,0xfa,0xd0,0x07,0xd0,0x06,0xd0,0x05,
+0xd0,0x04,0xd0,0x03,0xd0,0x02,0xd0,0x01,0xd0,0x00,0xd0,0x83,0xd0,0x82,0xd0,0xf0,
+0xd0,0xd0,0xd0,0xe0,0x32,0xc0,0xe0,0xc0,0xd0,0xc0,0x00,0xc0,0x01,0xc0,0x02,0xc2,
+0x8e,0x85,0x78,0x8d,0x85,0x79,0x8b,0xd2,0x8e,0x78,0x19,0x79,0x09,0x7a,0x07,0xe7,
+0x70,0x04,0xa6,0x00,0x80,0x0b,0xe6,0x60,0x08,0x16,0xe6,0x70,0x04,0xe7,0x44,0x80,
+0xf7,0x08,0x09,0xda,0xea,0xe5,0x73,0x60,0x13,0x14,0xf5,0x73,0x70,0x0e,0xe5,0x72,
+0x24,0x08,0xf8,0x76,0x00,0x12,0x31,0x93,0xd2,0x8c,0xd2,0x8d,0xd0,0x02,0xd0,0x01,
+0xd0,0x00,0xd0,0xd0,0xd0,0xe0,0x32,0x75,0x81,0xa7,0x75,0x90,0x00,0x75,0x79,0x30,
+0x75,0x78,0xf8,0x75,0x77,0x60,0x75,0x76,0xf0,0x12,0x05,0x3c,0x12,0x34,0x0f,0x12,
+0x17,0x8b,0x12,0x34,0x39,0x12,0x31,0xf5,0x80,0xe3,0x22,0xc0,0x00,0x7c,0x01,0xec,
+0x24,0x08,0xf8,0xe6,0x60,0x09,0x0c,0xbc,0x08,0xf5,0x12,0x31,0xe7,0x80,0xee,0xd0,
+0x00,0x22,0xc0,0xf0,0xc0,0x82,0xc0,0x83,0xc0,0x00,0xc0,0x06,0xc0,0x07,0xed,0x24,
+0x10,0xf8,0x76,0xb6,0xed,0x75,0xf0,0x21,0xa4,0x24,0x95,0xf5,0x82,0xe4,0x34,0xfd,
+0xf5,0x83,0xc0,0x82,0xc0,0x83,0xa3,0xa3,0xe4,0x78,0x0d,0xf0,0xa3,0xd8,0xfc,0xec,
+0x54,0x7f,0x75,0xf0,0x02,0xa4,0x24,0x82,0xf5,0x82,0xe5,0xf0,0x34,0x34,0xf5,0x83,
+0xe4,0x93,0xfe,0x74,0x01,0x93,0xf5,0x82,0x8e,0x83,0xe4,0x93,0xfe,0x74,0x01,0x93,
+0xff,0xd0,0x83,0xd0,0x82,0xef,0xf0,0xa3,0xee,0xf0,0xed,0x24,0x08,0xf8,0xec,0x44,
+0x80,0xf6,0xd0,0x07,0xd0,0x06,0xd0,0x00,0xd0,0x83,0xd0,0x82,0xd0,0xf0,0x22,0x75,
+0x72,0x00,0x75,0x75,0x00,0x7a,0x08,0x79,0x18,0x78,0x08,0x76,0x00,0x77,0x00,0x08,
+0x09,0xda,0xf8,0xe4,0x78,0x08,0x74,0x80,0x44,0x7f,0xf6,0x74,0x01,0x44,0x10,0xf5,
+0x89,0x75,0xb8,0x08,0xd2,0xab,0xd2,0xa9,0x22,0x75,0x81,0xa7,0xd2,0x8e,0xd2,0x8c,
+0xd2,0xaf,0xe5,0x75,0x60,0x32,0xff,0x90,0xfe,0x9d,0xe0,0x54,0x80,0x60,0x24,0x78,
+0x08,0x79,0x08,0xe0,0x54,0x7f,0xfa,0x7b,0x00,0xe6,0x54,0x7f,0xb5,0x02,0x02,0x7b,
+0xff,0x08,0xd9,0xf5,0xeb,0x70,0x0c,0xea,0xf0,0x12,0x33,0x8b,0xad,0x04,0xac,0x02,
+0x12,0x33,0xa2,0xa3,0xa3,0xa3,0xdf,0xd2,0x12,0x31,0xe7,0x80,0xc5,0x7c,0x01,0x7d,
+0x00,0x22,0x04,0xf5,0x04,0xe9,0x04,0xed,0x04,0xe1,0x04,0xdd,0x04,0xd9,0x04,0xe5,
+0x04,0xf1,0x04,0x9d,0x04,0xa1,0x04,0xcd,0x04,0xd1,0x04,0x99,0x04,0x99,0x04,0x99,
+0x04,0xd5,0x04,0xb5,0x04,0xad,0x04,0xb1,0x04,0xa9,0x04,0xc1,0x04,0xbd,0x04,0xb9,
+0x04,0xc5,0x04,0xc9,0x04,0xa5,0x19,0x01,0x03,0x00,0x22,0x00,0x48,0x02,0x00,0x24,
+0x0f,0x18,0x0a,0x10,0x64,0x0d,0x68,0x0c,0x05,0x06,0x02,0x03,0x01,0x01,0x81,0x01,
+0x00,0x00,0xe7,0x00,0xc0,0x00,0x80,0x00,0x60,0x00,0x40,0x00,0x30,0x00,0x18,0x00,
+0x0c,0x00,0x08,0x00,0x04,0x00,0x02,0x00,0x01,0x00,0x08,0x18,0x38,0x28,0x06,0x02,
+0x10,0x0a,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x81,0x10,0x0a,0x02,0x00,0x00,0x00,
+0x00,0x00,0xfb,0xe8,0xfb,0xfa,0x12,0x01,0x10,0x01,0xff,0x00,0x00,0x08,0x51,0x04,
+0x5f,0x50,0x16,0x01,0x01,0x02,0x00,0x02,0x09,0x02,0x35,0x00,0x01,0x02,0x00,0xe0,
+0x00,0x09,0x04,0x00,0x00,0x05,0xff,0x00,0x00,0x00,0x07,0x05,0x81,0x02,0x40,0x00,
+0x00,0x07,0x05,0x01,0x02,0x40,0x00,0x00,0x07,0x05,0x82,0x02,0x40,0x00,0x00,0x07,
+0x05,0x02,0x02,0x40,0x00,0x00,0x07,0x05,0x85,0x03,0x02,0x00,0x01,0x04,0x03,0x09,
+0x04,0x24,0x03,0x54,0x00,0x65,0x00,0x78,0x00,0x61,0x00,0x73,0x00,0x20,0x00,0x49,
+0x00,0x6e,0x00,0x73,0x00,0x74,0x00,0x72,0x00,0x75,0x00,0x6d,0x00,0x65,0x00,0x6e,
+0x00,0x74,0x00,0x73,0x00,0x2a,0x03,0x54,0x00,0x55,0x00,0x53,0x00,0x42,0x00,0x35,
+0x00,0x30,0x00,0x35,0x00,0x32,0x00,0x20,0x00,0x53,0x00,0x65,0x00,0x72,0x00,0x69,
+0x00,0x61,0x00,0x6c,0x00,0x20,0x00,0x50,0x00,0x6f,0x00,0x72,0x00,0x74,0x00,0x22,
+0x03,0x54,0x00,0x55,0x00,0x53,0x00,0x42,0x00,0x35,0x00,0x30,0x00,0x35,0x00,0x32,
+0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x20,
+0x00,
+};
+
+#endif /* ifndef _TI_FW_5052_H_ */
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
new file mode 100644
index 00000000000000..dc18427cf4e43b
--- /dev/null
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -0,0 +1,1842 @@
+/* vi: ts=8 sw=8
+ *
+ * TI 3410/5052 USB Serial Driver
+ *
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * This driver is based on the Linux io_ti driver, which is
+ * Copyright (C) 2000-2002 Inside Out Networks
+ * Copyright (C) 2001-2002 Greg Kroah-Hartman
+ *
+ * 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.
+ *
+ * For questions or problems with this driver, contact Texas Instruments
+ * technical support, or Al Borchers <alborchers@steinerpoint.com>, or
+ * Peter Berger <pberger@brimson.com>.
+ *
+ * This driver needs this hotplug script in /etc/hotplug/usb/ti_usb_3410_5052
+ * or in /etc/hotplug.d/usb/ti_usb_3410_5052.hotplug to set the device
+ * configuration.
+ *
+ * #!/bin/bash
+ *
+ * BOOT_CONFIG=1
+ * ACTIVE_CONFIG=2
+ *
+ * if [[ "$ACTION" != "add" ]]
+ * then
+ * exit
+ * fi
+ *
+ * CONFIG_PATH=/sys${DEVPATH%/?*}/bConfigurationValue
+ *
+ * if [[ 0`cat $CONFIG_PATH` -ne $BOOT_CONFIG ]]
+ * then
+ * exit
+ * fi
+ *
+ * PRODUCT=${PRODUCT%/?*} # delete version
+ * VENDOR_ID=`printf "%d" 0x${PRODUCT%/?*}`
+ * PRODUCT_ID=`printf "%d" 0x${PRODUCT#*?/}`
+ *
+ * PARAM_PATH=/sys/module/ti_usb_3410_5052/parameters
+ *
+ * function scan() {
+ * s=$1
+ * shift
+ * for i
+ * do
+ * if [[ $s -eq $i ]]
+ * then
+ * return 0
+ * fi
+ * done
+ * return 1
+ * }
+ *
+ * IFS=$IFS,
+ *
+ * if (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_3410` &&
+ * scan $PRODUCT_ID 13328 `cat $PARAM_PATH/product_3410`) ||
+ * (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_5052` &&
+ * scan $PRODUCT_ID 20562 20818 20570 20575 `cat $PARAM_PATH/product_5052`)
+ * then
+ * echo $ACTIVE_CONFIG > $CONFIG_PATH
+ * fi
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/ioctl.h>
+#include <linux/serial.h>
+#include <linux/circ_buf.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <linux/usb.h>
+
+#include "usb-serial.h"
+#include "ti_usb_3410_5052.h"
+#include "ti_fw_3410.h" /* firmware image for 3410 */
+#include "ti_fw_5052.h" /* firmware image for 5052 */
+
+
+/* Defines */
+
+#define TI_DRIVER_VERSION "v0.9"
+#define TI_DRIVER_AUTHOR "Al Borchers <alborchers@steinerpoint.com>"
+#define TI_DRIVER_DESC "TI USB 3410/5052 Serial Driver"
+
+#define TI_FIRMWARE_BUF_SIZE 16284
+
+#define TI_WRITE_BUF_SIZE 1024
+
+#define TI_TRANSFER_TIMEOUT 2
+
+#define TI_DEFAULT_LOW_LATENCY 0
+#define TI_DEFAULT_CLOSING_WAIT 4000 /* in .01 secs */
+
+/* supported setserial flags */
+#define TI_SET_SERIAL_FLAGS (ASYNC_LOW_LATENCY)
+
+/* read urb states */
+#define TI_READ_URB_RUNNING 0
+#define TI_READ_URB_STOPPING 1
+#define TI_READ_URB_STOPPED 2
+
+#define TI_EXTRA_VID_PID_COUNT 5
+
+
+/* Structures */
+
+struct ti_port {
+ int tp_is_open;
+ __u8 tp_msr;
+ __u8 tp_lsr;
+ __u8 tp_shadow_mcr;
+ __u8 tp_uart_mode; /* 232 or 485 modes */
+ unsigned int tp_uart_base_addr;
+ int tp_flags;
+ int tp_closing_wait;/* in .01 secs */
+ struct async_icount tp_icount;
+ wait_queue_head_t tp_msr_wait; /* wait for msr change */
+ wait_queue_head_t tp_write_wait;
+ struct ti_device *tp_tdev;
+ struct usb_serial_port *tp_port;
+ spinlock_t tp_lock;
+ int tp_read_urb_state;
+ int tp_write_urb_in_use;
+ struct circ_buf *tp_write_buf;
+};
+
+struct ti_device {
+ struct semaphore td_open_close_sem;
+ int td_open_port_count;
+ struct usb_serial *td_serial;
+ int td_is_3410;
+ int td_urb_error;
+};
+
+
+/* Function Declarations */
+
+static int ti_startup(struct usb_serial *serial);
+static void ti_shutdown(struct usb_serial *serial);
+static int ti_open(struct usb_serial_port *port, struct file *file);
+static void ti_close(struct usb_serial_port *port, struct file *file);
+static int ti_write(struct usb_serial_port *port, const unsigned char *data,
+ int count);
+static int ti_write_room(struct usb_serial_port *port);
+static int ti_chars_in_buffer(struct usb_serial_port *port);
+static void ti_throttle(struct usb_serial_port *port);
+static void ti_unthrottle(struct usb_serial_port *port);
+static int ti_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg);
+static void ti_set_termios(struct usb_serial_port *port,
+ struct termios *old_termios);
+static int ti_tiocmget(struct usb_serial_port *port, struct file *file);
+static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear);
+static void ti_break(struct usb_serial_port *port, int break_state);
+static void ti_interrupt_callback(struct urb *urb, struct pt_regs *regs);
+static void ti_bulk_in_callback(struct urb *urb, struct pt_regs *regs);
+static void ti_bulk_out_callback(struct urb *urb, struct pt_regs *regs);
+
+static void ti_recv(struct device *dev, struct tty_struct *tty,
+ unsigned char *data, int length);
+static void ti_send(struct ti_port *tport);
+static int ti_set_mcr(struct ti_port *tport, unsigned int mcr);
+static int ti_get_lsr(struct ti_port *tport);
+static int ti_get_serial_info(struct ti_port *tport,
+ struct serial_struct __user *ret_arg);
+static int ti_set_serial_info(struct ti_port *tport,
+ struct serial_struct __user *new_arg);
+static void ti_handle_new_msr(struct ti_port *tport, __u8 msr);
+
+static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush);
+
+static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty);
+static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty);
+
+static int ti_command_out_sync(struct ti_device *tdev, __u8 command,
+ __u16 moduleid, __u16 value, __u8 *data, int size);
+static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
+ __u16 moduleid, __u16 value, __u8 *data, int size);
+
+static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
+ __u8 mask, __u8 byte);
+
+static int ti_download_firmware(struct ti_device *tdev,
+ unsigned char *firmware, unsigned int firmware_size);
+
+/* circular buffer */
+static struct circ_buf *ti_buf_alloc(void);
+static void ti_buf_free(struct circ_buf *cb);
+static void ti_buf_clear(struct circ_buf *cb);
+static int ti_buf_data_avail(struct circ_buf *cb);
+static int ti_buf_space_avail(struct circ_buf *cb);
+static int ti_buf_put(struct circ_buf *cb, const char *buf, int count);
+static int ti_buf_get(struct circ_buf *cb, char *buf, int count);
+
+
+/* Data */
+
+/* module parameters */
+static int debug;
+static int low_latency = TI_DEFAULT_LOW_LATENCY;
+static int closing_wait = TI_DEFAULT_CLOSING_WAIT;
+static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT];
+static int vendor_3410_count;
+static ushort product_3410[TI_EXTRA_VID_PID_COUNT];
+static int product_3410_count;
+static ushort vendor_5052[TI_EXTRA_VID_PID_COUNT];
+static int vendor_5052_count;
+static ushort product_5052[TI_EXTRA_VID_PID_COUNT];
+static int product_5052_count;
+
+/* supported devices */
+/* the array dimension is the number of default entries plus */
+/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
+/* null entry */
+static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = {
+ { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
+};
+
+static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
+ { USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
+};
+
+static struct usb_device_id ti_id_table_combined[] = {
+ { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
+ { }
+};
+
+static struct usb_driver ti_usb_driver = {
+ .owner = THIS_MODULE,
+ .name = "ti_usb_3410_5052",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = ti_id_table_combined,
+};
+
+static struct usb_serial_device_type ti_1port_device = {
+ .owner = THIS_MODULE,
+ .name = "TI USB 3410 1 port adapter",
+ .id_table = ti_id_table_3410,
+ .num_interrupt_in = 1,
+ .num_bulk_in = 1,
+ .num_bulk_out = 1,
+ .num_ports = 1,
+ .attach = ti_startup,
+ .shutdown = ti_shutdown,
+ .open = ti_open,
+ .close = ti_close,
+ .write = ti_write,
+ .write_room = ti_write_room,
+ .chars_in_buffer = ti_chars_in_buffer,
+ .throttle = ti_throttle,
+ .unthrottle = ti_unthrottle,
+ .ioctl = ti_ioctl,
+ .set_termios = ti_set_termios,
+ .tiocmget = ti_tiocmget,
+ .tiocmset = ti_tiocmset,
+ .break_ctl = ti_break,
+ .read_int_callback = ti_interrupt_callback,
+ .read_bulk_callback = ti_bulk_in_callback,
+ .write_bulk_callback = ti_bulk_out_callback,
+};
+
+static struct usb_serial_device_type ti_2port_device = {
+ .owner = THIS_MODULE,
+ .name = "TI USB 5052 2 port adapter",
+ .id_table = ti_id_table_5052,
+ .num_interrupt_in = 1,
+ .num_bulk_in = 2,
+ .num_bulk_out = 2,
+ .num_ports = 2,
+ .attach = ti_startup,
+ .shutdown = ti_shutdown,
+ .open = ti_open,
+ .close = ti_close,
+ .write = ti_write,
+ .write_room = ti_write_room,
+ .chars_in_buffer = ti_chars_in_buffer,
+ .throttle = ti_throttle,
+ .unthrottle = ti_unthrottle,
+ .ioctl = ti_ioctl,
+ .set_termios = ti_set_termios,
+ .tiocmget = ti_tiocmget,
+ .tiocmset = ti_tiocmset,
+ .break_ctl = ti_break,
+ .read_int_callback = ti_interrupt_callback,
+ .read_bulk_callback = ti_bulk_in_callback,
+ .write_bulk_callback = ti_bulk_out_callback,
+};
+
+
+/* Module */
+
+MODULE_AUTHOR(TI_DRIVER_AUTHOR);
+MODULE_DESCRIPTION(TI_DRIVER_DESC);
+MODULE_VERSION(TI_DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes");
+
+module_param(low_latency, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(low_latency, "TTY low_latency flag, 0=off, 1=on, default is off");
+
+module_param(closing_wait, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain in close, in .01 secs, default is 4000");
+
+module_param_array(vendor_3410, ushort, &vendor_3410_count, S_IRUGO);
+MODULE_PARM_DESC(vendor_3410, "Vendor ids for 3410 based devices, 1-5 short integers");
+module_param_array(product_3410, ushort, &product_3410_count, S_IRUGO);
+MODULE_PARM_DESC(product_3410, "Product ids for 3410 based devices, 1-5 short integers");
+module_param_array(vendor_5052, ushort, &vendor_5052_count, S_IRUGO);
+MODULE_PARM_DESC(vendor_5052, "Vendor ids for 5052 based devices, 1-5 short integers");
+module_param_array(product_5052, ushort, &product_5052_count, S_IRUGO);
+MODULE_PARM_DESC(product_5052, "Product ids for 5052 based devices, 1-5 short integers");
+
+MODULE_DEVICE_TABLE(usb, ti_id_table_combined);
+
+
+/* Functions */
+
+static int __init ti_init(void)
+{
+ int i,j;
+ int ret;
+
+
+ /* insert extra vendor and product ids */
+ j = sizeof(ti_id_table_3410)/sizeof(struct usb_device_id)
+ - TI_EXTRA_VID_PID_COUNT - 1;
+ for (i=0; i<min(vendor_3410_count,product_3410_count); i++,j++) {
+ ti_id_table_3410[j].idVendor = vendor_3410[i];
+ ti_id_table_3410[j].idProduct = product_3410[i];
+ ti_id_table_3410[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ }
+ j = sizeof(ti_id_table_5052)/sizeof(struct usb_device_id)
+ - TI_EXTRA_VID_PID_COUNT - 1;
+ for (i=0; i<min(vendor_5052_count,product_5052_count); i++,j++) {
+ ti_id_table_5052[j].idVendor = vendor_5052[i];
+ ti_id_table_5052[j].idProduct = product_5052[i];
+ ti_id_table_5052[j].match_flags = USB_DEVICE_ID_MATCH_DEVICE;
+ }
+
+ ret = usb_serial_register(&ti_1port_device);
+ if (ret)
+ goto failed_1port;
+ ret = usb_serial_register(&ti_2port_device);
+ if (ret)
+ goto failed_2port;
+
+ ret = usb_register(&ti_usb_driver);
+ if (ret)
+ goto failed_usb;
+
+ info(TI_DRIVER_DESC " " TI_DRIVER_VERSION);
+
+ return 0;
+
+failed_usb:
+ usb_serial_deregister(&ti_2port_device);
+failed_2port:
+ usb_serial_deregister(&ti_1port_device);
+failed_1port:
+ return ret;
+}
+
+
+static void __exit ti_exit(void)
+{
+ usb_serial_deregister(&ti_1port_device);
+ usb_serial_deregister(&ti_2port_device);
+ usb_deregister(&ti_usb_driver);
+}
+
+
+module_init(ti_init);
+module_exit(ti_exit);
+
+
+static int ti_startup(struct usb_serial *serial)
+{
+ struct ti_device *tdev;
+ struct ti_port *tport;
+ struct usb_device *dev = serial->dev;
+ int status;
+ int i;
+
+
+ dbg("%s - product 0x%4X, num configurations %d, configuration value %d",
+ __FUNCTION__, le16_to_cpu(dev->descriptor.idProduct),
+ dev->descriptor.bNumConfigurations,
+ dev->actconfig->desc.bConfigurationValue);
+
+ /* create device structure */
+ tdev = kmalloc(sizeof(struct ti_device), GFP_KERNEL);
+ if (tdev == NULL) {
+ dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+ memset(tdev, 0, sizeof(struct ti_device));
+ sema_init(&tdev->td_open_close_sem, 1);
+ tdev->td_serial = serial;
+ usb_set_serial_data(serial, tdev);
+
+ /* determine device type */
+ if (usb_match_id(serial->interface, ti_id_table_3410))
+ tdev->td_is_3410 = 1;
+ dbg("%s - device type is %s", __FUNCTION__, tdev->td_is_3410 ? "3410" : "5052");
+
+ /* if we have only 1 configuration, download firmware */
+ if (dev->descriptor.bNumConfigurations == 1) {
+
+ if (tdev->td_is_3410)
+ status = ti_download_firmware(tdev, ti_fw_3410,
+ sizeof(ti_fw_3410));
+ else
+ status = ti_download_firmware(tdev, ti_fw_5052,
+ sizeof(ti_fw_5052));
+ if (status)
+ goto free_tdev;
+
+ /* 3410 must be reset, 5052 resets itself */
+ if (tdev->td_is_3410) {
+ msleep_interruptible(100);
+ usb_reset_device(dev);
+ }
+
+ status = -ENODEV;
+ goto free_tdev;
+ }
+
+ /* the second configuration must be set (in sysfs by hotplug script) */
+ if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) {
+ status = -ENODEV;
+ goto free_tdev;
+ }
+
+ /* set up port structures */
+ for (i = 0; i < serial->num_ports; ++i) {
+ tport = kmalloc(sizeof(struct ti_port), GFP_KERNEL);
+ if (tport == NULL) {
+ dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+ status = -ENOMEM;
+ goto free_tports;
+ }
+ memset(tport, 0, sizeof(struct ti_port));
+ spin_lock_init(&tport->tp_lock);
+ tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
+ tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
+ tport->tp_closing_wait = closing_wait;
+ init_waitqueue_head(&tport->tp_msr_wait);
+ init_waitqueue_head(&tport->tp_write_wait);
+ tport->tp_write_buf = ti_buf_alloc();
+ if (tport->tp_write_buf == NULL) {
+ dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+ kfree(tport);
+ status = -ENOMEM;
+ goto free_tports;
+ }
+ tport->tp_port = serial->port[i];
+ tport->tp_tdev = tdev;
+ usb_set_serial_port_data(serial->port[i], tport);
+ tport->tp_uart_mode = 0; /* default is RS232 */
+ }
+
+ return 0;
+
+free_tports:
+ for (--i; i>=0; --i) {
+ tport = usb_get_serial_port_data(serial->port[i]);
+ ti_buf_free(tport->tp_write_buf);
+ kfree(tport);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+free_tdev:
+ kfree(tdev);
+ usb_set_serial_data(serial, NULL);
+ return status;
+}
+
+
+static void ti_shutdown(struct usb_serial *serial)
+{
+ int i;
+ struct ti_device *tdev = usb_get_serial_data(serial);
+ struct ti_port *tport;
+
+ dbg("%s", __FUNCTION__);
+
+ for (i=0; i < serial->num_ports; ++i) {
+ tport = usb_get_serial_port_data(serial->port[i]);
+ if (tport) {
+ ti_buf_free(tport->tp_write_buf);
+ kfree(tport);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+ }
+
+ if (tdev)
+ kfree(tdev);
+ usb_set_serial_data(serial, NULL);
+}
+
+
+static int ti_open(struct usb_serial_port *port, struct file *file)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ struct ti_device *tdev;
+ struct usb_device *dev;
+ struct urb *urb;
+ int port_number;
+ int status;
+ __u16 open_settings = (__u8)(TI_PIPE_MODE_CONTINOUS |
+ TI_PIPE_TIMEOUT_ENABLE |
+ (TI_TRANSFER_TIMEOUT << 2));
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+
+ dev = port->serial->dev;
+ tdev = tport->tp_tdev;
+
+ /* only one open on any port on a device at a time */
+ if (down_interruptible(&tdev->td_open_close_sem))
+ return -ERESTARTSYS;
+
+ if (port->tty)
+ port->tty->low_latency =
+ (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+
+ port_number = port->number - port->serial->minor;
+
+ memset(&(tport->tp_icount), 0x00, sizeof(tport->tp_icount));
+
+ tport->tp_msr = 0;
+ tport->tp_shadow_mcr |= (TI_MCR_RTS | TI_MCR_DTR);
+
+ /* start interrupt urb the first time a port is opened on this device */
+ if (tdev->td_open_port_count == 0) {
+ dbg("%s - start interrupt in urb", __FUNCTION__);
+ urb = tdev->td_serial->port[0]->interrupt_in_urb;
+ if (!urb) {
+ dev_err(&port->dev, "%s - no interrupt urb\n", __FUNCTION__);
+ status = -EINVAL;
+ goto up_sem;
+ }
+ urb->complete = ti_interrupt_callback;
+ urb->context = tdev;
+ urb->dev = dev;
+ status = usb_submit_urb(urb, GFP_KERNEL);
+ if (status) {
+ dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __FUNCTION__, status);
+ goto up_sem;
+ }
+ }
+
+ ti_set_termios(port, NULL);
+
+ dbg("%s - sending TI_OPEN_PORT", __FUNCTION__);
+ status = ti_command_out_sync(tdev, TI_OPEN_PORT,
+ (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
+ if (status) {
+ dev_err(&port->dev, "%s - cannot send open command, %d\n", __FUNCTION__, status);
+ goto unlink_int_urb;
+ }
+
+ dbg("%s - sending TI_START_PORT", __FUNCTION__);
+ status = ti_command_out_sync(tdev, TI_START_PORT,
+ (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
+ if (status) {
+ dev_err(&port->dev, "%s - cannot send start command, %d\n", __FUNCTION__, status);
+ goto unlink_int_urb;
+ }
+
+ dbg("%s - sending TI_PURGE_PORT", __FUNCTION__);
+ status = ti_command_out_sync(tdev, TI_PURGE_PORT,
+ (__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0);
+ if (status) {
+ dev_err(&port->dev, "%s - cannot clear input buffers, %d\n", __FUNCTION__, status);
+ goto unlink_int_urb;
+ }
+ status = ti_command_out_sync(tdev, TI_PURGE_PORT,
+ (__u8)(TI_UART1_PORT + port_number), TI_PURGE_OUTPUT, NULL, 0);
+ if (status) {
+ dev_err(&port->dev, "%s - cannot clear output buffers, %d\n", __FUNCTION__, status);
+ goto unlink_int_urb;
+ }
+
+ /* reset the data toggle on the bulk endpoints to work around bug in
+ * host controllers where things get out of sync some times */
+ usb_clear_halt(dev, port->write_urb->pipe);
+ usb_clear_halt(dev, port->read_urb->pipe);
+
+ ti_set_termios(port, NULL);
+
+ dbg("%s - sending TI_OPEN_PORT (2)", __FUNCTION__);
+ status = ti_command_out_sync(tdev, TI_OPEN_PORT,
+ (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0);
+ if (status) {
+ dev_err(&port->dev, "%s - cannot send open command (2), %d\n", __FUNCTION__, status);
+ goto unlink_int_urb;
+ }
+
+ dbg("%s - sending TI_START_PORT (2)", __FUNCTION__);
+ status = ti_command_out_sync(tdev, TI_START_PORT,
+ (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
+ if (status) {
+ dev_err(&port->dev, "%s - cannot send start command (2), %d\n", __FUNCTION__, status);
+ goto unlink_int_urb;
+ }
+
+ /* start read urb */
+ dbg("%s - start read urb", __FUNCTION__);
+ urb = port->read_urb;
+ if (!urb) {
+ dev_err(&port->dev, "%s - no read urb\n", __FUNCTION__);
+ status = -EINVAL;
+ goto unlink_int_urb;
+ }
+ tport->tp_read_urb_state = TI_READ_URB_RUNNING;
+ urb->complete = ti_bulk_in_callback;
+ urb->context = tport;
+ urb->dev = dev;
+ status = usb_submit_urb(urb, GFP_KERNEL);
+ if (status) {
+ dev_err(&port->dev, "%s - submit read urb failed, %d\n", __FUNCTION__, status);
+ goto unlink_int_urb;
+ }
+
+ tport->tp_is_open = 1;
+ ++tdev->td_open_port_count;
+
+ goto up_sem;
+
+unlink_int_urb:
+ if (tdev->td_open_port_count == 0)
+ usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
+up_sem:
+ up(&tdev->td_open_close_sem);
+ dbg("%s - exit %d", __FUNCTION__, status);
+ return status;
+}
+
+
+static void ti_close(struct usb_serial_port *port, struct file *file)
+{
+ struct ti_device *tdev;
+ struct ti_port *tport;
+ int port_number;
+ int status;
+ int do_up;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ tdev = usb_get_serial_data(port->serial);
+ tport = usb_get_serial_port_data(port);
+ if (tdev == NULL || tport == NULL)
+ return;
+
+ tport->tp_is_open = 0;
+
+ ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 1);
+
+ usb_kill_urb(port->read_urb);
+ usb_kill_urb(port->write_urb);
+ tport->tp_write_urb_in_use = 0;
+
+ port_number = port->number - port->serial->minor;
+
+ dbg("%s - sending TI_CLOSE_PORT", __FUNCTION__);
+ status = ti_command_out_sync(tdev, TI_CLOSE_PORT,
+ (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0);
+ if (status)
+ dev_err(&port->dev, "%s - cannot send close port command, %d\n" , __FUNCTION__, status);
+
+ /* if down is interrupted, continue anyway */
+ do_up = !down_interruptible(&tdev->td_open_close_sem);
+ --tport->tp_tdev->td_open_port_count;
+ if (tport->tp_tdev->td_open_port_count <= 0) {
+ /* last port is closed, shut down interrupt urb */
+ usb_kill_urb(port->serial->port[0]->interrupt_in_urb);
+ tport->tp_tdev->td_open_port_count = 0;
+ }
+ if (do_up)
+ up(&tdev->td_open_close_sem);
+
+ dbg("%s - exit", __FUNCTION__);
+}
+
+
+static int ti_write(struct usb_serial_port *port, const unsigned char *data,
+ int count)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ unsigned long flags;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (count == 0) {
+ dbg("%s - write request of 0 bytes", __FUNCTION__);
+ return 0;
+ }
+
+ if (tport == NULL || !tport->tp_is_open)
+ return -ENODEV;
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+ count = ti_buf_put(tport->tp_write_buf, data, count);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ ti_send(tport);
+
+ return count;
+}
+
+
+static int ti_write_room(struct usb_serial_port *port)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ int room = 0;
+ unsigned long flags;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+ room = ti_buf_space_avail(tport->tp_write_buf);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ dbg("%s - returns %d", __FUNCTION__, room);
+ return room;
+}
+
+
+static int ti_chars_in_buffer(struct usb_serial_port *port)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ int chars = 0;
+ unsigned long flags;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+ chars = ti_buf_data_avail(tport->tp_write_buf);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ dbg("%s - returns %d", __FUNCTION__, chars);
+ return chars;
+}
+
+
+static void ti_throttle(struct usb_serial_port *port)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (tport == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+ dbg("%s - no tty", __FUNCTION__);
+ return;
+ }
+
+ if (I_IXOFF(tty) || C_CRTSCTS(tty))
+ ti_stop_read(tport, tty);
+
+}
+
+
+static void ti_unthrottle(struct usb_serial_port *port)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ struct tty_struct *tty;
+ int status;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (tport == NULL)
+ return;
+
+ tty = port->tty;
+ if (!tty) {
+ dbg("%s - no tty", __FUNCTION__);
+ return;
+ }
+
+ if (I_IXOFF(tty) || C_CRTSCTS(tty)) {
+ status = ti_restart_read(tport, tty);
+ if (status)
+ dev_err(&port->dev, "%s - cannot restart read, %d\n", __FUNCTION__, status);
+ }
+}
+
+
+static int ti_ioctl(struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ struct async_icount cnow;
+ struct async_icount cprev;
+
+ dbg("%s - port %d, cmd = 0x%04X", __FUNCTION__, port->number, cmd);
+
+ if (tport == NULL)
+ return -ENODEV;
+
+ switch (cmd) {
+ case TIOCGSERIAL:
+ dbg("%s - (%d) TIOCGSERIAL", __FUNCTION__, port->number);
+ return ti_get_serial_info(tport, (struct serial_struct __user *)arg);
+ break;
+
+ case TIOCSSERIAL:
+ dbg("%s - (%d) TIOCSSERIAL", __FUNCTION__, port->number);
+ return ti_set_serial_info(tport, (struct serial_struct __user *)arg);
+ break;
+
+ case TIOCMIWAIT:
+ dbg("%s - (%d) TIOCMIWAIT", __FUNCTION__, port->number);
+ cprev = tport->tp_icount;
+ while (1) {
+ interruptible_sleep_on(&tport->tp_msr_wait);
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ cnow = tport->tp_icount;
+ if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
+ cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
+ return -EIO; /* no change => error */
+ if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
+ ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
+ ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) ||
+ ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
+ return 0;
+ }
+ cprev = cnow;
+ }
+ break;
+
+ case TIOCGICOUNT:
+ dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, port->number, tport->tp_icount.rx, tport->tp_icount.tx);
+ if (copy_to_user((void __user *)arg, &tport->tp_icount, sizeof(tport->tp_icount)))
+ return -EFAULT;
+ return 0;
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+
+static void ti_set_termios(struct usb_serial_port *port,
+ struct termios *old_termios)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ struct tty_struct *tty = port->tty;
+ struct ti_uart_config *config;
+ tcflag_t cflag,iflag;
+ int baud;
+ int status;
+ int port_number = port->number - port->serial->minor;
+ unsigned int mcr;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (!tty || !tty->termios) {
+ dbg("%s - no tty or termios", __FUNCTION__);
+ return;
+ }
+
+ cflag = tty->termios->c_cflag;
+ iflag = tty->termios->c_iflag;
+
+ if (old_termios && cflag == old_termios->c_cflag
+ && iflag == old_termios->c_iflag) {
+ dbg("%s - nothing to change", __FUNCTION__);
+ return;
+ }
+
+ dbg("%s - clfag %08x, iflag %08x", __FUNCTION__, cflag, iflag);
+
+ if (old_termios)
+ dbg("%s - old clfag %08x, old iflag %08x", __FUNCTION__, old_termios->c_cflag, old_termios->c_iflag);
+
+ if (tport == NULL)
+ return;
+
+ config = kmalloc(sizeof(*config), GFP_KERNEL);
+ if (!config) {
+ dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__);
+ return;
+ }
+
+ config->wFlags = 0;
+
+ /* these flags must be set */
+ config->wFlags |= TI_UART_ENABLE_MS_INTS;
+ config->wFlags |= TI_UART_ENABLE_AUTO_START_DMA;
+ config->bUartMode = (__u8)(tport->tp_uart_mode);
+
+ switch (cflag & CSIZE) {
+ case CS5:
+ config->bDataBits = TI_UART_5_DATA_BITS;
+ break;
+ case CS6:
+ config->bDataBits = TI_UART_6_DATA_BITS;
+ break;
+ case CS7:
+ config->bDataBits = TI_UART_7_DATA_BITS;
+ break;
+ default:
+ case CS8:
+ config->bDataBits = TI_UART_8_DATA_BITS;
+ break;
+ }
+
+ if (cflag & PARENB) {
+ if (cflag & PARODD) {
+ config->wFlags |= TI_UART_ENABLE_PARITY_CHECKING;
+ config->bParity = TI_UART_ODD_PARITY;
+ } else {
+ config->wFlags |= TI_UART_ENABLE_PARITY_CHECKING;
+ config->bParity = TI_UART_EVEN_PARITY;
+ }
+ } else {
+ config->wFlags &= ~TI_UART_ENABLE_PARITY_CHECKING;
+ config->bParity = TI_UART_NO_PARITY;
+ }
+
+ if (cflag & CSTOPB)
+ config->bStopBits = TI_UART_2_STOP_BITS;
+ else
+ config->bStopBits = TI_UART_1_STOP_BITS;
+
+ if (cflag & CRTSCTS) {
+ /* RTS flow control must be off to drop RTS for baud rate B0 */
+ if ((cflag & CBAUD) != B0)
+ config->wFlags |= TI_UART_ENABLE_RTS_IN;
+ config->wFlags |= TI_UART_ENABLE_CTS_OUT;
+ } else {
+ tty->hw_stopped = 0;
+ ti_restart_read(tport, tty);
+ }
+
+ if (I_IXOFF(tty) || I_IXON(tty)) {
+ config->cXon = START_CHAR(tty);
+ config->cXoff = STOP_CHAR(tty);
+
+ if (I_IXOFF(tty))
+ config->wFlags |= TI_UART_ENABLE_X_IN;
+ else
+ ti_restart_read(tport, tty);
+
+ if (I_IXON(tty))
+ config->wFlags |= TI_UART_ENABLE_X_OUT;
+ }
+
+ baud = tty_get_baud_rate(tty);
+ if (!baud) baud = 9600;
+ if (tport->tp_tdev->td_is_3410)
+ config->wBaudRate = (__u16)((923077 + baud/2) / baud);
+ else
+ config->wBaudRate = (__u16)((461538 + baud/2) / baud);
+
+ dbg("%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d",
+ __FUNCTION__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode);
+
+ cpu_to_be16s(&config->wBaudRate);
+ cpu_to_be16s(&config->wFlags);
+
+ status = ti_command_out_sync(tport->tp_tdev, TI_SET_CONFIG,
+ (__u8)(TI_UART1_PORT + port_number), 0, (__u8 *)config,
+ sizeof(*config));
+ if (status)
+ dev_err(&port->dev, "%s - cannot set config on port %d, %d\n", __FUNCTION__, port_number, status);
+
+ /* SET_CONFIG asserts RTS and DTR, reset them correctly */
+ mcr = tport->tp_shadow_mcr;
+ /* if baud rate is B0, clear RTS and DTR */
+ if ((cflag & CBAUD) == B0)
+ mcr &= ~(TI_MCR_DTR | TI_MCR_RTS);
+ status = ti_set_mcr(tport, mcr);
+ if (status)
+ dev_err(&port->dev, "%s - cannot set modem control on port %d, %d\n", __FUNCTION__, port_number, status);
+
+ kfree(config);
+}
+
+
+static int ti_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ unsigned int result;
+ unsigned int msr;
+ unsigned int mcr;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+
+ msr = tport->tp_msr;
+ mcr = tport->tp_shadow_mcr;
+
+ result = ((mcr & TI_MCR_DTR) ? TIOCM_DTR : 0)
+ | ((mcr & TI_MCR_RTS) ? TIOCM_RTS : 0)
+ | ((mcr & TI_MCR_LOOP) ? TIOCM_LOOP : 0)
+ | ((msr & TI_MSR_CTS) ? TIOCM_CTS : 0)
+ | ((msr & TI_MSR_CD) ? TIOCM_CAR : 0)
+ | ((msr & TI_MSR_RI) ? TIOCM_RI : 0)
+ | ((msr & TI_MSR_DSR) ? TIOCM_DSR : 0);
+
+ dbg("%s - 0x%04X", __FUNCTION__, result);
+
+ return result;
+}
+
+
+static int ti_tiocmset(struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ unsigned int mcr;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (tport == NULL)
+ return -ENODEV;
+
+ mcr = tport->tp_shadow_mcr;
+
+ if (set & TIOCM_RTS)
+ mcr |= TI_MCR_RTS;
+ if (set & TIOCM_DTR)
+ mcr |= TI_MCR_DTR;
+ if (set & TIOCM_LOOP)
+ mcr |= TI_MCR_LOOP;
+
+ if (clear & TIOCM_RTS)
+ mcr &= ~TI_MCR_RTS;
+ if (clear & TIOCM_DTR)
+ mcr &= ~TI_MCR_DTR;
+ if (clear & TIOCM_LOOP)
+ mcr &= ~TI_MCR_LOOP;
+
+ return ti_set_mcr(tport, mcr);
+}
+
+
+static void ti_break(struct usb_serial_port *port, int break_state)
+{
+ struct ti_port *tport = usb_get_serial_port_data(port);
+ int status;
+
+ dbg("%s - state = %d", __FUNCTION__, break_state);
+
+ if (tport == NULL)
+ return;
+
+ ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0);
+
+ status = ti_write_byte(tport->tp_tdev,
+ tport->tp_uart_base_addr + TI_UART_OFFSET_LCR,
+ TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0);
+
+ if (status)
+ dbg("%s - error setting break, %d", __FUNCTION__, status);
+}
+
+
+static void ti_interrupt_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct ti_device *tdev = (struct ti_device *)urb->context;
+ struct usb_serial_port *port;
+ struct usb_serial *serial = tdev->td_serial;
+ struct ti_port *tport;
+ struct device *dev = &urb->dev->dev;
+ unsigned char *data = urb->transfer_buffer;
+ int length = urb->actual_length;
+ int port_number;
+ int function;
+ int status;
+ __u8 msr;
+
+ dbg("%s", __FUNCTION__);
+
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+ tdev->td_urb_error = 1;
+ return;
+ default:
+ dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status);
+ tdev->td_urb_error = 1;
+ goto exit;
+ }
+
+ if (length != 2) {
+ dbg("%s - bad packet size, %d", __FUNCTION__, length);
+ goto exit;
+ }
+
+ if (data[0] == TI_CODE_HARDWARE_ERROR) {
+ dev_err(dev, "%s - hardware error, %d\n", __FUNCTION__, data[1]);
+ goto exit;
+ }
+
+ port_number = TI_GET_PORT_FROM_CODE(data[0]);
+ function = TI_GET_FUNC_FROM_CODE(data[0]);
+
+ dbg("%s - port_number %d, function %d, data 0x%02X", __FUNCTION__, port_number, function, data[1]);
+
+ if (port_number >= serial->num_ports) {
+ dev_err(dev, "%s - bad port number, %d\n", __FUNCTION__, port_number);
+ goto exit;
+ }
+
+ port = serial->port[port_number];
+
+ tport = usb_get_serial_port_data(port);
+ if (!tport)
+ goto exit;
+
+ switch (function) {
+ case TI_CODE_DATA_ERROR:
+ dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", __FUNCTION__, port_number, data[1]);
+ break;
+
+ case TI_CODE_MODEM_STATUS:
+ msr = data[1];
+ dbg("%s - port %d, msr 0x%02X", __FUNCTION__, port_number, msr);
+ ti_handle_new_msr(tport, msr);
+ break;
+
+ default:
+ dev_err(dev, "%s - unknown interrupt code, 0x%02X\n", __FUNCTION__, data[1]);
+ break;
+ }
+
+exit:
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status)
+ dev_err(dev, "%s - resubmit interrupt urb failed, %d\n", __FUNCTION__, status);
+}
+
+
+static void ti_bulk_in_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct ti_port *tport = (struct ti_port *)urb->context;
+ struct usb_serial_port *port = tport->tp_port;
+ struct device *dev = &urb->dev->dev;
+ int status = 0;
+
+ dbg("%s", __FUNCTION__);
+
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+ tport->tp_tdev->td_urb_error = 1;
+ wake_up_interruptible(&tport->tp_write_wait);
+ return;
+ default:
+ dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status );
+ tport->tp_tdev->td_urb_error = 1;
+ wake_up_interruptible(&tport->tp_write_wait);
+ }
+
+ if (urb->status == -EPIPE)
+ goto exit;
+
+ if (urb->status) {
+ dev_err(dev, "%s - stopping read!\n", __FUNCTION__);
+ return;
+ }
+
+ if (port->tty && urb->actual_length) {
+ usb_serial_debug_data(debug, dev, __FUNCTION__,
+ urb->actual_length, urb->transfer_buffer);
+
+ if (!tport->tp_is_open)
+ dbg("%s - port closed, dropping data", __FUNCTION__);
+ else
+ ti_recv(&urb->dev->dev, port->tty, urb->transfer_buffer,
+ urb->actual_length);
+
+ spin_lock(&tport->tp_lock);
+ tport->tp_icount.rx += urb->actual_length;
+ spin_unlock(&tport->tp_lock);
+ }
+
+exit:
+ /* continue to read unless stopping */
+ spin_lock(&tport->tp_lock);
+ if (tport->tp_read_urb_state == TI_READ_URB_RUNNING) {
+ urb->dev = port->serial->dev;
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ } else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING) {
+ tport->tp_read_urb_state = TI_READ_URB_STOPPED;
+ }
+ spin_unlock(&tport->tp_lock);
+ if (status)
+ dev_err(dev, "%s - resubmit read urb failed, %d\n", __FUNCTION__, status);
+}
+
+
+static void ti_bulk_out_callback(struct urb *urb, struct pt_regs *regs)
+{
+ struct ti_port *tport = (struct ti_port *)urb->context;
+ struct usb_serial_port *port = tport->tp_port;
+ struct device *dev = &urb->dev->dev;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ tport->tp_write_urb_in_use = 0;
+
+ switch (urb->status) {
+ case 0:
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status);
+ tport->tp_tdev->td_urb_error = 1;
+ wake_up_interruptible(&tport->tp_write_wait);
+ return;
+ default:
+ dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status);
+ tport->tp_tdev->td_urb_error = 1;
+ wake_up_interruptible(&tport->tp_write_wait);
+ }
+
+ /* send any buffered data */
+ ti_send(tport);
+}
+
+
+static void ti_recv(struct device *dev, struct tty_struct *tty,
+ unsigned char *data, int length)
+{
+ int cnt;
+
+ do {
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
+ dev_err(dev, "%s - dropping data, %d bytes lost\n", __FUNCTION__, length);
+ return;
+ }
+ }
+ cnt = min(length, TTY_FLIPBUF_SIZE - tty->flip.count);
+ memcpy(tty->flip.char_buf_ptr, data, cnt);
+ memset(tty->flip.flag_buf_ptr, 0, cnt);
+ tty->flip.char_buf_ptr += cnt;
+ tty->flip.flag_buf_ptr += cnt;
+ tty->flip.count += cnt;
+ data += cnt;
+ length -= cnt;
+ } while (length > 0);
+
+ tty_flip_buffer_push(tty);
+}
+
+
+static void ti_send(struct ti_port *tport)
+{
+ int count, result;
+ struct usb_serial_port *port = tport->tp_port;
+ struct tty_struct *tty = port->tty;
+ unsigned long flags;
+
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+
+ if (tport->tp_write_urb_in_use) {
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+ return;
+ }
+
+ count = ti_buf_get(tport->tp_write_buf,
+ port->write_urb->transfer_buffer,
+ port->bulk_out_size);
+
+ if (count == 0) {
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+ return;
+ }
+
+ tport->tp_write_urb_in_use = 1;
+
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);
+
+ usb_fill_bulk_urb(port->write_urb, port->serial->dev,
+ usb_sndbulkpipe(port->serial->dev,
+ port->bulk_out_endpointAddress),
+ port->write_urb->transfer_buffer, count,
+ ti_bulk_out_callback, tport);
+
+ result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (result) {
+ dev_err(&port->dev, "%s - submit write urb failed, %d\n", __FUNCTION__, result);
+ tport->tp_write_urb_in_use = 0;
+ /* TODO: reschedule ti_send */
+ } else {
+ spin_lock_irqsave(&tport->tp_lock, flags);
+ tport->tp_icount.tx += count;
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+ }
+
+ /* more room in the buffer for new writes, wakeup */
+ if (tty)
+ tty_wakeup(tty);
+ wake_up_interruptible(&tport->tp_write_wait);
+}
+
+
+static int ti_set_mcr(struct ti_port *tport, unsigned int mcr)
+{
+ int status;
+
+ status = ti_write_byte(tport->tp_tdev,
+ tport->tp_uart_base_addr + TI_UART_OFFSET_MCR,
+ TI_MCR_RTS | TI_MCR_DTR | TI_MCR_LOOP, mcr);
+
+ if (!status)
+ tport->tp_shadow_mcr = mcr;
+
+ return status;
+}
+
+
+static int ti_get_lsr(struct ti_port *tport)
+{
+ int size,status;
+ struct ti_device *tdev = tport->tp_tdev;
+ struct usb_serial_port *port = tport->tp_port;
+ int port_number = port->number - port->serial->minor;
+ struct ti_port_status *data;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ size = sizeof(struct ti_port_status);
+ data = kmalloc(size, GFP_KERNEL);
+ if (!data) {
+ dev_err(&port->dev, "%s - out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ status = ti_command_in_sync(tdev, TI_GET_PORT_STATUS,
+ (__u8)(TI_UART1_PORT+port_number), 0, (__u8 *)data, size);
+ if (status) {
+ dev_err(&port->dev, "%s - get port status command failed, %d\n", __FUNCTION__, status);
+ goto free_data;
+ }
+
+ dbg("%s - lsr 0x%02X", __FUNCTION__, data->bLSR);
+
+ tport->tp_lsr = data->bLSR;
+
+free_data:
+ kfree(data);
+ return status;
+}
+
+
+static int ti_get_serial_info(struct ti_port *tport,
+ struct serial_struct __user *ret_arg)
+{
+ struct usb_serial_port *port = tport->tp_port;
+ struct serial_struct ret_serial;
+
+ if (!ret_arg)
+ return -EFAULT;
+
+ memset(&ret_serial, 0, sizeof(ret_serial));
+
+ ret_serial.type = PORT_16550A;
+ ret_serial.line = port->serial->minor;
+ ret_serial.port = port->number - port->serial->minor;
+ ret_serial.flags = tport->tp_flags;
+ ret_serial.xmit_fifo_size = TI_WRITE_BUF_SIZE;
+ ret_serial.baud_base = tport->tp_tdev->td_is_3410 ? 921600 : 460800;
+ ret_serial.closing_wait = tport->tp_closing_wait;
+
+ if (copy_to_user(ret_arg, &ret_serial, sizeof(*ret_arg)))
+ return -EFAULT;
+
+ return 0;
+}
+
+
+static int ti_set_serial_info(struct ti_port *tport,
+ struct serial_struct __user *new_arg)
+{
+ struct usb_serial_port *port = tport->tp_port;
+ struct serial_struct new_serial;
+
+ if (copy_from_user(&new_serial, new_arg, sizeof(new_serial)))
+ return -EFAULT;
+
+ tport->tp_flags = new_serial.flags & TI_SET_SERIAL_FLAGS;
+ if (port->tty)
+ port->tty->low_latency =
+ (tport->tp_flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+ tport->tp_closing_wait = new_serial.closing_wait;
+
+ return 0;
+}
+
+
+static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
+{
+ struct async_icount *icount;
+ struct tty_struct *tty;
+ unsigned long flags;
+
+ dbg("%s - msr 0x%02X", __FUNCTION__, msr);
+
+ if (msr & TI_MSR_DELTA_MASK) {
+ spin_lock_irqsave(&tport->tp_lock, flags);
+ icount = &tport->tp_icount;
+ if (msr & TI_MSR_DELTA_CTS)
+ icount->cts++;
+ if (msr & TI_MSR_DELTA_DSR)
+ icount->dsr++;
+ if (msr & TI_MSR_DELTA_CD)
+ icount->dcd++;
+ if (msr & TI_MSR_DELTA_RI)
+ icount->rng++;
+ wake_up_interruptible(&tport->tp_msr_wait);
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+ }
+
+ tport->tp_msr = msr & TI_MSR_MASK;
+
+ /* handle CTS flow control */
+ tty = tport->tp_port->tty;
+ if (tty && C_CRTSCTS(tty)) {
+ if (msr & TI_MSR_CTS) {
+ tty->hw_stopped = 0;
+ tty_wakeup(tty);
+ } else {
+ tty->hw_stopped = 1;
+ }
+ }
+}
+
+
+static void ti_drain(struct ti_port *tport, unsigned long timeout, int flush)
+{
+ struct ti_device *tdev = tport->tp_tdev;
+ struct usb_serial_port *port = tport->tp_port;
+ wait_queue_t wait;
+ unsigned long flags;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+
+ /* wait for data to drain from the buffer */
+ tdev->td_urb_error = 0;
+ init_waitqueue_entry(&wait, current);
+ add_wait_queue(&tport->tp_write_wait, &wait);
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (ti_buf_data_avail(tport->tp_write_buf) == 0
+ || timeout == 0 || signal_pending(current)
+ || tdev->td_urb_error
+ || !usb_get_intfdata(port->serial->interface)) /* disconnect */
+ break;
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+ timeout = schedule_timeout(timeout);
+ spin_lock_irqsave(&tport->tp_lock, flags);
+ }
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&tport->tp_write_wait, &wait);
+
+ /* flush any remaining data in the buffer */
+ if (flush)
+ ti_buf_clear(tport->tp_write_buf);
+
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ /* wait for data to drain from the device */
+ /* wait for empty tx register, plus 20 ms */
+ timeout += jiffies;
+ tport->tp_lsr &= ~TI_LSR_TX_EMPTY;
+ while ((long)(jiffies - timeout) < 0 && !signal_pending(current)
+ && !(tport->tp_lsr&TI_LSR_TX_EMPTY) && !tdev->td_urb_error
+ && usb_get_intfdata(port->serial->interface)) { /* not disconnected */
+ if (ti_get_lsr(tport))
+ break;
+ msleep_interruptible(20);
+ }
+}
+
+
+static void ti_stop_read(struct ti_port *tport, struct tty_struct *tty)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+
+ if (tport->tp_read_urb_state == TI_READ_URB_RUNNING)
+ tport->tp_read_urb_state = TI_READ_URB_STOPPING;
+
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+}
+
+
+static int ti_restart_read(struct ti_port *tport, struct tty_struct *tty)
+{
+ struct urb *urb;
+ int status = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tport->tp_lock, flags);
+
+ if (tport->tp_read_urb_state == TI_READ_URB_STOPPED) {
+ urb = tport->tp_port->read_urb;
+ urb->complete = ti_bulk_in_callback;
+ urb->context = tport;
+ urb->dev = tport->tp_port->serial->dev;
+ status = usb_submit_urb(urb, GFP_KERNEL);
+ }
+ tport->tp_read_urb_state = TI_READ_URB_RUNNING;
+
+ spin_unlock_irqrestore(&tport->tp_lock, flags);
+
+ return status;
+}
+
+
+static int ti_command_out_sync(struct ti_device *tdev, __u8 command,
+ __u16 moduleid, __u16 value, __u8 *data, int size)
+{
+ int status;
+
+ status = usb_control_msg(tdev->td_serial->dev,
+ usb_sndctrlpipe(tdev->td_serial->dev, 0), command,
+ (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
+ value, moduleid, data, size, HZ);
+
+ if (status == size)
+ status = 0;
+
+ if (status > 0)
+ status = -ECOMM;
+
+ return status;
+}
+
+
+static int ti_command_in_sync(struct ti_device *tdev, __u8 command,
+ __u16 moduleid, __u16 value, __u8 *data, int size)
+{
+ int status;
+
+ status = usb_control_msg(tdev->td_serial->dev,
+ usb_rcvctrlpipe(tdev->td_serial->dev, 0), command,
+ (USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN),
+ value, moduleid, data, size, HZ);
+
+ if (status == size)
+ status = 0;
+
+ if (status > 0)
+ status = -ECOMM;
+
+ return status;
+}
+
+
+static int ti_write_byte(struct ti_device *tdev, unsigned long addr,
+ __u8 mask, __u8 byte)
+{
+ int status;
+ unsigned int size;
+ struct ti_write_data_bytes *data;
+ struct device *dev = &tdev->td_serial->dev->dev;
+
+ dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", __FUNCTION__, addr, mask, byte);
+
+ size = sizeof(struct ti_write_data_bytes) + 2;
+ data = kmalloc(size, GFP_KERNEL);
+ if (!data) {
+ dev_err(dev, "%s - out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ data->bAddrType = TI_RW_DATA_ADDR_XDATA;
+ data->bDataType = TI_RW_DATA_BYTE;
+ data->bDataCounter = 1;
+ data->wBaseAddrHi = cpu_to_be16(addr>>16);
+ data->wBaseAddrLo = cpu_to_be16(addr);
+ data->bData[0] = mask;
+ data->bData[1] = byte;
+
+ status = ti_command_out_sync(tdev, TI_WRITE_DATA, TI_RAM_PORT, 0,
+ (__u8 *)data, size);
+
+ if (status < 0)
+ dev_err(dev, "%s - failed, %d\n", __FUNCTION__, status);
+
+ kfree(data);
+
+ return status;
+}
+
+
+static int ti_download_firmware(struct ti_device *tdev,
+ unsigned char *firmware, unsigned int firmware_size)
+{
+ int status = 0;
+ int buffer_size;
+ int pos;
+ int len;
+ int done;
+ __u8 cs = 0;
+ __u8 *buffer;
+ struct usb_device *dev = tdev->td_serial->dev;
+ struct ti_firmware_header *header;
+ unsigned int pipe = usb_sndbulkpipe(dev,
+ tdev->td_serial->port[0]->bulk_out_endpointAddress);
+
+
+ buffer_size = TI_FIRMWARE_BUF_SIZE + sizeof(struct ti_firmware_header);
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer) {
+ dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ memcpy(buffer, firmware, firmware_size);
+ memset(buffer+firmware_size, 0xff, buffer_size-firmware_size);
+
+ for(pos = sizeof(struct ti_firmware_header); pos < buffer_size; pos++)
+ cs = (__u8)(cs + buffer[pos]);
+
+ header = (struct ti_firmware_header *)buffer;
+ header->wLength = cpu_to_le16((__u16)(buffer_size - sizeof(struct ti_firmware_header)));
+ header->bCheckSum = cs;
+
+ dbg("%s - downloading firmware", __FUNCTION__);
+ for (pos = 0; pos < buffer_size; pos += done) {
+ len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
+ status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, HZ);
+ if (status)
+ break;
+ }
+
+ kfree(buffer);
+
+ if (status) {
+ dev_err(&dev->dev, "%s - error downloading firmware, %d\n", __FUNCTION__, status);
+ return status;
+ }
+
+ dbg("%s - download successful", __FUNCTION__);
+
+ return 0;
+}
+
+
+/* Circular Buffer Functions */
+
+/*
+ * ti_buf_alloc
+ *
+ * Allocate a circular buffer and all associated memory.
+ */
+
+static struct circ_buf *ti_buf_alloc(void)
+{
+ struct circ_buf *cb;
+
+ cb = (struct circ_buf *)kmalloc(sizeof(struct circ_buf), GFP_KERNEL);
+ if (cb == NULL)
+ return NULL;
+
+ cb->buf = kmalloc(TI_WRITE_BUF_SIZE, GFP_KERNEL);
+ if (cb->buf == NULL) {
+ kfree(cb);
+ return NULL;
+ }
+
+ ti_buf_clear(cb);
+
+ return cb;
+}
+
+
+/*
+ * ti_buf_free
+ *
+ * Free the buffer and all associated memory.
+ */
+
+static void ti_buf_free(struct circ_buf *cb)
+{
+ kfree(cb->buf);
+ kfree(cb);
+}
+
+
+/*
+ * ti_buf_clear
+ *
+ * Clear out all data in the circular buffer.
+ */
+
+static void ti_buf_clear(struct circ_buf *cb)
+{
+ cb->head = cb->tail = 0;
+}
+
+
+/*
+ * ti_buf_data_avail
+ *
+ * Return the number of bytes of data available in the circular
+ * buffer.
+ */
+
+static int ti_buf_data_avail(struct circ_buf *cb)
+{
+ return CIRC_CNT(cb->head,cb->tail,TI_WRITE_BUF_SIZE);
+}
+
+
+/*
+ * ti_buf_space_avail
+ *
+ * Return the number of bytes of space available in the circular
+ * buffer.
+ */
+
+static int ti_buf_space_avail(struct circ_buf *cb)
+{
+ return CIRC_SPACE(cb->head,cb->tail,TI_WRITE_BUF_SIZE);
+}
+
+
+/*
+ * ti_buf_put
+ *
+ * Copy data data from a user buffer and put it into the circular buffer.
+ * Restrict to the amount of space available.
+ *
+ * Return the number of bytes copied.
+ */
+
+static int ti_buf_put(struct circ_buf *cb, const char *buf, int count)
+{
+ int c, ret = 0;
+
+ while (1) {
+ c = CIRC_SPACE_TO_END(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
+ if (count < c)
+ c = count;
+ if (c <= 0)
+ break;
+ memcpy(cb->buf + cb->head, buf, c);
+ cb->head = (cb->head + c) & (TI_WRITE_BUF_SIZE-1);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+
+ return ret;
+}
+
+
+/*
+ * ti_buf_get
+ *
+ * Get data from the circular buffer and copy to the given buffer.
+ * Restrict to the amount of data available.
+ *
+ * Return the number of bytes copied.
+ */
+
+static int ti_buf_get(struct circ_buf *cb, char *buf, int count)
+{
+ int c, ret = 0;
+
+ while (1) {
+ c = CIRC_CNT_TO_END(cb->head, cb->tail, TI_WRITE_BUF_SIZE);
+ if (count < c)
+ c = count;
+ if (c <= 0)
+ break;
+ memcpy(buf, cb->buf + cb->tail, c);
+ cb->tail = (cb->tail + c) & (TI_WRITE_BUF_SIZE-1);
+ buf += c;
+ count -= c;
+ ret += c;
+ }
+
+ return ret;
+}
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
new file mode 100644
index 00000000000000..02c1aeb9e1b8e5
--- /dev/null
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -0,0 +1,224 @@
+/* vi: ts=8 sw=8
+ *
+ * TI 3410/5052 USB Serial Driver Header
+ *
+ * Copyright (C) 2004 Texas Instruments
+ *
+ * This driver is based on the Linux io_ti driver, which is
+ * Copyright (C) 2000-2002 Inside Out Networks
+ * Copyright (C) 2001-2002 Greg Kroah-Hartman
+ *
+ * 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.
+ *
+ * For questions or problems with this driver, contact Texas Instruments
+ * technical support, or Al Borchers <alborchers@steinerpoint.com>, or
+ * Peter Berger <pberger@brimson.com>.
+ */
+
+#ifndef _TI_3410_5052_H_
+#define _TI_3410_5052_H_
+
+/* Configuration ids */
+#define TI_BOOT_CONFIG 1
+#define TI_ACTIVE_CONFIG 2
+
+/* Vendor and product ids */
+#define TI_VENDOR_ID 0x0451
+#define TI_3410_PRODUCT_ID 0x3410
+#define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */
+#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
+#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
+#define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */
+
+/* Commands */
+#define TI_GET_VERSION 0x01
+#define TI_GET_PORT_STATUS 0x02
+#define TI_GET_PORT_DEV_INFO 0x03
+#define TI_GET_CONFIG 0x04
+#define TI_SET_CONFIG 0x05
+#define TI_OPEN_PORT 0x06
+#define TI_CLOSE_PORT 0x07
+#define TI_START_PORT 0x08
+#define TI_STOP_PORT 0x09
+#define TI_TEST_PORT 0x0A
+#define TI_PURGE_PORT 0x0B
+#define TI_RESET_EXT_DEVICE 0x0C
+#define TI_WRITE_DATA 0x80
+#define TI_READ_DATA 0x81
+#define TI_REQ_TYPE_CLASS 0x82
+
+/* Module identifiers */
+#define TI_I2C_PORT 0x01
+#define TI_IEEE1284_PORT 0x02
+#define TI_UART1_PORT 0x03
+#define TI_UART2_PORT 0x04
+#define TI_RAM_PORT 0x05
+
+/* Modem status */
+#define TI_MSR_DELTA_CTS 0x01
+#define TI_MSR_DELTA_DSR 0x02
+#define TI_MSR_DELTA_RI 0x04
+#define TI_MSR_DELTA_CD 0x08
+#define TI_MSR_CTS 0x10
+#define TI_MSR_DSR 0x20
+#define TI_MSR_RI 0x40
+#define TI_MSR_CD 0x80
+#define TI_MSR_DELTA_MASK 0x0F
+#define TI_MSR_MASK 0xF0
+
+/* Line status */
+#define TI_LSR_OVERRUN_ERROR 0x01
+#define TI_LSR_PARITY_ERROR 0x02
+#define TI_LSR_FRAMING_ERROR 0x04
+#define TI_LSR_BREAK 0x08
+#define TI_LSR_ERROR 0x0F
+#define TI_LSR_RX_FULL 0x10
+#define TI_LSR_TX_EMPTY 0x20
+
+/* Line control */
+#define TI_LCR_BREAK 0x40
+
+/* Modem control */
+#define TI_MCR_LOOP 0x04
+#define TI_MCR_DTR 0x10
+#define TI_MCR_RTS 0x20
+
+/* Mask settings */
+#define TI_UART_ENABLE_RTS_IN 0x0001
+#define TI_UART_DISABLE_RTS 0x0002
+#define TI_UART_ENABLE_PARITY_CHECKING 0x0008
+#define TI_UART_ENABLE_DSR_OUT 0x0010
+#define TI_UART_ENABLE_CTS_OUT 0x0020
+#define TI_UART_ENABLE_X_OUT 0x0040
+#define TI_UART_ENABLE_XA_OUT 0x0080
+#define TI_UART_ENABLE_X_IN 0x0100
+#define TI_UART_ENABLE_DTR_IN 0x0800
+#define TI_UART_DISABLE_DTR 0x1000
+#define TI_UART_ENABLE_MS_INTS 0x2000
+#define TI_UART_ENABLE_AUTO_START_DMA 0x4000
+
+/* Parity */
+#define TI_UART_NO_PARITY 0x00
+#define TI_UART_ODD_PARITY 0x01
+#define TI_UART_EVEN_PARITY 0x02
+#define TI_UART_MARK_PARITY 0x03
+#define TI_UART_SPACE_PARITY 0x04
+
+/* Stop bits */
+#define TI_UART_1_STOP_BITS 0x00
+#define TI_UART_1_5_STOP_BITS 0x01
+#define TI_UART_2_STOP_BITS 0x02
+
+/* Bits per character */
+#define TI_UART_5_DATA_BITS 0x00
+#define TI_UART_6_DATA_BITS 0x01
+#define TI_UART_7_DATA_BITS 0x02
+#define TI_UART_8_DATA_BITS 0x03
+
+/* 232/485 modes */
+#define TI_UART_232 0x00
+#define TI_UART_485_RECEIVER_DISABLED 0x01
+#define TI_UART_485_RECEIVER_ENABLED 0x02
+
+/* Pipe transfer mode and timeout */
+#define TI_PIPE_MODE_CONTINOUS 0x01
+#define TI_PIPE_MODE_MASK 0x03
+#define TI_PIPE_TIMEOUT_MASK 0x7C
+#define TI_PIPE_TIMEOUT_ENABLE 0x80
+
+/* Config struct */
+struct ti_uart_config {
+ __u16 wBaudRate;
+ __u16 wFlags;
+ __u8 bDataBits;
+ __u8 bParity;
+ __u8 bStopBits;
+ char cXon;
+ char cXoff;
+ __u8 bUartMode;
+} __attribute__((packed));
+
+/* Get port status */
+struct ti_port_status {
+ __u8 bCmdCode;
+ __u8 bModuleId;
+ __u8 bErrorCode;
+ __u8 bMSR;
+ __u8 bLSR;
+} __attribute__((packed));
+
+/* Purge modes */
+#define TI_PURGE_OUTPUT 0x00
+#define TI_PURGE_INPUT 0x80
+
+/* Read/Write data */
+#define TI_RW_DATA_ADDR_SFR 0x10
+#define TI_RW_DATA_ADDR_IDATA 0x20
+#define TI_RW_DATA_ADDR_XDATA 0x30
+#define TI_RW_DATA_ADDR_CODE 0x40
+#define TI_RW_DATA_ADDR_GPIO 0x50
+#define TI_RW_DATA_ADDR_I2C 0x60
+#define TI_RW_DATA_ADDR_FLASH 0x70
+#define TI_RW_DATA_ADDR_DSP 0x80
+
+#define TI_RW_DATA_UNSPECIFIED 0x00
+#define TI_RW_DATA_BYTE 0x01
+#define TI_RW_DATA_WORD 0x02
+#define TI_RW_DATA_DOUBLE_WORD 0x04
+
+struct ti_write_data_bytes {
+ __u8 bAddrType;
+ __u8 bDataType;
+ __u8 bDataCounter;
+ __be16 wBaseAddrHi;
+ __be16 wBaseAddrLo;
+ __u8 bData[0];
+} __attribute__((packed));
+
+struct ti_read_data_request {
+ __u8 bAddrType;
+ __u8 bDataType;
+ __u8 bDataCounter;
+ __be16 wBaseAddrHi;
+ __be16 wBaseAddrLo;
+} __attribute__((packed));
+
+struct ti_read_data_bytes {
+ __u8 bCmdCode;
+ __u8 bModuleId;
+ __u8 bErrorCode;
+ __u8 bData[0];
+} __attribute__((packed));
+
+/* Interrupt struct */
+struct ti_interrupt {
+ __u8 bICode;
+ __u8 bIInfo;
+} __attribute__((packed));
+
+/* Interrupt codes */
+#define TI_GET_PORT_FROM_CODE(c) (((c) >> 4) - 3)
+#define TI_GET_FUNC_FROM_CODE(c) ((c) & 0x0f)
+#define TI_CODE_HARDWARE_ERROR 0xFF
+#define TI_CODE_DATA_ERROR 0x03
+#define TI_CODE_MODEM_STATUS 0x04
+
+/* Download firmware max packet size */
+#define TI_DOWNLOAD_MAX_PACKET_SIZE 64
+
+/* Firmware image header */
+struct ti_firmware_header {
+ __le16 wLength;
+ __u8 bCheckSum;
+} __attribute__((packed));
+
+/* UART addresses */
+#define TI_UART1_BASE_ADDR 0xFFA0 /* UART 1 base address */
+#define TI_UART2_BASE_ADDR 0xFFB0 /* UART 2 base address */
+#define TI_UART_OFFSET_LCR 0x0002 /* UART MCR register offset */
+#define TI_UART_OFFSET_MCR 0x0004 /* UART MCR register offset */
+
+#endif /* _TI_3410_5052_H_ */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index e6c344bdbe97b0..2836dfed6be124 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -721,7 +721,9 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
if (serial->type->owner)
length += sprintf (page+length, " module:%s", module_name(serial->type->owner));
length += sprintf (page+length, " name:\"%s\"", serial->type->name);
- length += sprintf (page+length, " vendor:%04x product:%04x", serial->vendor, serial->product);
+ length += sprintf (page+length, " vendor:%04x product:%04x",
+ le16_to_cpu(serial->dev->descriptor.idVendor),
+ le16_to_cpu(serial->dev->descriptor.idProduct));
length += sprintf (page+length, " num_ports:%d", serial->num_ports);
length += sprintf (page+length, " port:%d", i - serial->minor + 1);
@@ -834,8 +836,6 @@ static struct usb_serial * create_serial (struct usb_device *dev,
serial->dev = usb_get_dev(dev);
serial->type = type;
serial->interface = interface;
- serial->vendor = dev->descriptor.idVendor;
- serial->product = dev->descriptor.idProduct;
kref_init(&serial->kref);
return serial;
@@ -959,10 +959,10 @@ int usb_serial_probe(struct usb_interface *interface,
#if defined(CONFIG_USB_SERIAL_PL2303) || defined(CONFIG_USB_SERIAL_PL2303_MODULE)
/* BEGIN HORRIBLE HACK FOR PL2303 */
/* this is needed due to the looney way its endpoints are set up */
- if (((dev->descriptor.idVendor == PL2303_VENDOR_ID) &&
- (dev->descriptor.idProduct == PL2303_PRODUCT_ID)) ||
- ((dev->descriptor.idVendor == ATEN_VENDOR_ID) &&
- (dev->descriptor.idProduct == ATEN_PRODUCT_ID))) {
+ if (((le16_to_cpu(dev->descriptor.idVendor) == PL2303_VENDOR_ID) &&
+ (le16_to_cpu(dev->descriptor.idProduct) == PL2303_PRODUCT_ID)) ||
+ ((le16_to_cpu(dev->descriptor.idVendor) == ATEN_VENDOR_ID) &&
+ (le16_to_cpu(dev->descriptor.idProduct) == ATEN_PRODUCT_ID))) {
if (interface != dev->actconfig->interface[0]) {
/* check out the endpoints of the other interface*/
iface_desc = dev->actconfig->interface[0]->cur_altsetting;
@@ -1060,7 +1060,7 @@ int usb_serial_probe(struct usb_interface *interface,
dev_err(&interface->dev, "No free urbs available\n");
goto probe_error;
}
- buffer_size = endpoint->wMaxPacketSize;
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->bulk_in_size = buffer_size;
port->bulk_in_endpointAddress = endpoint->bEndpointAddress;
port->bulk_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
@@ -1084,7 +1084,7 @@ int usb_serial_probe(struct usb_interface *interface,
dev_err(&interface->dev, "No free urbs available\n");
goto probe_error;
}
- buffer_size = endpoint->wMaxPacketSize;
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->bulk_out_size = buffer_size;
port->bulk_out_endpointAddress = endpoint->bEndpointAddress;
port->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
@@ -1109,7 +1109,7 @@ int usb_serial_probe(struct usb_interface *interface,
dev_err(&interface->dev, "No free urbs available\n");
goto probe_error;
}
- buffer_size = endpoint->wMaxPacketSize;
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->interrupt_in_endpointAddress = endpoint->bEndpointAddress;
port->interrupt_in_buffer = kmalloc (buffer_size, GFP_KERNEL);
if (!port->interrupt_in_buffer) {
@@ -1136,7 +1136,7 @@ int usb_serial_probe(struct usb_interface *interface,
dev_err(&interface->dev, "No free urbs available\n");
goto probe_error;
}
- buffer_size = endpoint->wMaxPacketSize;
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
port->interrupt_out_size = buffer_size;
port->interrupt_out_endpointAddress = endpoint->bEndpointAddress;
port->interrupt_out_buffer = kmalloc (buffer_size, GFP_KERNEL);
@@ -1238,13 +1238,20 @@ probe_error:
void usb_serial_disconnect(struct usb_interface *interface)
{
+ int i;
struct usb_serial *serial = usb_get_intfdata (interface);
struct device *dev = &interface->dev;
+ struct usb_serial_port *port;
dbg ("%s", __FUNCTION__);
usb_set_intfdata (interface, NULL);
if (serial) {
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (port && port->tty)
+ tty_hangup(port->tty);
+ }
/* let the last holder of this object
* cause it to be cleaned up */
kref_put(&serial->kref, destroy_serial);
diff --git a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
index 1daf0752feedf6..d1f0c4057fa61e 100644
--- a/drivers/usb/serial/usb-serial.h
+++ b/drivers/usb/serial/usb-serial.h
@@ -148,8 +148,6 @@ static inline void usb_set_serial_port_data (struct usb_serial_port *port, void
* @num_interrupt_out: number of interrupt out endpoints we have
* @num_bulk_in: number of bulk in endpoints we have
* @num_bulk_out: number of bulk out endpoints we have
- * @vendor: vendor id of this device
- * @product: product id of this device
* @port: array of struct usb_serial_port structures for the different ports.
* @private: place to put any driver specific information that is needed. The
* usb-serial driver is required to manage this data, the usb-serial core
@@ -167,8 +165,6 @@ struct usb_serial {
char num_interrupt_out;
char num_bulk_in;
char num_bulk_out;
- __u16 vendor;
- __u16 product;
struct usb_serial_port * port[MAX_NUM_PORTS];
struct kref kref;
void * private;
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index d5b5cdd9ef2af1..6c0d51638824be 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -734,9 +734,7 @@ static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_i
if (retval == sizeof(*connection_info)) {
connection_info = (struct visor_connection_info *)transfer_buffer;
- le16_to_cpus(&connection_info->num_ports);
- num_ports = connection_info->num_ports;
-
+ num_ports = le16_to_cpu(connection_info->num_ports);
for (i = 0; i < num_ports; ++i) {
switch (connection_info->connections[i].port_function_id) {
case VISOR_FUNCTION_GENERIC:
@@ -926,8 +924,8 @@ static int treo_attach (struct usb_serial *serial)
/* Only do this endpoint hack for the Handspring devices with
* interrupt in endpoints, which for now are the Treo devices. */
- if (!((serial->dev->descriptor.idVendor == HANDSPRING_VENDOR_ID) ||
- (serial->dev->descriptor.idVendor == KYOCERA_VENDOR_ID)) ||
+ if (!((le16_to_cpu(serial->dev->descriptor.idVendor) == HANDSPRING_VENDOR_ID) ||
+ (le16_to_cpu(serial->dev->descriptor.idVendor) == KYOCERA_VENDOR_ID)) ||
(serial->num_interrupt_in == 0))
goto generic_startup;
diff --git a/drivers/usb/serial/visor.h b/drivers/usb/serial/visor.h
index 55185b39820be2..2effcd0f7a1977 100644
--- a/drivers/usb/serial/visor.h
+++ b/drivers/usb/serial/visor.h
@@ -89,7 +89,7 @@
* VISOR_GET_CONNECTION_INFORMATION returns data in the following format
****************************************************************************/
struct visor_connection_info {
- __u16 num_ports;
+ __le16 num_ports;
struct {
__u8 port_function_id;
__u8 port;
@@ -135,12 +135,12 @@ struct visor_connection_info {
struct palm_ext_connection_info {
__u8 num_ports;
__u8 endpoint_numbers_different;
- __u16 reserved1;
+ __le16 reserved1;
struct {
__u32 port_function_id;
__u8 port;
__u8 end_point_info;
- __u16 reserved;
+ __le16 reserved;
} connections[2];
};
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 64e185fcf994ac..714e8328c84120 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -118,7 +118,7 @@ static int slave_configure(struct scsi_device *sdev)
* works okay and that's what Windows does. But we'll be
* conservative; people can always use the sysfs interface to
* increase max_sectors. */
- if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS &&
+ if (le16_to_cpu(us->pusb_dev->descriptor.idVendor) == USB_VENDOR_ID_GENESYS &&
sdev->request_queue->max_sectors > 64)
blk_queue_max_sectors(sdev->request_queue, 64);
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 08d3a96bbf92eb..ddc1e3bcf845bd 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -954,6 +954,13 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
int result;
int fake_sense = 0;
unsigned int cswlen;
+ unsigned int cbwlen = US_BULK_CB_WRAP_LEN;
+
+ /* Take care of BULK32 devices; set extra byte to 0 */
+ if ( unlikely(us->flags & US_FL_BULK32)) {
+ cbwlen = 32;
+ us->iobuf[31] = 0;
+ }
/* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
@@ -976,7 +983,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
(bcb->Lun >> 4), (bcb->Lun & 0x0F),
bcb->Length);
result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe,
- bcb, US_BULK_CB_WRAP_LEN, NULL);
+ bcb, cbwlen, NULL);
US_DEBUGP("Bulk command transfer result=%d\n", result);
if (result != USB_STOR_XFER_GOOD)
return USB_STOR_TRANSPORT_ERROR;
@@ -985,9 +992,10 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
/* send/receive data payload, if there is any */
/* Genesys Logic interface chips need a 100us delay between the
- * command phase and the data phase */
- if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS)
- udelay(100);
+ * command phase and the data phase. Some devices need a little
+ * more than that, probably because of clock rate inaccuracies. */
+ if (le16_to_cpu(us->pusb_dev->descriptor.idVendor) == USB_VENDOR_ID_GENESYS)
+ udelay(110);
if (transfer_length) {
unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 7b03131fe9ea2b..bb76460ae4a220 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -249,6 +249,17 @@ UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200,
"CD-RW Device",
US_SC_8020, US_PR_CB, NULL, 0),
+/* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
+ * Device uses standards-violating 32-byte Bulk Command Block Wrappers and
+ * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
+ */
+
+UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100,
+ "Kobian Mercury",
+ "Binocam DCB-132",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_BULK32),
+
/* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */
UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133,
"Belkin",
@@ -310,14 +321,14 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
"Sony",
"DSC-S30/S70/S75/505V/F505/F707/F717/P8",
US_SC_SCSI, US_PR_DEVICE, NULL,
- US_FL_SINGLE_LUN | US_FL_MODE_XLATE ),
+ US_FL_SINGLE_LUN ),
/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500,
"Sony",
"DSC-T1",
US_SC_8070, US_PR_DEVICE, NULL,
- US_FL_SINGLE_LUN | US_FL_MODE_XLATE ),
+ US_FL_SINGLE_LUN ),
/* Reported by wim@geeks.nl */
@@ -346,14 +357,14 @@ UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310,
"Sony",
"Handycam",
US_SC_SCSI, US_PR_DEVICE, NULL,
- US_FL_SINGLE_LUN | US_FL_MODE_XLATE),
+ US_FL_SINGLE_LUN ),
/* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */
UNUSUAL_DEV( 0x054c, 0x002e, 0x0500, 0x0500,
"Sony",
"Handycam HC-85",
US_SC_UFI, US_PR_DEVICE, NULL,
- US_FL_SINGLE_LUN | US_FL_MODE_XLATE),
+ US_FL_SINGLE_LUN ),
UNUSUAL_DEV( 0x054c, 0x0032, 0x0000, 0x9999,
"Sony",
@@ -483,7 +494,7 @@ UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
"Lexar",
"Jumpshot USB CF Reader",
US_SC_SCSI, US_PR_JUMPSHOT, NULL,
- US_FL_NEED_OVERRIDE | US_FL_MODE_XLATE ),
+ US_FL_NEED_OVERRIDE ),
#endif
/* Reported by Blake Matheny <bmatheny@purdue.edu> */
@@ -499,7 +510,7 @@ UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999,
"Vivitar",
"Vivicam 35Xx",
US_SC_SCSI, US_PR_BULK, NULL,
- US_FL_FIX_INQUIRY | US_FL_MODE_XLATE),
+ US_FL_FIX_INQUIRY ),
UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100,
"TEAC",
@@ -521,6 +532,20 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
+/* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */
+UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0001,
+ "Prolific Technology Inc.",
+ "ATAPI-6 Bridge Controller",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
+/* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */
+UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0001,
+ "Prolific Technology Inc.",
+ "ATAPI-6 Bridge Controller",
+ US_SC_DEVICE, US_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
/* Submitted by Benny Sjostrand <benny@hostmobility.com> */
UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
"Minolta",
@@ -609,48 +634,48 @@ UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015,
"Datafab",
"MDCFE-B USB CF Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE ),
-
- /*
- * The following Datafab-based devices may or may not work
- * using the current driver...the 0xffff is arbitrary since I
- * don't know what device versions exist for these guys.
- *
- * The 0xa003 and 0xa004 devices in particular I'm curious about.
- * I'm told they exist but so far nobody has come forward to say that
- * they work with this driver. Given the success we've had getting
- * other Datafab-based cards operational with this driver, I've decided
- * to leave these two devices in the list.
- */
+ 0 ),
+
+/*
+ * The following Datafab-based devices may or may not work
+ * using the current driver...the 0xffff is arbitrary since I
+ * don't know what device versions exist for these guys.
+ *
+ * The 0xa003 and 0xa004 devices in particular I'm curious about.
+ * I'm told they exist but so far nobody has come forward to say that
+ * they work with this driver. Given the success we've had getting
+ * other Datafab-based cards operational with this driver, I've decided
+ * to leave these two devices in the list.
+ */
UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff,
"SIIG/Datafab",
"SIIG/Datafab Memory Stick+CF Reader/Writer",
US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE ),
+ 0 ),
UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff,
"Datafab/Unknown",
"Datafab-based Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE ),
+ 0 ),
UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff,
"Datafab/Unknown",
"Datafab-based Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE ),
+ 0 ),
UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff,
"PNY/Datafab",
"PNY/Datafab CF+SM Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE ),
+ 0 ),
UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff,
"Simple Tech/Datafab",
"Simple Tech/Datafab CF+SM Reader",
US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE ),
+ 0 ),
#endif
#ifdef CONFIG_USB_STORAGE_SDDR55
@@ -668,7 +693,7 @@ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff,
"Datafab Systems, Inc.",
"USB to CF + SM Combo (LC1)",
US_SC_SCSI, US_PR_DATAFAB, NULL,
- US_FL_MODE_XLATE ),
+ 0 ),
#endif
#ifdef CONFIG_USB_STORAGE_SDDR55
/* SM part - aeb <Andries.Brouwer@cwi.nl> */
@@ -715,14 +740,18 @@ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY),
-/* Aiptek PocketCAM 3Mega
- * Nicolas DUPEUX <nicolas@dupeux.net>
+/* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
+ * Flag will support Bulk devices which use a standards-violating 32-byte
+ * Command Block Wrapper. Here, the "DC2MEGA" cameras (several brands) with
+ * Grandtech GT892x chip, which request "Proprietary SCSI Bulk" support.
*/
-UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999,
- "AIPTEK",
- "PocketCAM 3Mega",
+
+UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110,
+ "Grandtech",
+ "DC2MEGA",
US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_MODE_XLATE ),
+ US_FL_BULK32),
+
/* Entry needed for flags. Moreover, all devices with this ID use
* bulk-only transport, but _some_ falsely report Control/Bulk instead.
@@ -733,14 +762,14 @@ UNUSUAL_DEV( 0x090a, 0x1001, 0x0100, 0x0100,
"Trumpion",
"t33520 USB Flash Card Controller",
US_SC_DEVICE, US_PR_BULK, NULL,
- US_FL_NEED_OVERRIDE | US_FL_MODE_XLATE),
+ US_FL_NEED_OVERRIDE ),
/* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
"Trumpion",
"MP3 player",
US_SC_RBC, US_PR_BULK, NULL,
- US_FL_MODE_XLATE),
+ 0 ),
/* aeb */
UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
@@ -749,12 +778,6 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY ),
-UNUSUAL_DEV( 0x097a, 0x0001, 0x0000, 0x0001,
- "Minds@Work",
- "Digital Wallet",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_MODE_XLATE ),
-
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
@@ -859,17 +882,6 @@ UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
0 ),
-/* Reported by Dan Pilone <pilone@slac.com>
- * The device needs the flags only.
- * Also reported by Brian Hall <brihall@pcisys.net>, again for flags.
- * I also suspect this device may have a broken serial number.
- */
-UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x9999,
- "CCYU TECHNOLOGY",
- "EasyDisk Portable Device",
- US_SC_DEVICE, US_PR_DEVICE, NULL,
- US_FL_MODE_XLATE ),
-
/* Reported by Kotrla Vitezslav <kotrla@ceb.cz> */
UNUSUAL_DEV( 0x1370, 0x6828, 0x0110, 0x0110,
"SWISSBIT",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index cfa0ebfcfae457..0a8c42a0a8bf24 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -263,16 +263,17 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data,
available from the device."). */
memset(data+8,0,28);
} else {
+ u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice);
memcpy(data+8, us->unusual_dev->vendorName,
strlen(us->unusual_dev->vendorName) > 8 ? 8 :
strlen(us->unusual_dev->vendorName));
memcpy(data+16, us->unusual_dev->productName,
strlen(us->unusual_dev->productName) > 16 ? 16 :
strlen(us->unusual_dev->productName));
- data[32] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>12) & 0x0F);
- data[33] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>8) & 0x0F);
- data[34] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice>>4) & 0x0F);
- data[35] = 0x30 + ((us->pusb_dev->descriptor.bcdDevice) & 0x0F);
+ data[32] = 0x30 + ((bcdDevice>>12) & 0x0F);
+ data[33] = 0x30 + ((bcdDevice>>8) & 0x0F);
+ data[34] = 0x30 + ((bcdDevice>>4) & 0x0F);
+ data[35] = 0x30 + ((bcdDevice) & 0x0F);
}
usb_stor_set_xfer_buf(data, data_len, us->srb);
@@ -436,9 +437,9 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
us->pusb_intf = intf;
us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
US_DEBUGP("Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
- us->pusb_dev->descriptor.idVendor,
- us->pusb_dev->descriptor.idProduct,
- us->pusb_dev->descriptor.bcdDevice);
+ le16_to_cpu(us->pusb_dev->descriptor.idVendor),
+ le16_to_cpu(us->pusb_dev->descriptor.idProduct),
+ le16_to_cpu(us->pusb_dev->descriptor.bcdDevice));
US_DEBUGP("Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
intf->cur_altsetting->desc.bInterfaceSubClass,
intf->cur_altsetting->desc.bInterfaceProtocol);
@@ -507,8 +508,9 @@ static void get_device_info(struct us_data *us, int id_index)
" has %s in unusual_devs.h\n"
" Please send a copy of this message to "
"<linux-usb-devel@lists.sourceforge.net>\n",
- ddesc->idVendor, ddesc->idProduct,
- ddesc->bcdDevice,
+ le16_to_cpu(ddesc->idVendor),
+ le16_to_cpu(ddesc->idProduct),
+ le16_to_cpu(ddesc->bcdDevice),
idesc->bInterfaceSubClass,
idesc->bInterfaceProtocol,
msgs[msg]);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 45feb362a03761..aaaf7ed5455c46 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -74,6 +74,7 @@ struct us_unusual_dev {
#define US_FL_FIX_INQUIRY 0x00000040 /* INQUIRY response needs faking */
#define US_FL_FIX_CAPACITY 0x00000080 /* READ CAPACITY response too big */
#define US_FL_IGNORE_RESIDUE 0x00000100 /* reported residue is wrong */
+#define US_FL_BULK32 0x00000200 /* Uses 32-byte CBW length */
/* Dynamic flag definitions: used in set_bit() etc. */
#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
index d3a3fd9b109df7..71abda209aa2b6 100644
--- a/drivers/usb/usb-skeleton.c
+++ b/drivers/usb/usb-skeleton.c
@@ -260,7 +260,7 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk in endpoint */
- buffer_size = endpoint->wMaxPacketSize;
+ buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
dev->bulk_in_size = buffer_size;
dev->bulk_in_endpointAddr = endpoint->bEndpointAddress;
dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL);
diff --git a/drivers/w1/dscore.c b/drivers/w1/dscore.c
index 887d689e8c4fe4..284f378bb1b198 100644
--- a/drivers/w1/dscore.c
+++ b/drivers/w1/dscore.c
@@ -676,7 +676,7 @@ int ds_probe(struct usb_interface *intf, const struct usb_device_id *udev_id)
ds_dev->ep[i+1] = endpoint->bEndpointAddress;
printk("%d: addr=%x, size=%d, dir=%s, type=%x\n",
- i, endpoint->bEndpointAddress, endpoint->wMaxPacketSize,
+ i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize),
(endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT",
endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
}