diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-12 19:46:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-12 19:46:58 -0400 |
commit | 9374430a52dfae5c013b88f7f030c04a6774d410 (patch) | |
tree | ce1ee8eee4e79fbb9486e810278d1092afc74a44 /drivers | |
parent | 66f49739fe1591197364f2dad1b67b975e8f5e85 (diff) | |
parent | 13f9966b3ba5b45f47f2ea0eb0a90afceedfbb1f (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (149 commits)
USB: ohci-pnx4008: Remove unnecessary cast of return value of kzalloc
USB: additions to the quirk list
usb-storage: implement autosuspend
USB: cdc-acm: add new device id to option driver
USB: goku_udc trivial cleanups
USB: usb gadget stack can now -DDEBUG with Kconfig
usb gadget stack: remove usb_ep_*_buffer(), part 2
usb gadget stack: remove usb_ep_*_buffer(), part 1
USB: pxa2xx_udc -- cleanups, mostly removing dma hooks
USB: pxa2xx_udc: use generic gpio layer
USB: quirk for samsung printer
USB: usb/dma doc updates
USB: drivers/usb/storage/unusual_devs.h whitespace cleanup
USB: remove Makefile reference to obsolete OHCI_AT91
USB: io_*: remove bogus termios no change checks
USB: mos7720: remove bogus no termios change check
USB: visor and whiteheat: remove bogus termios change checks
USB: pl2303: remove bogus checks and fix speed support to use tty_get_baud_rate()
USB: mos7840.c: turn this into a serial driver
USB: make the usb_device numa_node get assigned from controller
...
Diffstat (limited to 'drivers')
134 files changed, 14567 insertions, 4431 deletions
diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 746a118a9b52..18c8b6c0db20 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c | |||
@@ -1547,10 +1547,8 @@ static void ub_reset_enter(struct ub_dev *sc, int try) | |||
1547 | #endif | 1547 | #endif |
1548 | 1548 | ||
1549 | #if 0 /* We let them stop themselves. */ | 1549 | #if 0 /* We let them stop themselves. */ |
1550 | struct list_head *p; | ||
1551 | struct ub_lun *lun; | 1550 | struct ub_lun *lun; |
1552 | list_for_each(p, &sc->luns) { | 1551 | list_for_each_entry(lun, &sc->luns, link) { |
1553 | lun = list_entry(p, struct ub_lun, link); | ||
1554 | blk_stop_queue(lun->disk->queue); | 1552 | blk_stop_queue(lun->disk->queue); |
1555 | } | 1553 | } |
1556 | #endif | 1554 | #endif |
@@ -1562,7 +1560,6 @@ static void ub_reset_task(struct work_struct *work) | |||
1562 | { | 1560 | { |
1563 | struct ub_dev *sc = container_of(work, struct ub_dev, reset_work); | 1561 | struct ub_dev *sc = container_of(work, struct ub_dev, reset_work); |
1564 | unsigned long flags; | 1562 | unsigned long flags; |
1565 | struct list_head *p; | ||
1566 | struct ub_lun *lun; | 1563 | struct ub_lun *lun; |
1567 | int lkr, rc; | 1564 | int lkr, rc; |
1568 | 1565 | ||
@@ -1608,8 +1605,7 @@ static void ub_reset_task(struct work_struct *work) | |||
1608 | spin_lock_irqsave(sc->lock, flags); | 1605 | spin_lock_irqsave(sc->lock, flags); |
1609 | sc->reset = 0; | 1606 | sc->reset = 0; |
1610 | tasklet_schedule(&sc->tasklet); | 1607 | tasklet_schedule(&sc->tasklet); |
1611 | list_for_each(p, &sc->luns) { | 1608 | list_for_each_entry(lun, &sc->luns, link) { |
1612 | lun = list_entry(p, struct ub_lun, link); | ||
1613 | blk_start_queue(lun->disk->queue); | 1609 | blk_start_queue(lun->disk->queue); |
1614 | } | 1610 | } |
1615 | wake_up(&sc->reset_wait); | 1611 | wake_up(&sc->reset_wait); |
@@ -2348,7 +2344,6 @@ err_alloc: | |||
2348 | static void ub_disconnect(struct usb_interface *intf) | 2344 | static void ub_disconnect(struct usb_interface *intf) |
2349 | { | 2345 | { |
2350 | struct ub_dev *sc = usb_get_intfdata(intf); | 2346 | struct ub_dev *sc = usb_get_intfdata(intf); |
2351 | struct list_head *p; | ||
2352 | struct ub_lun *lun; | 2347 | struct ub_lun *lun; |
2353 | unsigned long flags; | 2348 | unsigned long flags; |
2354 | 2349 | ||
@@ -2403,8 +2398,7 @@ static void ub_disconnect(struct usb_interface *intf) | |||
2403 | /* | 2398 | /* |
2404 | * Unregister the upper layer. | 2399 | * Unregister the upper layer. |
2405 | */ | 2400 | */ |
2406 | list_for_each (p, &sc->luns) { | 2401 | list_for_each_entry(lun, &sc->luns, link) { |
2407 | lun = list_entry(p, struct ub_lun, link); | ||
2408 | del_gendisk(lun->disk); | 2402 | del_gendisk(lun->disk); |
2409 | /* | 2403 | /* |
2410 | * I wish I could do: | 2404 | * I wish I could do: |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 3afa4a5035b7..b2baeaeba9be 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -1009,20 +1009,22 @@ static int hid_resume(struct usb_interface *intf) | |||
1009 | } | 1009 | } |
1010 | 1010 | ||
1011 | /* Treat USB reset pretty much the same as suspend/resume */ | 1011 | /* Treat USB reset pretty much the same as suspend/resume */ |
1012 | static void hid_pre_reset(struct usb_interface *intf) | 1012 | static int hid_pre_reset(struct usb_interface *intf) |
1013 | { | 1013 | { |
1014 | /* FIXME: What if the interface is already suspended? */ | 1014 | /* FIXME: What if the interface is already suspended? */ |
1015 | hid_suspend(intf, PMSG_ON); | 1015 | hid_suspend(intf, PMSG_ON); |
1016 | return 0; | ||
1016 | } | 1017 | } |
1017 | 1018 | ||
1018 | static void hid_post_reset(struct usb_interface *intf) | 1019 | /* Same routine used for post_reset and reset_resume */ |
1020 | static int hid_post_reset(struct usb_interface *intf) | ||
1019 | { | 1021 | { |
1020 | struct usb_device *dev = interface_to_usbdev (intf); | 1022 | struct usb_device *dev = interface_to_usbdev (intf); |
1021 | 1023 | ||
1022 | hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); | 1024 | hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0); |
1023 | /* FIXME: Any more reinitialization needed? */ | 1025 | /* FIXME: Any more reinitialization needed? */ |
1024 | 1026 | ||
1025 | hid_resume(intf); | 1027 | return hid_resume(intf); |
1026 | } | 1028 | } |
1027 | 1029 | ||
1028 | static struct usb_device_id hid_usb_ids [] = { | 1030 | static struct usb_device_id hid_usb_ids [] = { |
@@ -1039,6 +1041,7 @@ static struct usb_driver hid_driver = { | |||
1039 | .disconnect = hid_disconnect, | 1041 | .disconnect = hid_disconnect, |
1040 | .suspend = hid_suspend, | 1042 | .suspend = hid_suspend, |
1041 | .resume = hid_resume, | 1043 | .resume = hid_resume, |
1044 | .reset_resume = hid_post_reset, | ||
1042 | .pre_reset = hid_pre_reset, | 1045 | .pre_reset = hid_pre_reset, |
1043 | .post_reset = hid_post_reset, | 1046 | .post_reset = hid_post_reset, |
1044 | .id_table = hid_usb_ids, | 1047 | .id_table = hid_usb_ids, |
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 15499b7e33f4..172a6065f5a2 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -2,9 +2,12 @@ | |||
2 | # USB device configuration | 2 | # USB device configuration |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "USB support" | 5 | menuconfig USB_SUPPORT |
6 | bool "USB support" | ||
6 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
7 | 8 | ||
9 | if USB_SUPPORT | ||
10 | |||
8 | # Host-side USB depends on having a host controller | 11 | # Host-side USB depends on having a host controller |
9 | # NOTE: dummy_hcd is always an option, but it's ignored here ... | 12 | # NOTE: dummy_hcd is always an option, but it's ignored here ... |
10 | # NOTE: SL-811 option should be board-specific ... | 13 | # NOTE: SL-811 option should be board-specific ... |
@@ -12,6 +15,7 @@ config USB_ARCH_HAS_HCD | |||
12 | boolean | 15 | boolean |
13 | default y if USB_ARCH_HAS_OHCI | 16 | default y if USB_ARCH_HAS_OHCI |
14 | default y if USB_ARCH_HAS_EHCI | 17 | default y if USB_ARCH_HAS_EHCI |
18 | default y if PCMCIA # sl811_cs | ||
15 | default y if ARM # SL-811 | 19 | default y if ARM # SL-811 |
16 | default PCI | 20 | default PCI |
17 | 21 | ||
@@ -130,5 +134,4 @@ source "drivers/usb/atm/Kconfig" | |||
130 | 134 | ||
131 | source "drivers/usb/gadget/Kconfig" | 135 | source "drivers/usb/gadget/Kconfig" |
132 | 136 | ||
133 | endmenu | 137 | endif # USB_SUPPORT |
134 | |||
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 72464b586990..befff5f9d58c 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -15,7 +15,7 @@ obj-$(CONFIG_USB_OHCI_HCD) += host/ | |||
15 | obj-$(CONFIG_USB_UHCI_HCD) += host/ | 15 | obj-$(CONFIG_USB_UHCI_HCD) += host/ |
16 | obj-$(CONFIG_USB_SL811_HCD) += host/ | 16 | obj-$(CONFIG_USB_SL811_HCD) += host/ |
17 | obj-$(CONFIG_USB_U132_HCD) += host/ | 17 | obj-$(CONFIG_USB_U132_HCD) += host/ |
18 | obj-$(CONFIG_USB_OHCI_AT91) += host/ | 18 | obj-$(CONFIG_USB_R8A66597_HCD) += host/ |
19 | 19 | ||
20 | obj-$(CONFIG_USB_ACM) += class/ | 20 | obj-$(CONFIG_USB_ACM) += class/ |
21 | obj-$(CONFIG_USB_PRINTER) += class/ | 21 | obj-$(CONFIG_USB_PRINTER) += class/ |
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 8bcf7fe1dd80..1bc884051e0f 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c | |||
@@ -171,7 +171,7 @@ struct cxacru_data { | |||
171 | struct delayed_work poll_work; | 171 | struct delayed_work poll_work; |
172 | u32 card_info[CXINF_MAX]; | 172 | u32 card_info[CXINF_MAX]; |
173 | struct mutex poll_state_serialize; | 173 | struct mutex poll_state_serialize; |
174 | int poll_state; | 174 | enum cxacru_poll_state poll_state; |
175 | 175 | ||
176 | /* contol handles */ | 176 | /* contol handles */ |
177 | struct mutex cm_serialize; | 177 | struct mutex cm_serialize; |
@@ -226,58 +226,48 @@ static ssize_t cxacru_sysfs_showattr_s8(s8 value, char *buf) | |||
226 | 226 | ||
227 | static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf) | 227 | static ssize_t cxacru_sysfs_showattr_dB(s16 value, char *buf) |
228 | { | 228 | { |
229 | if (unlikely(value < 0)) { | 229 | return snprintf(buf, PAGE_SIZE, "%d.%02u\n", |
230 | return snprintf(buf, PAGE_SIZE, "%d.%02u\n", | 230 | value / 100, abs(value) % 100); |
231 | value / 100, -value % 100); | ||
232 | } else { | ||
233 | return snprintf(buf, PAGE_SIZE, "%d.%02u\n", | ||
234 | value / 100, value % 100); | ||
235 | } | ||
236 | } | 231 | } |
237 | 232 | ||
238 | static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf) | 233 | static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf) |
239 | { | 234 | { |
240 | switch (value) { | 235 | static char *str[] = { "no", "yes" }; |
241 | case 0: return snprintf(buf, PAGE_SIZE, "no\n"); | 236 | if (unlikely(value >= ARRAY_SIZE(str))) |
242 | case 1: return snprintf(buf, PAGE_SIZE, "yes\n"); | 237 | return snprintf(buf, PAGE_SIZE, "%u\n", value); |
243 | default: return 0; | 238 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); |
244 | } | ||
245 | } | 239 | } |
246 | 240 | ||
247 | static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf) | 241 | static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf) |
248 | { | 242 | { |
249 | switch (value) { | 243 | static char *str[] = { NULL, "not connected", "connected", "lost" }; |
250 | case 1: return snprintf(buf, PAGE_SIZE, "not connected\n"); | 244 | if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL)) |
251 | case 2: return snprintf(buf, PAGE_SIZE, "connected\n"); | 245 | return snprintf(buf, PAGE_SIZE, "%u\n", value); |
252 | case 3: return snprintf(buf, PAGE_SIZE, "lost\n"); | 246 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); |
253 | default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value); | ||
254 | } | ||
255 | } | 247 | } |
256 | 248 | ||
257 | static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf) | 249 | static ssize_t cxacru_sysfs_showattr_LINE(u32 value, char *buf) |
258 | { | 250 | { |
259 | switch (value) { | 251 | static char *str[] = { "down", "attempting to activate", |
260 | case 0: return snprintf(buf, PAGE_SIZE, "down\n"); | 252 | "training", "channel analysis", "exchange", "up", |
261 | case 1: return snprintf(buf, PAGE_SIZE, "attempting to activate\n"); | 253 | "waiting", "initialising" |
262 | case 2: return snprintf(buf, PAGE_SIZE, "training\n"); | 254 | }; |
263 | case 3: return snprintf(buf, PAGE_SIZE, "channel analysis\n"); | 255 | if (unlikely(value >= ARRAY_SIZE(str))) |
264 | case 4: return snprintf(buf, PAGE_SIZE, "exchange\n"); | 256 | return snprintf(buf, PAGE_SIZE, "%u\n", value); |
265 | case 5: return snprintf(buf, PAGE_SIZE, "up\n"); | 257 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); |
266 | case 6: return snprintf(buf, PAGE_SIZE, "waiting\n"); | ||
267 | case 7: return snprintf(buf, PAGE_SIZE, "initialising\n"); | ||
268 | default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value); | ||
269 | } | ||
270 | } | 258 | } |
271 | 259 | ||
272 | static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf) | 260 | static ssize_t cxacru_sysfs_showattr_MODU(u32 value, char *buf) |
273 | { | 261 | { |
274 | switch (value) { | 262 | static char *str[] = { |
275 | case 0: return 0; | 263 | NULL, |
276 | case 1: return snprintf(buf, PAGE_SIZE, "ANSI T1.413\n"); | 264 | "ANSI T1.413", |
277 | case 2: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.1 (G.DMT)\n"); | 265 | "ITU-T G.992.1 (G.DMT)", |
278 | case 3: return snprintf(buf, PAGE_SIZE, "ITU-T G.992.2 (G.LITE)\n"); | 266 | "ITU-T G.992.2 (G.LITE)" |
279 | default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value); | 267 | }; |
280 | } | 268 | if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL)) |
269 | return snprintf(buf, PAGE_SIZE, "%u\n", value); | ||
270 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); | ||
281 | } | 271 | } |
282 | 272 | ||
283 | /* | 273 | /* |
@@ -308,11 +298,10 @@ static ssize_t cxacru_sysfs_show_adsl_state(struct device *dev, | |||
308 | struct cxacru_data *instance = usbatm_instance->driver_data; | 298 | struct cxacru_data *instance = usbatm_instance->driver_data; |
309 | u32 value = instance->card_info[CXINF_LINE_STARTABLE]; | 299 | u32 value = instance->card_info[CXINF_LINE_STARTABLE]; |
310 | 300 | ||
311 | switch (value) { | 301 | static char *str[] = { "running", "stopped" }; |
312 | case 0: return snprintf(buf, PAGE_SIZE, "running\n"); | 302 | if (unlikely(value >= ARRAY_SIZE(str))) |
313 | case 1: return snprintf(buf, PAGE_SIZE, "stopped\n"); | 303 | return snprintf(buf, PAGE_SIZE, "%u\n", value); |
314 | default: return snprintf(buf, PAGE_SIZE, "unknown (%u)\n", value); | 304 | return snprintf(buf, PAGE_SIZE, "%s\n", str[value]); |
315 | } | ||
316 | } | 305 | } |
317 | 306 | ||
318 | static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev, | 307 | static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev, |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 0081c1d12687..cd51520c7e72 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -1157,6 +1157,9 @@ static struct usb_device_id acm_ids[] = { | |||
1157 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ | 1157 | { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ |
1158 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1158 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1159 | }, | 1159 | }, |
1160 | { USB_DEVICE(0x0e8d, 0x0003), /* FIREFLY, MediaTek Inc; andrey.arapov@gmail.com */ | ||
1161 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | ||
1162 | }, | ||
1160 | { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ | 1163 | { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ |
1161 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1164 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
1162 | }, | 1165 | }, |
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 6778f9af7943..9a1478972bf5 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * usblp.c Version 0.13 | 2 | * usblp.c |
3 | * | 3 | * |
4 | * Copyright (c) 1999 Michael Gee <michael@linuxspecific.com> | 4 | * Copyright (c) 1999 Michael Gee <michael@linuxspecific.com> |
5 | * Copyright (c) 1999 Pavel Machek <pavel@suse.cz> | 5 | * Copyright (c) 1999 Pavel Machek <pavel@suse.cz> |
@@ -61,11 +61,11 @@ | |||
61 | /* | 61 | /* |
62 | * Version Information | 62 | * Version Information |
63 | */ | 63 | */ |
64 | #define DRIVER_VERSION "v0.13" | ||
65 | #define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal" | 64 | #define DRIVER_AUTHOR "Michael Gee, Pavel Machek, Vojtech Pavlik, Randy Dunlap, Pete Zaitcev, David Paschal" |
66 | #define DRIVER_DESC "USB Printer Device Class driver" | 65 | #define DRIVER_DESC "USB Printer Device Class driver" |
67 | 66 | ||
68 | #define USBLP_BUF_SIZE 8192 | 67 | #define USBLP_BUF_SIZE 8192 |
68 | #define USBLP_BUF_SIZE_IN 1024 | ||
69 | #define USBLP_DEVICE_ID_SIZE 1024 | 69 | #define USBLP_DEVICE_ID_SIZE 1024 |
70 | 70 | ||
71 | /* ioctls: */ | 71 | /* ioctls: */ |
@@ -127,14 +127,22 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H | |||
127 | */ | 127 | */ |
128 | #define STATUS_BUF_SIZE 8 | 128 | #define STATUS_BUF_SIZE 8 |
129 | 129 | ||
130 | /* | ||
131 | * Locks down the locking order: | ||
132 | * ->wmut locks wstatus. | ||
133 | * ->mut locks the whole usblp, except [rw]complete, and thus, by indirection, | ||
134 | * [rw]status. We only touch status when we know the side idle. | ||
135 | * ->lock locks what interrupt accesses. | ||
136 | */ | ||
130 | struct usblp { | 137 | struct usblp { |
131 | struct usb_device *dev; /* USB device */ | 138 | struct usb_device *dev; /* USB device */ |
132 | struct mutex mut; /* locks this struct, especially "dev" */ | 139 | struct mutex wmut; |
133 | char *writebuf; /* write transfer_buffer */ | 140 | struct mutex mut; |
141 | spinlock_t lock; /* locks rcomplete, wcomplete */ | ||
134 | char *readbuf; /* read transfer_buffer */ | 142 | char *readbuf; /* read transfer_buffer */ |
135 | char *statusbuf; /* status transfer_buffer */ | 143 | char *statusbuf; /* status transfer_buffer */ |
136 | struct urb *readurb, *writeurb; /* The urbs */ | 144 | struct usb_anchor urbs; |
137 | wait_queue_head_t wait; /* Zzzzz ... */ | 145 | wait_queue_head_t rwait, wwait; |
138 | int readcount; /* Counter for reads */ | 146 | int readcount; /* Counter for reads */ |
139 | int ifnum; /* Interface number */ | 147 | int ifnum; /* Interface number */ |
140 | struct usb_interface *intf; /* The interface */ | 148 | struct usb_interface *intf; /* The interface */ |
@@ -147,8 +155,9 @@ struct usblp { | |||
147 | } protocol[USBLP_MAX_PROTOCOLS]; | 155 | } protocol[USBLP_MAX_PROTOCOLS]; |
148 | int current_protocol; | 156 | int current_protocol; |
149 | int minor; /* minor number of device */ | 157 | int minor; /* minor number of device */ |
150 | int wcomplete; /* writing is completed */ | 158 | int wcomplete, rcomplete; |
151 | int rcomplete; /* reading is completed */ | 159 | int wstatus; /* bytes written or error */ |
160 | int rstatus; /* bytes ready or error */ | ||
152 | unsigned int quirks; /* quirks flags */ | 161 | unsigned int quirks; /* quirks flags */ |
153 | unsigned char used; /* True if open */ | 162 | unsigned char used; /* True if open */ |
154 | unsigned char present; /* True if not disconnected */ | 163 | unsigned char present; /* True if not disconnected */ |
@@ -166,9 +175,6 @@ static void usblp_dump(struct usblp *usblp) { | |||
166 | dbg("dev=0x%p", usblp->dev); | 175 | dbg("dev=0x%p", usblp->dev); |
167 | dbg("present=%d", usblp->present); | 176 | dbg("present=%d", usblp->present); |
168 | dbg("readbuf=0x%p", usblp->readbuf); | 177 | dbg("readbuf=0x%p", usblp->readbuf); |
169 | dbg("writebuf=0x%p", usblp->writebuf); | ||
170 | dbg("readurb=0x%p", usblp->readurb); | ||
171 | dbg("writeurb=0x%p", usblp->writeurb); | ||
172 | dbg("readcount=%d", usblp->readcount); | 178 | dbg("readcount=%d", usblp->readcount); |
173 | dbg("ifnum=%d", usblp->ifnum); | 179 | dbg("ifnum=%d", usblp->ifnum); |
174 | for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) { | 180 | for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) { |
@@ -178,8 +184,8 @@ static void usblp_dump(struct usblp *usblp) { | |||
178 | } | 184 | } |
179 | dbg("current_protocol=%d", usblp->current_protocol); | 185 | dbg("current_protocol=%d", usblp->current_protocol); |
180 | dbg("minor=%d", usblp->minor); | 186 | dbg("minor=%d", usblp->minor); |
181 | dbg("wcomplete=%d", usblp->wcomplete); | 187 | dbg("wstatus=%d", usblp->wstatus); |
182 | dbg("rcomplete=%d", usblp->rcomplete); | 188 | dbg("rstatus=%d", usblp->rstatus); |
183 | dbg("quirks=%d", usblp->quirks); | 189 | dbg("quirks=%d", usblp->quirks); |
184 | dbg("used=%d", usblp->used); | 190 | dbg("used=%d", usblp->used); |
185 | dbg("bidir=%d", usblp->bidir); | 191 | dbg("bidir=%d", usblp->bidir); |
@@ -222,6 +228,11 @@ static const struct quirk_printer_struct quirk_printers[] = { | |||
222 | { 0, 0 } | 228 | { 0, 0 } |
223 | }; | 229 | }; |
224 | 230 | ||
231 | static int usblp_wwait(struct usblp *usblp, int nonblock); | ||
232 | static int usblp_wtest(struct usblp *usblp, int nonblock); | ||
233 | static int usblp_rwait_and_lock(struct usblp *usblp, int nonblock); | ||
234 | static int usblp_rtest(struct usblp *usblp, int nonblock); | ||
235 | static int usblp_submit_read(struct usblp *usblp); | ||
225 | static int usblp_select_alts(struct usblp *usblp); | 236 | static int usblp_select_alts(struct usblp *usblp); |
226 | static int usblp_set_protocol(struct usblp *usblp, int protocol); | 237 | static int usblp_set_protocol(struct usblp *usblp, int protocol); |
227 | static int usblp_cache_device_id_string(struct usblp *usblp); | 238 | static int usblp_cache_device_id_string(struct usblp *usblp); |
@@ -279,33 +290,47 @@ static void usblp_bulk_read(struct urb *urb) | |||
279 | { | 290 | { |
280 | struct usblp *usblp = urb->context; | 291 | struct usblp *usblp = urb->context; |
281 | 292 | ||
282 | if (unlikely(!usblp || !usblp->dev || !usblp->used)) | 293 | if (usblp->present && usblp->used) { |
283 | return; | 294 | if (urb->status) |
284 | 295 | printk(KERN_WARNING "usblp%d: " | |
285 | if (unlikely(!usblp->present)) | 296 | "nonzero read bulk status received: %d\n", |
286 | goto unplug; | 297 | usblp->minor, urb->status); |
287 | if (unlikely(urb->status)) | 298 | } |
288 | warn("usblp%d: nonzero read/write bulk status received: %d", | 299 | spin_lock(&usblp->lock); |
289 | usblp->minor, urb->status); | 300 | if (urb->status < 0) |
301 | usblp->rstatus = urb->status; | ||
302 | else | ||
303 | usblp->rstatus = urb->actual_length; | ||
290 | usblp->rcomplete = 1; | 304 | usblp->rcomplete = 1; |
291 | unplug: | 305 | wake_up(&usblp->rwait); |
292 | wake_up_interruptible(&usblp->wait); | 306 | spin_unlock(&usblp->lock); |
307 | |||
308 | usb_free_urb(urb); | ||
293 | } | 309 | } |
294 | 310 | ||
295 | static void usblp_bulk_write(struct urb *urb) | 311 | static void usblp_bulk_write(struct urb *urb) |
296 | { | 312 | { |
297 | struct usblp *usblp = urb->context; | 313 | struct usblp *usblp = urb->context; |
298 | 314 | ||
299 | if (unlikely(!usblp || !usblp->dev || !usblp->used)) | 315 | if (usblp->present && usblp->used) { |
300 | return; | 316 | if (urb->status) |
301 | if (unlikely(!usblp->present)) | 317 | printk(KERN_WARNING "usblp%d: " |
302 | goto unplug; | 318 | "nonzero write bulk status received: %d\n", |
303 | if (unlikely(urb->status)) | 319 | usblp->minor, urb->status); |
304 | warn("usblp%d: nonzero read/write bulk status received: %d", | 320 | } |
305 | usblp->minor, urb->status); | 321 | spin_lock(&usblp->lock); |
322 | if (urb->status < 0) | ||
323 | usblp->wstatus = urb->status; | ||
324 | else | ||
325 | usblp->wstatus = urb->actual_length; | ||
306 | usblp->wcomplete = 1; | 326 | usblp->wcomplete = 1; |
307 | unplug: | 327 | wake_up(&usblp->wwait); |
308 | wake_up_interruptible(&usblp->wait); | 328 | spin_unlock(&usblp->lock); |
329 | |||
330 | /* XXX Use usb_setup_bulk_urb when available. Talk to Marcel. */ | ||
331 | kfree(urb->transfer_buffer); | ||
332 | urb->transfer_buffer = NULL; /* Not refcounted, so to be safe... */ | ||
333 | usb_free_urb(urb); | ||
309 | } | 334 | } |
310 | 335 | ||
311 | /* | 336 | /* |
@@ -322,7 +347,8 @@ static int usblp_check_status(struct usblp *usblp, int err) | |||
322 | error = usblp_read_status (usblp, usblp->statusbuf); | 347 | error = usblp_read_status (usblp, usblp->statusbuf); |
323 | if (error < 0) { | 348 | if (error < 0) { |
324 | if (printk_ratelimit()) | 349 | if (printk_ratelimit()) |
325 | err("usblp%d: error %d reading printer status", | 350 | printk(KERN_ERR |
351 | "usblp%d: error %d reading printer status\n", | ||
326 | usblp->minor, error); | 352 | usblp->minor, error); |
327 | return 0; | 353 | return 0; |
328 | } | 354 | } |
@@ -336,8 +362,10 @@ static int usblp_check_status(struct usblp *usblp, int err) | |||
336 | if (~status & LP_PSELECD) | 362 | if (~status & LP_PSELECD) |
337 | newerr = 2; | 363 | newerr = 2; |
338 | 364 | ||
339 | if (newerr != err) | 365 | if (newerr != err) { |
340 | info("usblp%d: %s", usblp->minor, usblp_messages[newerr]); | 366 | printk(KERN_INFO "usblp%d: %s\n", |
367 | usblp->minor, usblp_messages[newerr]); | ||
368 | } | ||
341 | 369 | ||
342 | return newerr; | 370 | return newerr; |
343 | } | 371 | } |
@@ -345,12 +373,9 @@ static int usblp_check_status(struct usblp *usblp, int err) | |||
345 | static int handle_bidir (struct usblp *usblp) | 373 | static int handle_bidir (struct usblp *usblp) |
346 | { | 374 | { |
347 | if (usblp->bidir && usblp->used && !usblp->sleeping) { | 375 | if (usblp->bidir && usblp->used && !usblp->sleeping) { |
348 | usblp->readcount = 0; | 376 | if (usblp_submit_read(usblp) < 0) |
349 | usblp->readurb->dev = usblp->dev; | ||
350 | if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) | ||
351 | return -EIO; | 377 | return -EIO; |
352 | } | 378 | } |
353 | |||
354 | return 0; | 379 | return 0; |
355 | } | 380 | } |
356 | 381 | ||
@@ -403,11 +428,9 @@ static int usblp_open(struct inode *inode, struct file *file) | |||
403 | usblp->used = 1; | 428 | usblp->used = 1; |
404 | file->private_data = usblp; | 429 | file->private_data = usblp; |
405 | 430 | ||
406 | usblp->writeurb->transfer_buffer_length = 0; | ||
407 | usblp->wcomplete = 1; /* we begin writeable */ | 431 | usblp->wcomplete = 1; /* we begin writeable */ |
432 | usblp->wstatus = 0; | ||
408 | usblp->rcomplete = 0; | 433 | usblp->rcomplete = 0; |
409 | usblp->writeurb->status = 0; | ||
410 | usblp->readurb->status = 0; | ||
411 | 434 | ||
412 | if (handle_bidir(usblp) < 0) { | 435 | if (handle_bidir(usblp) < 0) { |
413 | usblp->used = 0; | 436 | usblp->used = 0; |
@@ -421,20 +444,17 @@ out: | |||
421 | 444 | ||
422 | static void usblp_cleanup (struct usblp *usblp) | 445 | static void usblp_cleanup (struct usblp *usblp) |
423 | { | 446 | { |
424 | info("usblp%d: removed", usblp->minor); | 447 | printk(KERN_INFO "usblp%d: removed\n", usblp->minor); |
425 | 448 | ||
449 | kfree(usblp->readbuf); | ||
426 | kfree (usblp->device_id_string); | 450 | kfree (usblp->device_id_string); |
427 | kfree (usblp->statusbuf); | 451 | kfree (usblp->statusbuf); |
428 | usb_free_urb(usblp->writeurb); | ||
429 | usb_free_urb(usblp->readurb); | ||
430 | kfree (usblp); | 452 | kfree (usblp); |
431 | } | 453 | } |
432 | 454 | ||
433 | static void usblp_unlink_urbs(struct usblp *usblp) | 455 | static void usblp_unlink_urbs(struct usblp *usblp) |
434 | { | 456 | { |
435 | usb_kill_urb(usblp->writeurb); | 457 | usb_kill_anchored_urbs(&usblp->urbs); |
436 | if (usblp->bidir) | ||
437 | usb_kill_urb(usblp->readurb); | ||
438 | } | 458 | } |
439 | 459 | ||
440 | static int usblp_release(struct inode *inode, struct file *file) | 460 | static int usblp_release(struct inode *inode, struct file *file) |
@@ -455,10 +475,18 @@ static int usblp_release(struct inode *inode, struct file *file) | |||
455 | /* No kernel lock - fine */ | 475 | /* No kernel lock - fine */ |
456 | static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait) | 476 | static unsigned int usblp_poll(struct file *file, struct poll_table_struct *wait) |
457 | { | 477 | { |
478 | int ret; | ||
479 | unsigned long flags; | ||
480 | |||
458 | struct usblp *usblp = file->private_data; | 481 | struct usblp *usblp = file->private_data; |
459 | poll_wait(file, &usblp->wait, wait); | 482 | /* Should we check file->f_mode & FMODE_WRITE before poll_wait()? */ |
460 | return ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN | POLLRDNORM) | 483 | poll_wait(file, &usblp->rwait, wait); |
484 | poll_wait(file, &usblp->wwait, wait); | ||
485 | spin_lock_irqsave(&usblp->lock, flags); | ||
486 | ret = ((!usblp->bidir || !usblp->rcomplete) ? 0 : POLLIN | POLLRDNORM) | ||
461 | | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM); | 487 | | (!usblp->wcomplete ? 0 : POLLOUT | POLLWRNORM); |
488 | spin_unlock_irqrestore(&usblp->lock, flags); | ||
489 | return ret; | ||
462 | } | 490 | } |
463 | 491 | ||
464 | static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 492 | static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
@@ -632,10 +660,11 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
632 | switch (cmd) { | 660 | switch (cmd) { |
633 | 661 | ||
634 | case LPGETSTATUS: | 662 | case LPGETSTATUS: |
635 | if (usblp_read_status(usblp, usblp->statusbuf)) { | 663 | if ((retval = usblp_read_status(usblp, usblp->statusbuf))) { |
636 | if (printk_ratelimit()) | 664 | if (printk_ratelimit()) |
637 | err("usblp%d: failed reading printer status", | 665 | printk(KERN_ERR "usblp%d:" |
638 | usblp->minor); | 666 | "failed reading printer status (%d)\n", |
667 | usblp->minor, retval); | ||
639 | retval = -EIO; | 668 | retval = -EIO; |
640 | goto done; | 669 | goto done; |
641 | } | 670 | } |
@@ -656,168 +685,303 @@ done: | |||
656 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 685 | static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
657 | { | 686 | { |
658 | struct usblp *usblp = file->private_data; | 687 | struct usblp *usblp = file->private_data; |
659 | int timeout, intr, rv, err = 0, transfer_length = 0; | 688 | char *writebuf; |
660 | size_t writecount = 0; | 689 | struct urb *writeurb; |
690 | int rv; | ||
691 | int transfer_length; | ||
692 | ssize_t writecount = 0; | ||
693 | |||
694 | if (mutex_lock_interruptible(&usblp->wmut)) { | ||
695 | rv = -EINTR; | ||
696 | goto raise_biglock; | ||
697 | } | ||
698 | if ((rv = usblp_wwait(usblp, !!(file->f_flags & O_NONBLOCK))) < 0) | ||
699 | goto raise_wait; | ||
661 | 700 | ||
662 | while (writecount < count) { | 701 | while (writecount < count) { |
663 | if (!usblp->wcomplete) { | 702 | /* |
664 | barrier(); | 703 | * Step 1: Submit next block. |
665 | if (file->f_flags & O_NONBLOCK) { | ||
666 | writecount += transfer_length; | ||
667 | return writecount ? writecount : -EAGAIN; | ||
668 | } | ||
669 | |||
670 | timeout = USBLP_WRITE_TIMEOUT; | ||
671 | |||
672 | rv = wait_event_interruptible_timeout(usblp->wait, usblp->wcomplete || !usblp->present , timeout); | ||
673 | if (rv < 0) | ||
674 | return writecount ? writecount : -EINTR; | ||
675 | } | ||
676 | intr = mutex_lock_interruptible (&usblp->mut); | ||
677 | if (intr) | ||
678 | return writecount ? writecount : -EINTR; | ||
679 | if (!usblp->present) { | ||
680 | mutex_unlock (&usblp->mut); | ||
681 | return -ENODEV; | ||
682 | } | ||
683 | |||
684 | if (usblp->sleeping) { | ||
685 | mutex_unlock (&usblp->mut); | ||
686 | return writecount ? writecount : -ENODEV; | ||
687 | } | ||
688 | |||
689 | if (usblp->writeurb->status != 0) { | ||
690 | if (usblp->quirks & USBLP_QUIRK_BIDIR) { | ||
691 | if (!usblp->wcomplete) | ||
692 | err("usblp%d: error %d writing to printer", | ||
693 | usblp->minor, usblp->writeurb->status); | ||
694 | err = usblp->writeurb->status; | ||
695 | } else | ||
696 | err = usblp_check_status(usblp, err); | ||
697 | mutex_unlock (&usblp->mut); | ||
698 | |||
699 | /* if the fault was due to disconnect, let khubd's | ||
700 | * call to usblp_disconnect() grab usblp->mut ... | ||
701 | */ | ||
702 | schedule (); | ||
703 | continue; | ||
704 | } | ||
705 | |||
706 | /* We must increment writecount here, and not at the | ||
707 | * end of the loop. Otherwise, the final loop iteration may | ||
708 | * be skipped, leading to incomplete printer output. | ||
709 | */ | 704 | */ |
710 | writecount += transfer_length; | 705 | if ((transfer_length = count - writecount) > USBLP_BUF_SIZE) |
711 | if (writecount == count) { | ||
712 | mutex_unlock(&usblp->mut); | ||
713 | break; | ||
714 | } | ||
715 | |||
716 | transfer_length=(count - writecount); | ||
717 | if (transfer_length > USBLP_BUF_SIZE) | ||
718 | transfer_length = USBLP_BUF_SIZE; | 706 | transfer_length = USBLP_BUF_SIZE; |
719 | 707 | ||
720 | usblp->writeurb->transfer_buffer_length = transfer_length; | 708 | rv = -ENOMEM; |
721 | 709 | if ((writebuf = kmalloc(USBLP_BUF_SIZE, GFP_KERNEL)) == NULL) | |
722 | if (copy_from_user(usblp->writeurb->transfer_buffer, | 710 | goto raise_buf; |
711 | if ((writeurb = usb_alloc_urb(0, GFP_KERNEL)) == NULL) | ||
712 | goto raise_urb; | ||
713 | usb_fill_bulk_urb(writeurb, usblp->dev, | ||
714 | usb_sndbulkpipe(usblp->dev, | ||
715 | usblp->protocol[usblp->current_protocol].epwrite->bEndpointAddress), | ||
716 | writebuf, transfer_length, usblp_bulk_write, usblp); | ||
717 | usb_anchor_urb(writeurb, &usblp->urbs); | ||
718 | |||
719 | if (copy_from_user(writebuf, | ||
723 | buffer + writecount, transfer_length)) { | 720 | buffer + writecount, transfer_length)) { |
724 | mutex_unlock(&usblp->mut); | 721 | rv = -EFAULT; |
725 | return writecount ? writecount : -EFAULT; | 722 | goto raise_badaddr; |
726 | } | 723 | } |
727 | 724 | ||
728 | usblp->writeurb->dev = usblp->dev; | 725 | spin_lock_irq(&usblp->lock); |
729 | usblp->wcomplete = 0; | 726 | usblp->wcomplete = 0; |
730 | err = usb_submit_urb(usblp->writeurb, GFP_KERNEL); | 727 | spin_unlock_irq(&usblp->lock); |
731 | if (err) { | 728 | if ((rv = usb_submit_urb(writeurb, GFP_KERNEL)) < 0) { |
729 | usblp->wstatus = 0; | ||
730 | spin_lock_irq(&usblp->lock); | ||
732 | usblp->wcomplete = 1; | 731 | usblp->wcomplete = 1; |
733 | if (err != -ENOMEM) | 732 | wake_up(&usblp->wwait); |
734 | count = -EIO; | 733 | spin_unlock_irq(&usblp->lock); |
735 | else | 734 | if (rv != -ENOMEM) |
736 | count = writecount ? writecount : -ENOMEM; | 735 | rv = -EIO; |
737 | mutex_unlock (&usblp->mut); | 736 | goto raise_submit; |
738 | break; | 737 | } |
738 | |||
739 | /* | ||
740 | * Step 2: Wait for transfer to end, collect results. | ||
741 | */ | ||
742 | rv = usblp_wwait(usblp, !!(file->f_flags&O_NONBLOCK)); | ||
743 | if (rv < 0) { | ||
744 | /* | ||
745 | * If interrupted, we simply leave the URB to dangle, | ||
746 | * so the ->release will call usb_kill_urb(). | ||
747 | */ | ||
748 | goto collect_error; | ||
739 | } | 749 | } |
740 | mutex_unlock (&usblp->mut); | 750 | |
751 | if (usblp->wstatus < 0) { | ||
752 | usblp_check_status(usblp, 0); | ||
753 | rv = -EIO; | ||
754 | goto collect_error; | ||
755 | } | ||
756 | /* | ||
757 | * This is critical: it must be our URB, not other writer's. | ||
758 | * The wmut exists mainly to cover us here. | ||
759 | */ | ||
760 | writecount += usblp->wstatus; | ||
741 | } | 761 | } |
742 | 762 | ||
743 | return count; | 763 | mutex_unlock(&usblp->wmut); |
764 | return writecount; | ||
765 | |||
766 | raise_submit: | ||
767 | raise_badaddr: | ||
768 | usb_unanchor_urb(writeurb); | ||
769 | usb_free_urb(writeurb); | ||
770 | raise_urb: | ||
771 | kfree(writebuf); | ||
772 | raise_buf: | ||
773 | raise_wait: | ||
774 | collect_error: /* Out of raise sequence */ | ||
775 | mutex_unlock(&usblp->wmut); | ||
776 | raise_biglock: | ||
777 | return writecount ? writecount : rv; | ||
744 | } | 778 | } |
745 | 779 | ||
746 | static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) | 780 | /* |
781 | * Notice that we fail to restart in a few cases: on EFAULT, on restart | ||
782 | * error, etc. This is the historical behaviour. In all such cases we return | ||
783 | * EIO, and applications loop in order to get the new read going. | ||
784 | */ | ||
785 | static ssize_t usblp_read(struct file *file, char __user *buffer, size_t len, loff_t *ppos) | ||
747 | { | 786 | { |
748 | struct usblp *usblp = file->private_data; | 787 | struct usblp *usblp = file->private_data; |
749 | int rv, intr; | 788 | ssize_t count; |
789 | ssize_t avail; | ||
790 | int rv; | ||
750 | 791 | ||
751 | if (!usblp->bidir) | 792 | if (!usblp->bidir) |
752 | return -EINVAL; | 793 | return -EINVAL; |
753 | 794 | ||
754 | intr = mutex_lock_interruptible (&usblp->mut); | 795 | rv = usblp_rwait_and_lock(usblp, !!(file->f_flags & O_NONBLOCK)); |
755 | if (intr) | 796 | if (rv < 0) |
756 | return -EINTR; | 797 | return rv; |
757 | if (!usblp->present) { | 798 | |
758 | count = -ENODEV; | 799 | if ((avail = usblp->rstatus) < 0) { |
800 | printk(KERN_ERR "usblp%d: error %d reading from printer\n", | ||
801 | usblp->minor, (int)avail); | ||
802 | usblp_submit_read(usblp); | ||
803 | count = -EIO; | ||
759 | goto done; | 804 | goto done; |
760 | } | 805 | } |
761 | 806 | ||
762 | if (!usblp->rcomplete) { | 807 | count = len < avail - usblp->readcount ? len : avail - usblp->readcount; |
763 | barrier(); | 808 | if (count != 0 && |
809 | copy_to_user(buffer, usblp->readbuf + usblp->readcount, count)) { | ||
810 | count = -EFAULT; | ||
811 | goto done; | ||
812 | } | ||
764 | 813 | ||
765 | if (file->f_flags & O_NONBLOCK) { | 814 | if ((usblp->readcount += count) == avail) { |
766 | count = -EAGAIN; | 815 | if (usblp_submit_read(usblp) < 0) { |
767 | goto done; | 816 | /* We don't want to leak USB return codes into errno. */ |
768 | } | 817 | if (count == 0) |
769 | mutex_unlock(&usblp->mut); | 818 | count = -EIO; |
770 | rv = wait_event_interruptible(usblp->wait, usblp->rcomplete || !usblp->present); | ||
771 | mutex_lock(&usblp->mut); | ||
772 | if (rv < 0) { | ||
773 | count = -EINTR; | ||
774 | goto done; | 819 | goto done; |
775 | } | 820 | } |
776 | } | 821 | } |
777 | 822 | ||
778 | if (!usblp->present) { | 823 | done: |
779 | count = -ENODEV; | 824 | mutex_unlock (&usblp->mut); |
780 | goto done; | 825 | return count; |
826 | } | ||
827 | |||
828 | /* | ||
829 | * Wait for the write path to come idle. | ||
830 | * This is called under the ->wmut, so the idle path stays idle. | ||
831 | * | ||
832 | * Our write path has a peculiar property: it does not buffer like a tty, | ||
833 | * but waits for the write to succeed. This allows our ->release to bug out | ||
834 | * without waiting for writes to drain. But it obviously does not work | ||
835 | * when O_NONBLOCK is set. So, applications setting O_NONBLOCK must use | ||
836 | * select(2) or poll(2) to wait for the buffer to drain before closing. | ||
837 | * Alternatively, set blocking mode with fcntl and issue a zero-size write. | ||
838 | * | ||
839 | * Old v0.13 code had a non-functional timeout for wait_event(). Someone forgot | ||
840 | * to check the return code for timeout expiration, so it had no effect. | ||
841 | * Apparently, it was intended to check for error conditons, such as out | ||
842 | * of paper. It is going to return when we settle things with CUPS. XXX | ||
843 | */ | ||
844 | static int usblp_wwait(struct usblp *usblp, int nonblock) | ||
845 | { | ||
846 | DECLARE_WAITQUEUE(waita, current); | ||
847 | int rc; | ||
848 | |||
849 | add_wait_queue(&usblp->wwait, &waita); | ||
850 | for (;;) { | ||
851 | if (mutex_lock_interruptible(&usblp->mut)) { | ||
852 | rc = -EINTR; | ||
853 | break; | ||
854 | } | ||
855 | set_current_state(TASK_INTERRUPTIBLE); | ||
856 | if ((rc = usblp_wtest(usblp, nonblock)) < 0) { | ||
857 | mutex_unlock(&usblp->mut); | ||
858 | break; | ||
859 | } | ||
860 | mutex_unlock(&usblp->mut); | ||
861 | if (rc == 0) | ||
862 | break; | ||
863 | schedule(); | ||
781 | } | 864 | } |
865 | set_current_state(TASK_RUNNING); | ||
866 | remove_wait_queue(&usblp->wwait, &waita); | ||
867 | return rc; | ||
868 | } | ||
782 | 869 | ||
783 | if (usblp->sleeping) { | 870 | static int usblp_wtest(struct usblp *usblp, int nonblock) |
784 | count = -ENODEV; | 871 | { |
785 | goto done; | 872 | unsigned long flags; |
873 | |||
874 | if (!usblp->present) | ||
875 | return -ENODEV; | ||
876 | if (signal_pending(current)) | ||
877 | return -EINTR; | ||
878 | spin_lock_irqsave(&usblp->lock, flags); | ||
879 | if (usblp->wcomplete) { | ||
880 | spin_unlock_irqrestore(&usblp->lock, flags); | ||
881 | return 0; | ||
786 | } | 882 | } |
883 | spin_unlock_irqrestore(&usblp->lock, flags); | ||
884 | if (usblp->sleeping) | ||
885 | return -ENODEV; | ||
886 | if (nonblock) | ||
887 | return -EAGAIN; | ||
888 | return 1; | ||
889 | } | ||
787 | 890 | ||
788 | if (usblp->readurb->status) { | 891 | /* |
789 | err("usblp%d: error %d reading from printer", | 892 | * Wait for read bytes to become available. This probably should have been |
790 | usblp->minor, usblp->readurb->status); | 893 | * called usblp_r_lock_and_wait(), because we lock first. But it's a traditional |
791 | usblp->readurb->dev = usblp->dev; | 894 | * name for functions which lock and return. |
792 | usblp->readcount = 0; | 895 | * |
793 | usblp->rcomplete = 0; | 896 | * We do not use wait_event_interruptible because it makes locking iffy. |
794 | if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) | 897 | */ |
795 | dbg("error submitting urb"); | 898 | static int usblp_rwait_and_lock(struct usblp *usblp, int nonblock) |
796 | count = -EIO; | 899 | { |
797 | goto done; | 900 | DECLARE_WAITQUEUE(waita, current); |
901 | int rc; | ||
902 | |||
903 | add_wait_queue(&usblp->rwait, &waita); | ||
904 | for (;;) { | ||
905 | if (mutex_lock_interruptible(&usblp->mut)) { | ||
906 | rc = -EINTR; | ||
907 | break; | ||
908 | } | ||
909 | set_current_state(TASK_INTERRUPTIBLE); | ||
910 | if ((rc = usblp_rtest(usblp, nonblock)) < 0) { | ||
911 | mutex_unlock(&usblp->mut); | ||
912 | break; | ||
913 | } | ||
914 | if (rc == 0) /* Keep it locked */ | ||
915 | break; | ||
916 | mutex_unlock(&usblp->mut); | ||
917 | schedule(); | ||
798 | } | 918 | } |
919 | set_current_state(TASK_RUNNING); | ||
920 | remove_wait_queue(&usblp->rwait, &waita); | ||
921 | return rc; | ||
922 | } | ||
799 | 923 | ||
800 | count = count < usblp->readurb->actual_length - usblp->readcount ? | 924 | static int usblp_rtest(struct usblp *usblp, int nonblock) |
801 | count : usblp->readurb->actual_length - usblp->readcount; | 925 | { |
926 | unsigned long flags; | ||
802 | 927 | ||
803 | if (copy_to_user(buffer, usblp->readurb->transfer_buffer + usblp->readcount, count)) { | 928 | if (!usblp->present) |
804 | count = -EFAULT; | 929 | return -ENODEV; |
805 | goto done; | 930 | if (signal_pending(current)) |
931 | return -EINTR; | ||
932 | spin_lock_irqsave(&usblp->lock, flags); | ||
933 | if (usblp->rcomplete) { | ||
934 | spin_unlock_irqrestore(&usblp->lock, flags); | ||
935 | return 0; | ||
806 | } | 936 | } |
937 | spin_unlock_irqrestore(&usblp->lock, flags); | ||
938 | if (usblp->sleeping) | ||
939 | return -ENODEV; | ||
940 | if (nonblock) | ||
941 | return -EAGAIN; | ||
942 | return 1; | ||
943 | } | ||
807 | 944 | ||
808 | if ((usblp->readcount += count) == usblp->readurb->actual_length) { | 945 | /* |
809 | usblp->readcount = 0; | 946 | * Please check ->bidir and other such things outside for now. |
810 | usblp->readurb->dev = usblp->dev; | 947 | */ |
811 | usblp->rcomplete = 0; | 948 | static int usblp_submit_read(struct usblp *usblp) |
812 | if (usb_submit_urb(usblp->readurb, GFP_KERNEL)) { | 949 | { |
813 | count = -EIO; | 950 | struct urb *urb; |
814 | goto done; | 951 | unsigned long flags; |
815 | } | 952 | int rc; |
953 | |||
954 | rc = -ENOMEM; | ||
955 | if ((urb = usb_alloc_urb(0, GFP_KERNEL)) == NULL) | ||
956 | goto raise_urb; | ||
957 | |||
958 | usb_fill_bulk_urb(urb, usblp->dev, | ||
959 | usb_rcvbulkpipe(usblp->dev, | ||
960 | usblp->protocol[usblp->current_protocol].epread->bEndpointAddress), | ||
961 | usblp->readbuf, USBLP_BUF_SIZE_IN, | ||
962 | usblp_bulk_read, usblp); | ||
963 | usb_anchor_urb(urb, &usblp->urbs); | ||
964 | |||
965 | spin_lock_irqsave(&usblp->lock, flags); | ||
966 | usblp->readcount = 0; /* XXX Why here? */ | ||
967 | usblp->rcomplete = 0; | ||
968 | spin_unlock_irqrestore(&usblp->lock, flags); | ||
969 | if ((rc = usb_submit_urb(urb, GFP_KERNEL)) < 0) { | ||
970 | dbg("error submitting urb (%d)", rc); | ||
971 | spin_lock_irqsave(&usblp->lock, flags); | ||
972 | usblp->rstatus = rc; | ||
973 | usblp->rcomplete = 1; | ||
974 | spin_unlock_irqrestore(&usblp->lock, flags); | ||
975 | goto raise_submit; | ||
816 | } | 976 | } |
817 | 977 | ||
818 | done: | 978 | return 0; |
819 | mutex_unlock (&usblp->mut); | 979 | |
820 | return count; | 980 | raise_submit: |
981 | usb_unanchor_urb(urb); | ||
982 | usb_free_urb(urb); | ||
983 | raise_urb: | ||
984 | return rc; | ||
821 | } | 985 | } |
822 | 986 | ||
823 | /* | 987 | /* |
@@ -891,55 +1055,41 @@ static int usblp_probe(struct usb_interface *intf, | |||
891 | /* Malloc and start initializing usblp structure so we can use it | 1055 | /* Malloc and start initializing usblp structure so we can use it |
892 | * directly. */ | 1056 | * directly. */ |
893 | if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) { | 1057 | if (!(usblp = kzalloc(sizeof(struct usblp), GFP_KERNEL))) { |
894 | err("out of memory for usblp"); | 1058 | retval = -ENOMEM; |
895 | goto abort; | 1059 | goto abort; |
896 | } | 1060 | } |
897 | usblp->dev = dev; | 1061 | usblp->dev = dev; |
1062 | mutex_init(&usblp->wmut); | ||
898 | mutex_init (&usblp->mut); | 1063 | mutex_init (&usblp->mut); |
899 | init_waitqueue_head(&usblp->wait); | 1064 | spin_lock_init(&usblp->lock); |
1065 | init_waitqueue_head(&usblp->rwait); | ||
1066 | init_waitqueue_head(&usblp->wwait); | ||
1067 | init_usb_anchor(&usblp->urbs); | ||
900 | usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; | 1068 | usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; |
901 | usblp->intf = intf; | 1069 | usblp->intf = intf; |
902 | 1070 | ||
903 | usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL); | ||
904 | if (!usblp->writeurb) { | ||
905 | err("out of memory"); | ||
906 | goto abort; | ||
907 | } | ||
908 | usblp->readurb = usb_alloc_urb(0, GFP_KERNEL); | ||
909 | if (!usblp->readurb) { | ||
910 | err("out of memory"); | ||
911 | goto abort; | ||
912 | } | ||
913 | |||
914 | /* Malloc device ID string buffer to the largest expected length, | 1071 | /* Malloc device ID string buffer to the largest expected length, |
915 | * since we can re-query it on an ioctl and a dynamic string | 1072 | * since we can re-query it on an ioctl and a dynamic string |
916 | * could change in length. */ | 1073 | * could change in length. */ |
917 | if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) { | 1074 | if (!(usblp->device_id_string = kmalloc(USBLP_DEVICE_ID_SIZE, GFP_KERNEL))) { |
918 | err("out of memory for device_id_string"); | 1075 | retval = -ENOMEM; |
919 | goto abort; | 1076 | goto abort; |
920 | } | 1077 | } |
921 | 1078 | ||
922 | usblp->writebuf = usblp->readbuf = NULL; | 1079 | /* |
923 | usblp->writeurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | 1080 | * Allocate read buffer. We somewhat wastefully |
924 | usblp->readurb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | ||
925 | /* Malloc write & read buffers. We somewhat wastefully | ||
926 | * malloc both regardless of bidirectionality, because the | 1081 | * malloc both regardless of bidirectionality, because the |
927 | * alternate setting can be changed later via an ioctl. */ | 1082 | * alternate setting can be changed later via an ioctl. |
928 | if (!(usblp->writebuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE, | 1083 | */ |
929 | GFP_KERNEL, &usblp->writeurb->transfer_dma))) { | 1084 | if (!(usblp->readbuf = kmalloc(USBLP_BUF_SIZE_IN, GFP_KERNEL))) { |
930 | err("out of memory for write buf"); | 1085 | retval = -ENOMEM; |
931 | goto abort; | ||
932 | } | ||
933 | if (!(usblp->readbuf = usb_buffer_alloc(dev, USBLP_BUF_SIZE, | ||
934 | GFP_KERNEL, &usblp->readurb->transfer_dma))) { | ||
935 | err("out of memory for read buf"); | ||
936 | goto abort; | 1086 | goto abort; |
937 | } | 1087 | } |
938 | 1088 | ||
939 | /* Allocate buffer for printer status */ | 1089 | /* Allocate buffer for printer status */ |
940 | usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); | 1090 | usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); |
941 | if (!usblp->statusbuf) { | 1091 | if (!usblp->statusbuf) { |
942 | err("out of memory for statusbuf"); | 1092 | retval = -ENOMEM; |
943 | goto abort; | 1093 | goto abort; |
944 | } | 1094 | } |
945 | 1095 | ||
@@ -954,12 +1104,15 @@ static int usblp_probe(struct usb_interface *intf, | |||
954 | dbg("incompatible printer-class device 0x%4.4X/0x%4.4X", | 1104 | dbg("incompatible printer-class device 0x%4.4X/0x%4.4X", |
955 | le16_to_cpu(dev->descriptor.idVendor), | 1105 | le16_to_cpu(dev->descriptor.idVendor), |
956 | le16_to_cpu(dev->descriptor.idProduct)); | 1106 | le16_to_cpu(dev->descriptor.idProduct)); |
1107 | retval = -ENODEV; | ||
957 | goto abort; | 1108 | goto abort; |
958 | } | 1109 | } |
959 | 1110 | ||
960 | /* Setup the selected alternate setting and endpoints. */ | 1111 | /* Setup the selected alternate setting and endpoints. */ |
961 | if (usblp_set_protocol(usblp, protocol) < 0) | 1112 | if (usblp_set_protocol(usblp, protocol) < 0) { |
1113 | retval = -ENODEV; /* ->probe isn't ->ioctl */ | ||
962 | goto abort; | 1114 | goto abort; |
1115 | } | ||
963 | 1116 | ||
964 | /* Retrieve and store the device ID string. */ | 1117 | /* Retrieve and store the device ID string. */ |
965 | usblp_cache_device_id_string(usblp); | 1118 | usblp_cache_device_id_string(usblp); |
@@ -977,12 +1130,14 @@ static int usblp_probe(struct usb_interface *intf, | |||
977 | 1130 | ||
978 | retval = usb_register_dev(intf, &usblp_class); | 1131 | retval = usb_register_dev(intf, &usblp_class); |
979 | if (retval) { | 1132 | if (retval) { |
980 | err("Not able to get a minor for this device."); | 1133 | printk(KERN_ERR "usblp: Not able to get a minor" |
1134 | " (base %u, slice default): %d\n", | ||
1135 | USBLP_MINOR_BASE, retval); | ||
981 | goto abort_intfdata; | 1136 | goto abort_intfdata; |
982 | } | 1137 | } |
983 | usblp->minor = intf->minor; | 1138 | usblp->minor = intf->minor; |
984 | info("usblp%d: USB %sdirectional printer dev %d " | 1139 | printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d " |
985 | "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X", | 1140 | "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n", |
986 | usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, | 1141 | usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum, |
987 | usblp->ifnum, | 1142 | usblp->ifnum, |
988 | usblp->protocol[usblp->current_protocol].alt_setting, | 1143 | usblp->protocol[usblp->current_protocol].alt_setting, |
@@ -997,19 +1152,12 @@ abort_intfdata: | |||
997 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); | 1152 | device_remove_file(&intf->dev, &dev_attr_ieee1284_id); |
998 | abort: | 1153 | abort: |
999 | if (usblp) { | 1154 | if (usblp) { |
1000 | if (usblp->writebuf) | 1155 | kfree(usblp->readbuf); |
1001 | usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, | ||
1002 | usblp->writebuf, usblp->writeurb->transfer_dma); | ||
1003 | if (usblp->readbuf) | ||
1004 | usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, | ||
1005 | usblp->readbuf, usblp->readurb->transfer_dma); | ||
1006 | kfree(usblp->statusbuf); | 1156 | kfree(usblp->statusbuf); |
1007 | kfree(usblp->device_id_string); | 1157 | kfree(usblp->device_id_string); |
1008 | usb_free_urb(usblp->writeurb); | ||
1009 | usb_free_urb(usblp->readurb); | ||
1010 | kfree(usblp); | 1158 | kfree(usblp); |
1011 | } | 1159 | } |
1012 | return -EIO; | 1160 | return retval; |
1013 | } | 1161 | } |
1014 | 1162 | ||
1015 | /* | 1163 | /* |
@@ -1078,8 +1226,9 @@ static int usblp_select_alts(struct usblp *usblp) | |||
1078 | if (ifd->desc.bInterfaceProtocol == 1) { | 1226 | if (ifd->desc.bInterfaceProtocol == 1) { |
1079 | epread = NULL; | 1227 | epread = NULL; |
1080 | } else if (usblp->quirks & USBLP_QUIRK_BIDIR) { | 1228 | } else if (usblp->quirks & USBLP_QUIRK_BIDIR) { |
1081 | info("Disabling reads from problem bidirectional " | 1229 | printk(KERN_INFO "usblp%d: Disabling reads from " |
1082 | "printer on usblp%d", usblp->minor); | 1230 | "problematic bidirectional printer\n", |
1231 | usblp->minor); | ||
1083 | epread = NULL; | 1232 | epread = NULL; |
1084 | } | 1233 | } |
1085 | 1234 | ||
@@ -1119,25 +1268,12 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol) | |||
1119 | return -EINVAL; | 1268 | return -EINVAL; |
1120 | r = usb_set_interface(usblp->dev, usblp->ifnum, alts); | 1269 | r = usb_set_interface(usblp->dev, usblp->ifnum, alts); |
1121 | if (r < 0) { | 1270 | if (r < 0) { |
1122 | err("can't set desired altsetting %d on interface %d", | 1271 | printk(KERN_ERR "usblp: can't set desired altsetting %d on interface %d\n", |
1123 | alts, usblp->ifnum); | 1272 | alts, usblp->ifnum); |
1124 | return r; | 1273 | return r; |
1125 | } | 1274 | } |
1126 | 1275 | ||
1127 | usb_fill_bulk_urb(usblp->writeurb, usblp->dev, | ||
1128 | usb_sndbulkpipe(usblp->dev, | ||
1129 | usblp->protocol[protocol].epwrite->bEndpointAddress), | ||
1130 | usblp->writebuf, 0, | ||
1131 | usblp_bulk_write, usblp); | ||
1132 | |||
1133 | usblp->bidir = (usblp->protocol[protocol].epread != NULL); | 1276 | usblp->bidir = (usblp->protocol[protocol].epread != NULL); |
1134 | if (usblp->bidir) | ||
1135 | usb_fill_bulk_urb(usblp->readurb, usblp->dev, | ||
1136 | usb_rcvbulkpipe(usblp->dev, | ||
1137 | usblp->protocol[protocol].epread->bEndpointAddress), | ||
1138 | usblp->readbuf, USBLP_BUF_SIZE, | ||
1139 | usblp_bulk_read, usblp); | ||
1140 | |||
1141 | usblp->current_protocol = protocol; | 1277 | usblp->current_protocol = protocol; |
1142 | dbg("usblp%d set protocol %d", usblp->minor, protocol); | 1278 | dbg("usblp%d set protocol %d", usblp->minor, protocol); |
1143 | return 0; | 1279 | return 0; |
@@ -1190,13 +1326,11 @@ static void usblp_disconnect(struct usb_interface *intf) | |||
1190 | mutex_lock (&usblp_mutex); | 1326 | mutex_lock (&usblp_mutex); |
1191 | mutex_lock (&usblp->mut); | 1327 | mutex_lock (&usblp->mut); |
1192 | usblp->present = 0; | 1328 | usblp->present = 0; |
1329 | wake_up(&usblp->wwait); | ||
1330 | wake_up(&usblp->rwait); | ||
1193 | usb_set_intfdata (intf, NULL); | 1331 | usb_set_intfdata (intf, NULL); |
1194 | 1332 | ||
1195 | usblp_unlink_urbs(usblp); | 1333 | usblp_unlink_urbs(usblp); |
1196 | usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, | ||
1197 | usblp->writebuf, usblp->writeurb->transfer_dma); | ||
1198 | usb_buffer_free (usblp->dev, USBLP_BUF_SIZE, | ||
1199 | usblp->readbuf, usblp->readurb->transfer_dma); | ||
1200 | mutex_unlock (&usblp->mut); | 1334 | mutex_unlock (&usblp->mut); |
1201 | 1335 | ||
1202 | if (!usblp->used) | 1336 | if (!usblp->used) |
@@ -1211,6 +1345,11 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message) | |||
1211 | /* we take no more IO */ | 1345 | /* we take no more IO */ |
1212 | usblp->sleeping = 1; | 1346 | usblp->sleeping = 1; |
1213 | usblp_unlink_urbs(usblp); | 1347 | usblp_unlink_urbs(usblp); |
1348 | #if 0 /* XXX Do we want this? What if someone is reading, should we fail? */ | ||
1349 | /* not strictly necessary, but just in case */ | ||
1350 | wake_up(&usblp->wwait); | ||
1351 | wake_up(&usblp->rwait); | ||
1352 | #endif | ||
1214 | 1353 | ||
1215 | return 0; | 1354 | return 0; |
1216 | } | 1355 | } |
@@ -1251,12 +1390,7 @@ static struct usb_driver usblp_driver = { | |||
1251 | 1390 | ||
1252 | static int __init usblp_init(void) | 1391 | static int __init usblp_init(void) |
1253 | { | 1392 | { |
1254 | int retval; | 1393 | return usb_register(&usblp_driver); |
1255 | retval = usb_register(&usblp_driver); | ||
1256 | if (!retval) | ||
1257 | info(DRIVER_VERSION ": " DRIVER_DESC); | ||
1258 | |||
1259 | return retval; | ||
1260 | } | 1394 | } |
1261 | 1395 | ||
1262 | static void __exit usblp_exit(void) | 1396 | static void __exit usblp_exit(void) |
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 346fc030c929..97b09f282705 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig | |||
@@ -86,6 +86,31 @@ config USB_SUSPEND | |||
86 | 86 | ||
87 | If you are unsure about this, say N here. | 87 | If you are unsure about this, say N here. |
88 | 88 | ||
89 | config USB_PERSIST | ||
90 | bool "USB device persistence during system suspend (DANGEROUS)" | ||
91 | depends on USB && PM && EXPERIMENTAL | ||
92 | default n | ||
93 | help | ||
94 | |||
95 | If you say Y here and enable the "power/persist" attribute | ||
96 | for a USB device, the device's data structures will remain | ||
97 | persistent across system suspend, even if the USB bus loses | ||
98 | power. (This includes hibernation, also known as swsusp or | ||
99 | suspend-to-disk.) The devices will reappear as if by magic | ||
100 | when the system wakes up, with no need to unmount USB | ||
101 | filesystems, rmmod host-controller drivers, or do anything | ||
102 | else. | ||
103 | |||
104 | WARNING: This option can be dangerous! | ||
105 | |||
106 | If a USB device is replaced by another of the same type while | ||
107 | the system is asleep, there's a good chance the kernel won't | ||
108 | detect the change. Likewise if the media in a USB storage | ||
109 | device is replaced. When this happens it's almost certain to | ||
110 | cause data corruption and maybe even crash your system. | ||
111 | |||
112 | If you are unsure, say N here. | ||
113 | |||
89 | config USB_OTG | 114 | config USB_OTG |
90 | bool | 115 | bool |
91 | depends on USB && EXPERIMENTAL | 116 | depends on USB && EXPERIMENTAL |
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index dd3482328ad2..cb69aa1e02e8 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c | |||
@@ -85,15 +85,21 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, | |||
85 | memcpy(&endpoint->desc, d, n); | 85 | memcpy(&endpoint->desc, d, n); |
86 | INIT_LIST_HEAD(&endpoint->urb_list); | 86 | INIT_LIST_HEAD(&endpoint->urb_list); |
87 | 87 | ||
88 | /* If the bInterval value is outside the legal range, | 88 | /* Fix up bInterval values outside the legal range. Use 32 ms if no |
89 | * set it to a default value: 32 ms */ | 89 | * proper value can be guessed. */ |
90 | i = 0; /* i = min, j = max, n = default */ | 90 | i = 0; /* i = min, j = max, n = default */ |
91 | j = 255; | 91 | j = 255; |
92 | if (usb_endpoint_xfer_int(d)) { | 92 | if (usb_endpoint_xfer_int(d)) { |
93 | i = 1; | 93 | i = 1; |
94 | switch (to_usb_device(ddev)->speed) { | 94 | switch (to_usb_device(ddev)->speed) { |
95 | case USB_SPEED_HIGH: | 95 | case USB_SPEED_HIGH: |
96 | n = 9; /* 32 ms = 2^(9-1) uframes */ | 96 | /* Many device manufacturers are using full-speed |
97 | * bInterval values in high-speed interrupt endpoint | ||
98 | * descriptors. Try to fix those and fall back to a | ||
99 | * 32 ms default value otherwise. */ | ||
100 | n = fls(d->bInterval*8); | ||
101 | if (n == 0) | ||
102 | n = 9; /* 32 ms = 2^(9-1) uframes */ | ||
97 | j = 16; | 103 | j = 16; |
98 | break; | 104 | break; |
99 | default: /* USB_SPEED_FULL or _LOW */ | 105 | default: /* USB_SPEED_FULL or _LOW */ |
@@ -124,6 +130,21 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, | |||
124 | endpoint->desc.bInterval = n; | 130 | endpoint->desc.bInterval = n; |
125 | } | 131 | } |
126 | 132 | ||
133 | /* Some buggy low-speed devices have Bulk endpoints, which is | ||
134 | * explicitly forbidden by the USB spec. In an attempt to make | ||
135 | * them usable, we will try treating them as Interrupt endpoints. | ||
136 | */ | ||
137 | if (to_usb_device(ddev)->speed == USB_SPEED_LOW && | ||
138 | usb_endpoint_xfer_bulk(d)) { | ||
139 | dev_warn(ddev, "config %d interface %d altsetting %d " | ||
140 | "endpoint 0x%X is Bulk; changing to Interrupt\n", | ||
141 | cfgno, inum, asnum, d->bEndpointAddress); | ||
142 | endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT; | ||
143 | endpoint->desc.bInterval = 1; | ||
144 | if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8) | ||
145 | endpoint->desc.wMaxPacketSize = cpu_to_le16(8); | ||
146 | } | ||
147 | |||
127 | /* Skip over any Class Specific or Vendor Specific descriptors; | 148 | /* Skip over any Class Specific or Vendor Specific descriptors; |
128 | * find the next endpoint or interface descriptor */ | 149 | * find the next endpoint or interface descriptor */ |
129 | endpoint->extra = buffer; | 150 | endpoint->extra = buffer; |
@@ -274,6 +295,7 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx, | |||
274 | struct usb_descriptor_header *header; | 295 | struct usb_descriptor_header *header; |
275 | int len, retval; | 296 | int len, retval; |
276 | u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES]; | 297 | u8 inums[USB_MAXINTERFACES], nalts[USB_MAXINTERFACES]; |
298 | unsigned iad_num = 0; | ||
277 | 299 | ||
278 | memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); | 300 | memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); |
279 | if (config->desc.bDescriptorType != USB_DT_CONFIG || | 301 | if (config->desc.bDescriptorType != USB_DT_CONFIG || |
@@ -351,6 +373,20 @@ static int usb_parse_configuration(struct device *ddev, int cfgidx, | |||
351 | ++n; | 373 | ++n; |
352 | } | 374 | } |
353 | 375 | ||
376 | } else if (header->bDescriptorType == | ||
377 | USB_DT_INTERFACE_ASSOCIATION) { | ||
378 | if (iad_num == USB_MAXIADS) { | ||
379 | dev_warn(ddev, "found more Interface " | ||
380 | "Association Descriptors " | ||
381 | "than allocated for in " | ||
382 | "configuration %d\n", cfgno); | ||
383 | } else { | ||
384 | config->intf_assoc[iad_num] = | ||
385 | (struct usb_interface_assoc_descriptor | ||
386 | *)header; | ||
387 | iad_num++; | ||
388 | } | ||
389 | |||
354 | } else if (header->bDescriptorType == USB_DT_DEVICE || | 390 | } else if (header->bDescriptorType == USB_DT_DEVICE || |
355 | header->bDescriptorType == USB_DT_CONFIG) | 391 | header->bDescriptorType == USB_DT_CONFIG) |
356 | dev_warn(ddev, "config %d contains an unexpected " | 392 | dev_warn(ddev, "config %d contains an unexpected " |
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 6753ca059ee4..87c794d60aa0 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c | |||
@@ -102,6 +102,10 @@ static const char *format_config = | |||
102 | /* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */ | 102 | /* C: #Ifs=dd Cfg#=dd Atr=xx MPwr=dddmA */ |
103 | "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n"; | 103 | "C:%c #Ifs=%2d Cfg#=%2d Atr=%02x MxPwr=%3dmA\n"; |
104 | 104 | ||
105 | static const char *format_iad = | ||
106 | /* A: FirstIf#=dd IfCount=dd Cls=xx(sssss) Sub=xx Prot=xx */ | ||
107 | "A: FirstIf#=%2d IfCount=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x\n"; | ||
108 | |||
105 | static const char *format_iface = | 109 | static const char *format_iface = |
106 | /* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/ | 110 | /* I: If#=dd Alt=dd #EPs=dd Cls=xx(sssss) Sub=xx Prot=xx Driver=xxxx*/ |
107 | "I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n"; | 111 | "I:%c If#=%2d Alt=%2d #EPs=%2d Cls=%02x(%-5s) Sub=%02x Prot=%02x Driver=%s\n"; |
@@ -146,6 +150,7 @@ static const struct class_info clas_info[] = | |||
146 | {USB_CLASS_STILL_IMAGE, "still"}, | 150 | {USB_CLASS_STILL_IMAGE, "still"}, |
147 | {USB_CLASS_CSCID, "scard"}, | 151 | {USB_CLASS_CSCID, "scard"}, |
148 | {USB_CLASS_CONTENT_SEC, "c-sec"}, | 152 | {USB_CLASS_CONTENT_SEC, "c-sec"}, |
153 | {USB_CLASS_VIDEO, "video"}, | ||
149 | {-1, "unk."} /* leave as last */ | 154 | {-1, "unk."} /* leave as last */ |
150 | }; | 155 | }; |
151 | 156 | ||
@@ -286,6 +291,21 @@ static char *usb_dump_interface( | |||
286 | return start; | 291 | return start; |
287 | } | 292 | } |
288 | 293 | ||
294 | static char *usb_dump_iad_descriptor(char *start, char *end, | ||
295 | const struct usb_interface_assoc_descriptor *iad) | ||
296 | { | ||
297 | if (start > end) | ||
298 | return start; | ||
299 | start += sprintf(start, format_iad, | ||
300 | iad->bFirstInterface, | ||
301 | iad->bInterfaceCount, | ||
302 | iad->bFunctionClass, | ||
303 | class_decode(iad->bFunctionClass), | ||
304 | iad->bFunctionSubClass, | ||
305 | iad->bFunctionProtocol); | ||
306 | return start; | ||
307 | } | ||
308 | |||
289 | /* TBD: | 309 | /* TBD: |
290 | * 0. TBDs | 310 | * 0. TBDs |
291 | * 1. marking active interface altsettings (code lists all, but should mark | 311 | * 1. marking active interface altsettings (code lists all, but should mark |
@@ -322,6 +342,12 @@ static char *usb_dump_config ( | |||
322 | if (!config) /* getting these some in 2.3.7; none in 2.3.6 */ | 342 | if (!config) /* getting these some in 2.3.7; none in 2.3.6 */ |
323 | return start + sprintf(start, "(null Cfg. desc.)\n"); | 343 | return start + sprintf(start, "(null Cfg. desc.)\n"); |
324 | start = usb_dump_config_descriptor(start, end, &config->desc, active); | 344 | start = usb_dump_config_descriptor(start, end, &config->desc, active); |
345 | for (i = 0; i < USB_MAXIADS; i++) { | ||
346 | if (config->intf_assoc[i] == NULL) | ||
347 | break; | ||
348 | start = usb_dump_iad_descriptor(start, end, | ||
349 | config->intf_assoc[i]); | ||
350 | } | ||
325 | for (i = 0; i < config->desc.bNumInterfaces; i++) { | 351 | for (i = 0; i < config->desc.bNumInterfaces; i++) { |
326 | intfc = config->intf_cache[i]; | 352 | intfc = config->intf_cache[i]; |
327 | interface = config->interface[i]; | 353 | interface = config->interface[i]; |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2619986e5300..73c49362cd47 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -24,10 +24,19 @@ | |||
24 | 24 | ||
25 | #include <linux/device.h> | 25 | #include <linux/device.h> |
26 | #include <linux/usb.h> | 26 | #include <linux/usb.h> |
27 | #include <linux/usb/quirks.h> | ||
27 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
28 | #include "hcd.h" | 29 | #include "hcd.h" |
29 | #include "usb.h" | 30 | #include "usb.h" |
30 | 31 | ||
32 | #define VERBOSE_DEBUG 0 | ||
33 | |||
34 | #if VERBOSE_DEBUG | ||
35 | #define dev_vdbg dev_dbg | ||
36 | #else | ||
37 | #define dev_vdbg(dev, fmt, args...) do { } while (0) | ||
38 | #endif | ||
39 | |||
31 | #ifdef CONFIG_HOTPLUG | 40 | #ifdef CONFIG_HOTPLUG |
32 | 41 | ||
33 | /* | 42 | /* |
@@ -802,18 +811,17 @@ static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) | |||
802 | udev->state == USB_STATE_SUSPENDED) | 811 | udev->state == USB_STATE_SUSPENDED) |
803 | goto done; | 812 | goto done; |
804 | 813 | ||
805 | /* For devices that don't have a driver, we do a standard suspend. */ | 814 | /* For devices that don't have a driver, we do a generic suspend. */ |
806 | if (udev->dev.driver == NULL) { | 815 | if (udev->dev.driver) |
816 | udriver = to_usb_device_driver(udev->dev.driver); | ||
817 | else { | ||
807 | udev->do_remote_wakeup = 0; | 818 | udev->do_remote_wakeup = 0; |
808 | status = usb_port_suspend(udev); | 819 | udriver = &usb_generic_driver; |
809 | goto done; | ||
810 | } | 820 | } |
811 | |||
812 | udriver = to_usb_device_driver(udev->dev.driver); | ||
813 | status = udriver->suspend(udev, msg); | 821 | status = udriver->suspend(udev, msg); |
814 | 822 | ||
815 | done: | 823 | done: |
816 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); | 824 | dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); |
817 | if (status == 0) | 825 | if (status == 0) |
818 | udev->dev.power.power_state.event = msg.event; | 826 | udev->dev.power.power_state.event = msg.event; |
819 | return status; | 827 | return status; |
@@ -825,8 +833,9 @@ static int usb_resume_device(struct usb_device *udev) | |||
825 | struct usb_device_driver *udriver; | 833 | struct usb_device_driver *udriver; |
826 | int status = 0; | 834 | int status = 0; |
827 | 835 | ||
828 | if (udev->state == USB_STATE_NOTATTACHED || | 836 | if (udev->state == USB_STATE_NOTATTACHED) |
829 | udev->state != USB_STATE_SUSPENDED) | 837 | goto done; |
838 | if (udev->state != USB_STATE_SUSPENDED && !udev->reset_resume) | ||
830 | goto done; | 839 | goto done; |
831 | 840 | ||
832 | /* Can't resume it if it doesn't have a driver. */ | 841 | /* Can't resume it if it doesn't have a driver. */ |
@@ -835,11 +844,14 @@ static int usb_resume_device(struct usb_device *udev) | |||
835 | goto done; | 844 | goto done; |
836 | } | 845 | } |
837 | 846 | ||
847 | if (udev->quirks & USB_QUIRK_RESET_RESUME) | ||
848 | udev->reset_resume = 1; | ||
849 | |||
838 | udriver = to_usb_device_driver(udev->dev.driver); | 850 | udriver = to_usb_device_driver(udev->dev.driver); |
839 | status = udriver->resume(udev); | 851 | status = udriver->resume(udev); |
840 | 852 | ||
841 | done: | 853 | done: |
842 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); | 854 | dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); |
843 | if (status == 0) { | 855 | if (status == 0) { |
844 | udev->autoresume_disabled = 0; | 856 | udev->autoresume_disabled = 0; |
845 | udev->dev.power.power_state.event = PM_EVENT_ON; | 857 | udev->dev.power.power_state.event = PM_EVENT_ON; |
@@ -877,15 +889,13 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) | |||
877 | mark_quiesced(intf); | 889 | mark_quiesced(intf); |
878 | } | 890 | } |
879 | 891 | ||
880 | done: | 892 | done: |
881 | // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status); | 893 | dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status); |
882 | if (status == 0) | ||
883 | intf->dev.power.power_state.event = msg.event; | ||
884 | return status; | 894 | return status; |
885 | } | 895 | } |
886 | 896 | ||
887 | /* Caller has locked intf's usb_device's pm_mutex */ | 897 | /* Caller has locked intf's usb_device's pm_mutex */ |
888 | static int usb_resume_interface(struct usb_interface *intf) | 898 | static int usb_resume_interface(struct usb_interface *intf, int reset_resume) |
889 | { | 899 | { |
890 | struct usb_driver *driver; | 900 | struct usb_driver *driver; |
891 | int status = 0; | 901 | int status = 0; |
@@ -905,23 +915,37 @@ static int usb_resume_interface(struct usb_interface *intf) | |||
905 | } | 915 | } |
906 | driver = to_usb_driver(intf->dev.driver); | 916 | driver = to_usb_driver(intf->dev.driver); |
907 | 917 | ||
908 | if (driver->resume) { | 918 | if (reset_resume) { |
909 | status = driver->resume(intf); | 919 | if (driver->reset_resume) { |
910 | if (status) | 920 | status = driver->reset_resume(intf); |
911 | dev_err(&intf->dev, "%s error %d\n", | 921 | if (status) |
912 | "resume", status); | 922 | dev_err(&intf->dev, "%s error %d\n", |
913 | else | 923 | "reset_resume", status); |
914 | mark_active(intf); | 924 | } else { |
925 | // status = -EOPNOTSUPP; | ||
926 | dev_warn(&intf->dev, "no %s for driver %s?\n", | ||
927 | "reset_resume", driver->name); | ||
928 | } | ||
915 | } else { | 929 | } else { |
916 | dev_warn(&intf->dev, "no resume for driver %s?\n", | 930 | if (driver->resume) { |
917 | driver->name); | 931 | status = driver->resume(intf); |
918 | mark_active(intf); | 932 | if (status) |
933 | dev_err(&intf->dev, "%s error %d\n", | ||
934 | "resume", status); | ||
935 | } else { | ||
936 | // status = -EOPNOTSUPP; | ||
937 | dev_warn(&intf->dev, "no %s for driver %s?\n", | ||
938 | "resume", driver->name); | ||
939 | } | ||
919 | } | 940 | } |
920 | 941 | ||
921 | done: | 942 | done: |
922 | // dev_dbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status); | 943 | dev_vdbg(&intf->dev, "%s: status %d\n", __FUNCTION__, status); |
923 | if (status == 0) | 944 | if (status == 0) |
924 | intf->dev.power.power_state.event = PM_EVENT_ON; | 945 | mark_active(intf); |
946 | |||
947 | /* FIXME: Unbind the driver and reprobe if the resume failed | ||
948 | * (not possible if auto_pm is set) */ | ||
925 | return status; | 949 | return status; |
926 | } | 950 | } |
927 | 951 | ||
@@ -958,6 +982,18 @@ static int autosuspend_check(struct usb_device *udev) | |||
958 | "for autosuspend\n"); | 982 | "for autosuspend\n"); |
959 | return -EOPNOTSUPP; | 983 | return -EOPNOTSUPP; |
960 | } | 984 | } |
985 | |||
986 | /* Don't allow autosuspend if the device will need | ||
987 | * a reset-resume and any of its interface drivers | ||
988 | * doesn't include support. | ||
989 | */ | ||
990 | if (udev->quirks & USB_QUIRK_RESET_RESUME) { | ||
991 | struct usb_driver *driver; | ||
992 | |||
993 | driver = to_usb_driver(intf->dev.driver); | ||
994 | if (!driver->reset_resume) | ||
995 | return -EOPNOTSUPP; | ||
996 | } | ||
961 | } | 997 | } |
962 | } | 998 | } |
963 | 999 | ||
@@ -974,7 +1010,7 @@ static int autosuspend_check(struct usb_device *udev) | |||
974 | * or for the past. | 1010 | * or for the past. |
975 | */ | 1011 | */ |
976 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, | 1012 | queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, |
977 | suspend_time - jiffies); | 1013 | round_jiffies_relative(suspend_time - jiffies)); |
978 | } | 1014 | } |
979 | return -EAGAIN; | 1015 | return -EAGAIN; |
980 | } | 1016 | } |
@@ -1054,14 +1090,21 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1054 | break; | 1090 | break; |
1055 | } | 1091 | } |
1056 | } | 1092 | } |
1057 | if (status == 0) | 1093 | if (status == 0) { |
1094 | |||
1095 | /* Non-root devices don't need to do anything for FREEZE | ||
1096 | * or PRETHAW. */ | ||
1097 | if (udev->parent && (msg.event == PM_EVENT_FREEZE || | ||
1098 | msg.event == PM_EVENT_PRETHAW)) | ||
1099 | goto done; | ||
1058 | status = usb_suspend_device(udev, msg); | 1100 | status = usb_suspend_device(udev, msg); |
1101 | } | ||
1059 | 1102 | ||
1060 | /* If the suspend failed, resume interfaces that did get suspended */ | 1103 | /* If the suspend failed, resume interfaces that did get suspended */ |
1061 | if (status != 0) { | 1104 | if (status != 0) { |
1062 | while (--i >= 0) { | 1105 | while (--i >= 0) { |
1063 | intf = udev->actconfig->interface[i]; | 1106 | intf = udev->actconfig->interface[i]; |
1064 | usb_resume_interface(intf); | 1107 | usb_resume_interface(intf, 0); |
1065 | } | 1108 | } |
1066 | 1109 | ||
1067 | /* Try another autosuspend when the interfaces aren't busy */ | 1110 | /* Try another autosuspend when the interfaces aren't busy */ |
@@ -1076,7 +1119,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) | |||
1076 | } | 1119 | } |
1077 | 1120 | ||
1078 | done: | 1121 | done: |
1079 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); | 1122 | dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); |
1080 | return status; | 1123 | return status; |
1081 | } | 1124 | } |
1082 | 1125 | ||
@@ -1131,7 +1174,8 @@ static int usb_resume_both(struct usb_device *udev) | |||
1131 | status = usb_autoresume_device(parent); | 1174 | status = usb_autoresume_device(parent); |
1132 | if (status == 0) { | 1175 | if (status == 0) { |
1133 | status = usb_resume_device(udev); | 1176 | status = usb_resume_device(udev); |
1134 | if (status) { | 1177 | if (status || udev->state == |
1178 | USB_STATE_NOTATTACHED) { | ||
1135 | usb_autosuspend_device(parent); | 1179 | usb_autosuspend_device(parent); |
1136 | 1180 | ||
1137 | /* It's possible usb_resume_device() | 1181 | /* It's possible usb_resume_device() |
@@ -1152,28 +1196,25 @@ static int usb_resume_both(struct usb_device *udev) | |||
1152 | /* We can't progagate beyond the USB subsystem, | 1196 | /* We can't progagate beyond the USB subsystem, |
1153 | * so if a root hub's controller is suspended | 1197 | * so if a root hub's controller is suspended |
1154 | * then we're stuck. */ | 1198 | * then we're stuck. */ |
1155 | if (udev->dev.parent->power.power_state.event != | 1199 | status = usb_resume_device(udev); |
1156 | PM_EVENT_ON) | ||
1157 | status = -EHOSTUNREACH; | ||
1158 | else | ||
1159 | status = usb_resume_device(udev); | ||
1160 | } | 1200 | } |
1161 | } else { | 1201 | } else { |
1162 | 1202 | ||
1163 | /* Needed only for setting udev->dev.power.power_state.event | 1203 | /* Needed for setting udev->dev.power.power_state.event, |
1164 | * and for possible debugging message. */ | 1204 | * for possible debugging message, and for reset_resume. */ |
1165 | status = usb_resume_device(udev); | 1205 | status = usb_resume_device(udev); |
1166 | } | 1206 | } |
1167 | 1207 | ||
1168 | if (status == 0 && udev->actconfig) { | 1208 | if (status == 0 && udev->actconfig) { |
1169 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { | 1209 | for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { |
1170 | intf = udev->actconfig->interface[i]; | 1210 | intf = udev->actconfig->interface[i]; |
1171 | usb_resume_interface(intf); | 1211 | usb_resume_interface(intf, udev->reset_resume); |
1172 | } | 1212 | } |
1173 | } | 1213 | } |
1174 | 1214 | ||
1175 | done: | 1215 | done: |
1176 | // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); | 1216 | dev_vdbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); |
1217 | udev->reset_resume = 0; | ||
1177 | return status; | 1218 | return status; |
1178 | } | 1219 | } |
1179 | 1220 | ||
@@ -1240,8 +1281,8 @@ void usb_autosuspend_device(struct usb_device *udev) | |||
1240 | int status; | 1281 | int status; |
1241 | 1282 | ||
1242 | status = usb_autopm_do_device(udev, -1); | 1283 | status = usb_autopm_do_device(udev, -1); |
1243 | // dev_dbg(&udev->dev, "%s: cnt %d\n", | 1284 | dev_vdbg(&udev->dev, "%s: cnt %d\n", |
1244 | // __FUNCTION__, udev->pm_usage_cnt); | 1285 | __FUNCTION__, udev->pm_usage_cnt); |
1245 | } | 1286 | } |
1246 | 1287 | ||
1247 | /** | 1288 | /** |
@@ -1260,8 +1301,8 @@ void usb_autosuspend_device(struct usb_device *udev) | |||
1260 | void usb_try_autosuspend_device(struct usb_device *udev) | 1301 | void usb_try_autosuspend_device(struct usb_device *udev) |
1261 | { | 1302 | { |
1262 | usb_autopm_do_device(udev, 0); | 1303 | usb_autopm_do_device(udev, 0); |
1263 | // dev_dbg(&udev->dev, "%s: cnt %d\n", | 1304 | dev_vdbg(&udev->dev, "%s: cnt %d\n", |
1264 | // __FUNCTION__, udev->pm_usage_cnt); | 1305 | __FUNCTION__, udev->pm_usage_cnt); |
1265 | } | 1306 | } |
1266 | 1307 | ||
1267 | /** | 1308 | /** |
@@ -1288,8 +1329,8 @@ int usb_autoresume_device(struct usb_device *udev) | |||
1288 | int status; | 1329 | int status; |
1289 | 1330 | ||
1290 | status = usb_autopm_do_device(udev, 1); | 1331 | status = usb_autopm_do_device(udev, 1); |
1291 | // dev_dbg(&udev->dev, "%s: status %d cnt %d\n", | 1332 | dev_vdbg(&udev->dev, "%s: status %d cnt %d\n", |
1292 | // __FUNCTION__, status, udev->pm_usage_cnt); | 1333 | __FUNCTION__, status, udev->pm_usage_cnt); |
1293 | return status; | 1334 | return status; |
1294 | } | 1335 | } |
1295 | 1336 | ||
@@ -1361,8 +1402,8 @@ void usb_autopm_put_interface(struct usb_interface *intf) | |||
1361 | int status; | 1402 | int status; |
1362 | 1403 | ||
1363 | status = usb_autopm_do_interface(intf, -1); | 1404 | status = usb_autopm_do_interface(intf, -1); |
1364 | // dev_dbg(&intf->dev, "%s: status %d cnt %d\n", | 1405 | dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", |
1365 | // __FUNCTION__, status, intf->pm_usage_cnt); | 1406 | __FUNCTION__, status, intf->pm_usage_cnt); |
1366 | } | 1407 | } |
1367 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface); | 1408 | EXPORT_SYMBOL_GPL(usb_autopm_put_interface); |
1368 | 1409 | ||
@@ -1405,8 +1446,8 @@ int usb_autopm_get_interface(struct usb_interface *intf) | |||
1405 | int status; | 1446 | int status; |
1406 | 1447 | ||
1407 | status = usb_autopm_do_interface(intf, 1); | 1448 | status = usb_autopm_do_interface(intf, 1); |
1408 | // dev_dbg(&intf->dev, "%s: status %d cnt %d\n", | 1449 | dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", |
1409 | // __FUNCTION__, status, intf->pm_usage_cnt); | 1450 | __FUNCTION__, status, intf->pm_usage_cnt); |
1410 | return status; | 1451 | return status; |
1411 | } | 1452 | } |
1412 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface); | 1453 | EXPORT_SYMBOL_GPL(usb_autopm_get_interface); |
@@ -1427,8 +1468,8 @@ int usb_autopm_set_interface(struct usb_interface *intf) | |||
1427 | int status; | 1468 | int status; |
1428 | 1469 | ||
1429 | status = usb_autopm_do_interface(intf, 0); | 1470 | status = usb_autopm_do_interface(intf, 0); |
1430 | // dev_dbg(&intf->dev, "%s: status %d cnt %d\n", | 1471 | dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", |
1431 | // __FUNCTION__, status, intf->pm_usage_cnt); | 1472 | __FUNCTION__, status, intf->pm_usage_cnt); |
1432 | return status; | 1473 | return status; |
1433 | } | 1474 | } |
1434 | EXPORT_SYMBOL_GPL(usb_autopm_set_interface); | 1475 | EXPORT_SYMBOL_GPL(usb_autopm_set_interface); |
@@ -1508,8 +1549,15 @@ static int usb_resume(struct device *dev) | |||
1508 | if (!is_usb_device(dev)) /* Ignore PM for interfaces */ | 1549 | if (!is_usb_device(dev)) /* Ignore PM for interfaces */ |
1509 | return 0; | 1550 | return 0; |
1510 | udev = to_usb_device(dev); | 1551 | udev = to_usb_device(dev); |
1511 | if (udev->autoresume_disabled) | 1552 | |
1512 | return -EPERM; | 1553 | /* If autoresume is disabled then we also want to prevent resume |
1554 | * during system wakeup. However, a "persistent-device" reset-resume | ||
1555 | * after power loss counts as a wakeup event. So allow a | ||
1556 | * reset-resume to occur if remote wakeup is enabled. */ | ||
1557 | if (udev->autoresume_disabled) { | ||
1558 | if (!(udev->reset_resume && udev->do_remote_wakeup)) | ||
1559 | return -EPERM; | ||
1560 | } | ||
1513 | return usb_external_resume_device(udev); | 1561 | return usb_external_resume_device(udev); |
1514 | } | 1562 | } |
1515 | 1563 | ||
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c index 01c857ac27af..5d860bc9b421 100644 --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c | |||
@@ -16,15 +16,15 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/spinlock.h> | ||
20 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
20 | #include <linux/rwsem.h> | ||
21 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
22 | 22 | ||
23 | #include "usb.h" | 23 | #include "usb.h" |
24 | 24 | ||
25 | #define MAX_USB_MINORS 256 | 25 | #define MAX_USB_MINORS 256 |
26 | static const struct file_operations *usb_minors[MAX_USB_MINORS]; | 26 | static const struct file_operations *usb_minors[MAX_USB_MINORS]; |
27 | static DEFINE_SPINLOCK(minor_lock); | 27 | static DECLARE_RWSEM(minor_rwsem); |
28 | 28 | ||
29 | static int usb_open(struct inode * inode, struct file * file) | 29 | static int usb_open(struct inode * inode, struct file * file) |
30 | { | 30 | { |
@@ -33,14 +33,11 @@ static int usb_open(struct inode * inode, struct file * file) | |||
33 | int err = -ENODEV; | 33 | int err = -ENODEV; |
34 | const struct file_operations *old_fops, *new_fops = NULL; | 34 | const struct file_operations *old_fops, *new_fops = NULL; |
35 | 35 | ||
36 | spin_lock (&minor_lock); | 36 | down_read(&minor_rwsem); |
37 | c = usb_minors[minor]; | 37 | c = usb_minors[minor]; |
38 | 38 | ||
39 | if (!c || !(new_fops = fops_get(c))) { | 39 | if (!c || !(new_fops = fops_get(c))) |
40 | spin_unlock(&minor_lock); | 40 | goto done; |
41 | return err; | ||
42 | } | ||
43 | spin_unlock(&minor_lock); | ||
44 | 41 | ||
45 | old_fops = file->f_op; | 42 | old_fops = file->f_op; |
46 | file->f_op = new_fops; | 43 | file->f_op = new_fops; |
@@ -52,6 +49,8 @@ static int usb_open(struct inode * inode, struct file * file) | |||
52 | file->f_op = fops_get(old_fops); | 49 | file->f_op = fops_get(old_fops); |
53 | } | 50 | } |
54 | fops_put(old_fops); | 51 | fops_put(old_fops); |
52 | done: | ||
53 | up_read(&minor_rwsem); | ||
55 | return err; | 54 | return err; |
56 | } | 55 | } |
57 | 56 | ||
@@ -166,7 +165,7 @@ int usb_register_dev(struct usb_interface *intf, | |||
166 | if (class_driver->fops == NULL) | 165 | if (class_driver->fops == NULL) |
167 | goto exit; | 166 | goto exit; |
168 | 167 | ||
169 | spin_lock (&minor_lock); | 168 | down_write(&minor_rwsem); |
170 | for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { | 169 | for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) { |
171 | if (usb_minors[minor]) | 170 | if (usb_minors[minor]) |
172 | continue; | 171 | continue; |
@@ -176,7 +175,7 @@ int usb_register_dev(struct usb_interface *intf, | |||
176 | retval = 0; | 175 | retval = 0; |
177 | break; | 176 | break; |
178 | } | 177 | } |
179 | spin_unlock (&minor_lock); | 178 | up_write(&minor_rwsem); |
180 | 179 | ||
181 | if (retval) | 180 | if (retval) |
182 | goto exit; | 181 | goto exit; |
@@ -197,9 +196,9 @@ int usb_register_dev(struct usb_interface *intf, | |||
197 | intf->usb_dev = device_create(usb_class->class, &intf->dev, | 196 | intf->usb_dev = device_create(usb_class->class, &intf->dev, |
198 | MKDEV(USB_MAJOR, minor), "%s", temp); | 197 | MKDEV(USB_MAJOR, minor), "%s", temp); |
199 | if (IS_ERR(intf->usb_dev)) { | 198 | if (IS_ERR(intf->usb_dev)) { |
200 | spin_lock (&minor_lock); | 199 | down_write(&minor_rwsem); |
201 | usb_minors[intf->minor] = NULL; | 200 | usb_minors[intf->minor] = NULL; |
202 | spin_unlock (&minor_lock); | 201 | up_write(&minor_rwsem); |
203 | retval = PTR_ERR(intf->usb_dev); | 202 | retval = PTR_ERR(intf->usb_dev); |
204 | } | 203 | } |
205 | exit: | 204 | exit: |
@@ -236,9 +235,9 @@ void usb_deregister_dev(struct usb_interface *intf, | |||
236 | 235 | ||
237 | dbg ("removing %d minor", intf->minor); | 236 | dbg ("removing %d minor", intf->minor); |
238 | 237 | ||
239 | spin_lock (&minor_lock); | 238 | down_write(&minor_rwsem); |
240 | usb_minors[intf->minor] = NULL; | 239 | usb_minors[intf->minor] = NULL; |
241 | spin_unlock (&minor_lock); | 240 | up_write(&minor_rwsem); |
242 | 241 | ||
243 | snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); | 242 | snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base); |
244 | device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); | 243 | device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); |
@@ -247,5 +246,3 @@ void usb_deregister_dev(struct usb_interface *intf, | |||
247 | destroy_usb_class(); | 246 | destroy_usb_class(); |
248 | } | 247 | } |
249 | EXPORT_SYMBOL(usb_deregister_dev); | 248 | EXPORT_SYMBOL(usb_deregister_dev); |
250 | |||
251 | |||
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 9bbcb20e2d94..b2fc2b115256 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/usb.h> | 20 | #include <linux/usb.h> |
21 | #include "usb.h" | 21 | #include "usb.h" |
22 | #include "hcd.h" | ||
22 | 23 | ||
23 | static inline const char *plural(int n) | 24 | static inline const char *plural(int n) |
24 | { | 25 | { |
@@ -193,16 +194,34 @@ static void generic_disconnect(struct usb_device *udev) | |||
193 | 194 | ||
194 | static int generic_suspend(struct usb_device *udev, pm_message_t msg) | 195 | static int generic_suspend(struct usb_device *udev, pm_message_t msg) |
195 | { | 196 | { |
196 | /* USB devices enter SUSPEND state through their hubs, but can be | 197 | int rc; |
197 | * marked for FREEZE as soon as their children are already idled. | 198 | |
198 | * But those semantics are useless, so we equate the two (sigh). | 199 | /* Normal USB devices suspend through their upstream port. |
200 | * Root hubs don't have upstream ports to suspend, | ||
201 | * so we have to shut down their downstream HC-to-USB | ||
202 | * interfaces manually by doing a bus (or "global") suspend. | ||
199 | */ | 203 | */ |
200 | return usb_port_suspend(udev); | 204 | if (!udev->parent) |
205 | rc = hcd_bus_suspend(udev); | ||
206 | else | ||
207 | rc = usb_port_suspend(udev); | ||
208 | return rc; | ||
201 | } | 209 | } |
202 | 210 | ||
203 | static int generic_resume(struct usb_device *udev) | 211 | static int generic_resume(struct usb_device *udev) |
204 | { | 212 | { |
205 | return usb_port_resume(udev); | 213 | int rc; |
214 | |||
215 | /* Normal USB devices resume/reset through their upstream port. | ||
216 | * Root hubs don't have upstream ports to resume or reset, | ||
217 | * so we have to start up their downstream HC-to-USB | ||
218 | * interfaces manually by doing a bus (or "global") resume. | ||
219 | */ | ||
220 | if (!udev->parent) | ||
221 | rc = hcd_bus_resume(udev); | ||
222 | else | ||
223 | rc = usb_port_resume(udev); | ||
224 | return rc; | ||
206 | } | 225 | } |
207 | 226 | ||
208 | #endif /* CONFIG_PM */ | 227 | #endif /* CONFIG_PM */ |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index edf4300a3f7a..5cf6d5f9acbd 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -207,7 +207,8 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t message) | |||
207 | * We must ignore the FREEZE vs SUSPEND distinction here, because | 207 | * We must ignore the FREEZE vs SUSPEND distinction here, because |
208 | * otherwise the swsusp will save (and restore) garbage state. | 208 | * otherwise the swsusp will save (and restore) garbage state. |
209 | */ | 209 | */ |
210 | if (hcd->self.root_hub->dev.power.power_state.event == PM_EVENT_ON) | 210 | if (!(hcd->state == HC_STATE_SUSPENDED || |
211 | hcd->state == HC_STATE_HALT)) | ||
211 | return -EBUSY; | 212 | return -EBUSY; |
212 | 213 | ||
213 | if (hcd->driver->suspend) { | 214 | if (hcd->driver->suspend) { |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 8969e42434b9..963520fbef90 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -582,10 +582,12 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) | |||
582 | } | 582 | } |
583 | 583 | ||
584 | /* The USB 2.0 spec says 256 ms. This is close enough and won't | 584 | /* The USB 2.0 spec says 256 ms. This is close enough and won't |
585 | * exceed that limit if HZ is 100. */ | 585 | * exceed that limit if HZ is 100. The math is more clunky than |
586 | * maybe expected, this is to make sure that all timers for USB devices | ||
587 | * fire at the same time to give the CPU a break inbetween */ | ||
586 | if (hcd->uses_new_polling ? hcd->poll_rh : | 588 | if (hcd->uses_new_polling ? hcd->poll_rh : |
587 | (length == 0 && hcd->status_urb != NULL)) | 589 | (length == 0 && hcd->status_urb != NULL)) |
588 | mod_timer (&hcd->rh_timer, jiffies + msecs_to_jiffies(250)); | 590 | mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); |
589 | } | 591 | } |
590 | EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status); | 592 | EXPORT_SYMBOL_GPL(usb_hcd_poll_rh_status); |
591 | 593 | ||
@@ -614,8 +616,8 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) | |||
614 | urb->hcpriv = hcd; /* indicate it's queued */ | 616 | urb->hcpriv = hcd; /* indicate it's queued */ |
615 | 617 | ||
616 | if (!hcd->uses_new_polling) | 618 | if (!hcd->uses_new_polling) |
617 | mod_timer (&hcd->rh_timer, jiffies + | 619 | mod_timer (&hcd->rh_timer, |
618 | msecs_to_jiffies(250)); | 620 | (jiffies/(HZ/4) + 1) * (HZ/4)); |
619 | 621 | ||
620 | /* If a status change has already occurred, report it ASAP */ | 622 | /* If a status change has already occurred, report it ASAP */ |
621 | else if (hcd->poll_pending) | 623 | else if (hcd->poll_pending) |
@@ -901,17 +903,32 @@ EXPORT_SYMBOL (usb_calc_bus_time); | |||
901 | 903 | ||
902 | /*-------------------------------------------------------------------------*/ | 904 | /*-------------------------------------------------------------------------*/ |
903 | 905 | ||
904 | static void urb_unlink (struct urb *urb) | 906 | static void urb_unlink(struct usb_hcd *hcd, struct urb *urb) |
905 | { | 907 | { |
906 | unsigned long flags; | 908 | unsigned long flags; |
909 | int at_root_hub = (urb->dev == hcd->self.root_hub); | ||
907 | 910 | ||
908 | /* clear all state linking urb to this dev (and hcd) */ | 911 | /* clear all state linking urb to this dev (and hcd) */ |
909 | |||
910 | spin_lock_irqsave (&hcd_data_lock, flags); | 912 | spin_lock_irqsave (&hcd_data_lock, flags); |
911 | list_del_init (&urb->urb_list); | 913 | list_del_init (&urb->urb_list); |
912 | spin_unlock_irqrestore (&hcd_data_lock, flags); | 914 | spin_unlock_irqrestore (&hcd_data_lock, flags); |
913 | } | ||
914 | 915 | ||
916 | if (hcd->self.uses_dma && !at_root_hub) { | ||
917 | if (usb_pipecontrol (urb->pipe) | ||
918 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | ||
919 | dma_unmap_single (hcd->self.controller, urb->setup_dma, | ||
920 | sizeof (struct usb_ctrlrequest), | ||
921 | DMA_TO_DEVICE); | ||
922 | if (urb->transfer_buffer_length != 0 | ||
923 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) | ||
924 | dma_unmap_single (hcd->self.controller, | ||
925 | urb->transfer_dma, | ||
926 | urb->transfer_buffer_length, | ||
927 | usb_pipein (urb->pipe) | ||
928 | ? DMA_FROM_DEVICE | ||
929 | : DMA_TO_DEVICE); | ||
930 | } | ||
931 | } | ||
915 | 932 | ||
916 | /* may be called in any context with a valid urb->dev usecount | 933 | /* may be called in any context with a valid urb->dev usecount |
917 | * caller surrenders "ownership" of urb | 934 | * caller surrenders "ownership" of urb |
@@ -948,19 +965,9 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | |||
948 | else switch (hcd->state) { | 965 | else switch (hcd->state) { |
949 | case HC_STATE_RUNNING: | 966 | case HC_STATE_RUNNING: |
950 | case HC_STATE_RESUMING: | 967 | case HC_STATE_RESUMING: |
951 | doit: | ||
952 | list_add_tail (&urb->urb_list, &ep->urb_list); | 968 | list_add_tail (&urb->urb_list, &ep->urb_list); |
953 | status = 0; | 969 | status = 0; |
954 | break; | 970 | break; |
955 | case HC_STATE_SUSPENDED: | ||
956 | /* HC upstream links (register access, wakeup signaling) can work | ||
957 | * even when the downstream links (and DMA etc) are quiesced; let | ||
958 | * usbcore talk to the root hub. | ||
959 | */ | ||
960 | if (hcd->self.controller->power.power_state.event == PM_EVENT_ON | ||
961 | && urb->dev->parent == NULL) | ||
962 | goto doit; | ||
963 | /* FALL THROUGH */ | ||
964 | default: | 971 | default: |
965 | status = -ESHUTDOWN; | 972 | status = -ESHUTDOWN; |
966 | break; | 973 | break; |
@@ -1014,7 +1021,7 @@ doit: | |||
1014 | status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags); | 1021 | status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags); |
1015 | done: | 1022 | done: |
1016 | if (unlikely (status)) { | 1023 | if (unlikely (status)) { |
1017 | urb_unlink (urb); | 1024 | urb_unlink(hcd, urb); |
1018 | atomic_dec (&urb->use_count); | 1025 | atomic_dec (&urb->use_count); |
1019 | if (urb->reject) | 1026 | if (urb->reject) |
1020 | wake_up (&usb_kill_urb_queue); | 1027 | wake_up (&usb_kill_urb_queue); |
@@ -1255,42 +1262,59 @@ rescan: | |||
1255 | 1262 | ||
1256 | #ifdef CONFIG_PM | 1263 | #ifdef CONFIG_PM |
1257 | 1264 | ||
1258 | int hcd_bus_suspend (struct usb_bus *bus) | 1265 | int hcd_bus_suspend(struct usb_device *rhdev) |
1259 | { | 1266 | { |
1260 | struct usb_hcd *hcd; | 1267 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); |
1261 | int status; | 1268 | int status; |
1269 | int old_state = hcd->state; | ||
1262 | 1270 | ||
1263 | hcd = container_of (bus, struct usb_hcd, self); | 1271 | dev_dbg(&rhdev->dev, "bus %s%s\n", |
1264 | if (!hcd->driver->bus_suspend) | 1272 | rhdev->auto_pm ? "auto-" : "", "suspend"); |
1265 | return -ENOENT; | 1273 | if (!hcd->driver->bus_suspend) { |
1266 | hcd->state = HC_STATE_QUIESCING; | 1274 | status = -ENOENT; |
1267 | status = hcd->driver->bus_suspend (hcd); | 1275 | } else { |
1268 | if (status == 0) | 1276 | hcd->state = HC_STATE_QUIESCING; |
1277 | status = hcd->driver->bus_suspend(hcd); | ||
1278 | } | ||
1279 | if (status == 0) { | ||
1280 | usb_set_device_state(rhdev, USB_STATE_SUSPENDED); | ||
1269 | hcd->state = HC_STATE_SUSPENDED; | 1281 | hcd->state = HC_STATE_SUSPENDED; |
1270 | else | 1282 | } else { |
1271 | dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n", | 1283 | hcd->state = old_state; |
1284 | dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", | ||
1272 | "suspend", status); | 1285 | "suspend", status); |
1286 | } | ||
1273 | return status; | 1287 | return status; |
1274 | } | 1288 | } |
1275 | 1289 | ||
1276 | int hcd_bus_resume (struct usb_bus *bus) | 1290 | int hcd_bus_resume(struct usb_device *rhdev) |
1277 | { | 1291 | { |
1278 | struct usb_hcd *hcd; | 1292 | struct usb_hcd *hcd = container_of(rhdev->bus, struct usb_hcd, self); |
1279 | int status; | 1293 | int status; |
1294 | int old_state = hcd->state; | ||
1280 | 1295 | ||
1281 | hcd = container_of (bus, struct usb_hcd, self); | 1296 | dev_dbg(&rhdev->dev, "usb %s%s\n", |
1297 | rhdev->auto_pm ? "auto-" : "", "resume"); | ||
1282 | if (!hcd->driver->bus_resume) | 1298 | if (!hcd->driver->bus_resume) |
1283 | return -ENOENT; | 1299 | return -ENOENT; |
1284 | if (hcd->state == HC_STATE_RUNNING) | 1300 | if (hcd->state == HC_STATE_RUNNING) |
1285 | return 0; | 1301 | return 0; |
1302 | |||
1286 | hcd->state = HC_STATE_RESUMING; | 1303 | hcd->state = HC_STATE_RESUMING; |
1287 | status = hcd->driver->bus_resume (hcd); | 1304 | status = hcd->driver->bus_resume(hcd); |
1288 | if (status == 0) | 1305 | if (status == 0) { |
1306 | /* TRSMRCY = 10 msec */ | ||
1307 | msleep(10); | ||
1308 | usb_set_device_state(rhdev, rhdev->actconfig | ||
1309 | ? USB_STATE_CONFIGURED | ||
1310 | : USB_STATE_ADDRESS); | ||
1289 | hcd->state = HC_STATE_RUNNING; | 1311 | hcd->state = HC_STATE_RUNNING; |
1290 | else { | 1312 | } else { |
1291 | dev_dbg(&bus->root_hub->dev, "%s fail, err %d\n", | 1313 | hcd->state = old_state; |
1314 | dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", | ||
1292 | "resume", status); | 1315 | "resume", status); |
1293 | usb_hc_died(hcd); | 1316 | if (status != -ESHUTDOWN) |
1317 | usb_hc_died(hcd); | ||
1294 | } | 1318 | } |
1295 | return status; | 1319 | return status; |
1296 | } | 1320 | } |
@@ -1384,30 +1408,10 @@ EXPORT_SYMBOL (usb_bus_start_enum); | |||
1384 | */ | 1408 | */ |
1385 | void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) | 1409 | void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb) |
1386 | { | 1410 | { |
1387 | int at_root_hub; | 1411 | urb_unlink(hcd, urb); |
1388 | |||
1389 | at_root_hub = (urb->dev == hcd->self.root_hub); | ||
1390 | urb_unlink (urb); | ||
1391 | |||
1392 | /* lower level hcd code should use *_dma exclusively if the | ||
1393 | * host controller does DMA */ | ||
1394 | if (hcd->self.uses_dma && !at_root_hub) { | ||
1395 | if (usb_pipecontrol (urb->pipe) | ||
1396 | && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) | ||
1397 | dma_unmap_single (hcd->self.controller, urb->setup_dma, | ||
1398 | sizeof (struct usb_ctrlrequest), | ||
1399 | DMA_TO_DEVICE); | ||
1400 | if (urb->transfer_buffer_length != 0 | ||
1401 | && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) | ||
1402 | dma_unmap_single (hcd->self.controller, | ||
1403 | urb->transfer_dma, | ||
1404 | urb->transfer_buffer_length, | ||
1405 | usb_pipein (urb->pipe) | ||
1406 | ? DMA_FROM_DEVICE | ||
1407 | : DMA_TO_DEVICE); | ||
1408 | } | ||
1409 | |||
1410 | usbmon_urb_complete (&hcd->self, urb); | 1412 | usbmon_urb_complete (&hcd->self, urb); |
1413 | usb_unanchor_urb(urb); | ||
1414 | |||
1411 | /* pass ownership to the completion handler */ | 1415 | /* pass ownership to the completion handler */ |
1412 | urb->complete (urb); | 1416 | urb->complete (urb); |
1413 | atomic_dec (&urb->use_count); | 1417 | atomic_dec (&urb->use_count); |
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index ef50fa494e47..b5ebb73c2332 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -364,23 +364,13 @@ extern int usb_find_interface_driver (struct usb_device *dev, | |||
364 | #ifdef CONFIG_PM | 364 | #ifdef CONFIG_PM |
365 | extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); | 365 | extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); |
366 | extern void usb_root_hub_lost_power (struct usb_device *rhdev); | 366 | extern void usb_root_hub_lost_power (struct usb_device *rhdev); |
367 | extern int hcd_bus_suspend (struct usb_bus *bus); | 367 | extern int hcd_bus_suspend(struct usb_device *rhdev); |
368 | extern int hcd_bus_resume (struct usb_bus *bus); | 368 | extern int hcd_bus_resume(struct usb_device *rhdev); |
369 | #else | 369 | #else |
370 | static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) | 370 | static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) |
371 | { | 371 | { |
372 | return; | 372 | return; |
373 | } | 373 | } |
374 | |||
375 | static inline int hcd_bus_suspend(struct usb_bus *bus) | ||
376 | { | ||
377 | return 0; | ||
378 | } | ||
379 | |||
380 | static inline int hcd_bus_resume (struct usb_bus *bus) | ||
381 | { | ||
382 | return 0; | ||
383 | } | ||
384 | #endif /* CONFIG_PM */ | 374 | #endif /* CONFIG_PM */ |
385 | 375 | ||
386 | /* | 376 | /* |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a9cf8b30bccc..50e79010401c 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -31,9 +31,16 @@ | |||
31 | #include "hcd.h" | 31 | #include "hcd.h" |
32 | #include "hub.h" | 32 | #include "hub.h" |
33 | 33 | ||
34 | #ifdef CONFIG_USB_PERSIST | ||
35 | #define USB_PERSIST 1 | ||
36 | #else | ||
37 | #define USB_PERSIST 0 | ||
38 | #endif | ||
39 | |||
34 | struct usb_hub { | 40 | struct usb_hub { |
35 | struct device *intfdev; /* the "interface" device */ | 41 | struct device *intfdev; /* the "interface" device */ |
36 | struct usb_device *hdev; | 42 | struct usb_device *hdev; |
43 | struct kref kref; | ||
37 | struct urb *urb; /* for interrupt polling pipe */ | 44 | struct urb *urb; /* for interrupt polling pipe */ |
38 | 45 | ||
39 | /* buffer for urb ... with extra space in case of babble */ | 46 | /* buffer for urb ... with extra space in case of babble */ |
@@ -66,6 +73,7 @@ struct usb_hub { | |||
66 | unsigned limited_power:1; | 73 | unsigned limited_power:1; |
67 | unsigned quiescing:1; | 74 | unsigned quiescing:1; |
68 | unsigned activating:1; | 75 | unsigned activating:1; |
76 | unsigned disconnected:1; | ||
69 | 77 | ||
70 | unsigned has_indicators:1; | 78 | unsigned has_indicators:1; |
71 | u8 indicator[USB_MAXCHILDREN]; | 79 | u8 indicator[USB_MAXCHILDREN]; |
@@ -321,7 +329,7 @@ static void kick_khubd(struct usb_hub *hub) | |||
321 | to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; | 329 | to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; |
322 | 330 | ||
323 | spin_lock_irqsave(&hub_event_lock, flags); | 331 | spin_lock_irqsave(&hub_event_lock, flags); |
324 | if (list_empty(&hub->event_list)) { | 332 | if (!hub->disconnected & list_empty(&hub->event_list)) { |
325 | list_add_tail(&hub->event_list, &hub_event_list); | 333 | list_add_tail(&hub->event_list, &hub_event_list); |
326 | wake_up(&khubd_wait); | 334 | wake_up(&khubd_wait); |
327 | } | 335 | } |
@@ -330,6 +338,7 @@ static void kick_khubd(struct usb_hub *hub) | |||
330 | 338 | ||
331 | void usb_kick_khubd(struct usb_device *hdev) | 339 | void usb_kick_khubd(struct usb_device *hdev) |
332 | { | 340 | { |
341 | /* FIXME: What if hdev isn't bound to the hub driver? */ | ||
333 | kick_khubd(hdev_to_hub(hdev)); | 342 | kick_khubd(hdev_to_hub(hdev)); |
334 | } | 343 | } |
335 | 344 | ||
@@ -400,9 +409,10 @@ static void hub_tt_kevent (struct work_struct *work) | |||
400 | struct usb_hub *hub = | 409 | struct usb_hub *hub = |
401 | container_of(work, struct usb_hub, tt.kevent); | 410 | container_of(work, struct usb_hub, tt.kevent); |
402 | unsigned long flags; | 411 | unsigned long flags; |
412 | int limit = 100; | ||
403 | 413 | ||
404 | spin_lock_irqsave (&hub->tt.lock, flags); | 414 | spin_lock_irqsave (&hub->tt.lock, flags); |
405 | while (!list_empty (&hub->tt.clear_list)) { | 415 | while (--limit && !list_empty (&hub->tt.clear_list)) { |
406 | struct list_head *temp; | 416 | struct list_head *temp; |
407 | struct usb_tt_clear *clear; | 417 | struct usb_tt_clear *clear; |
408 | struct usb_device *hdev = hub->hdev; | 418 | struct usb_device *hdev = hub->hdev; |
@@ -550,48 +560,68 @@ static int hub_hub_status(struct usb_hub *hub, | |||
550 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | 560 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) |
551 | { | 561 | { |
552 | struct usb_device *hdev = hub->hdev; | 562 | struct usb_device *hdev = hub->hdev; |
553 | int ret; | 563 | int ret = 0; |
554 | 564 | ||
555 | if (hdev->children[port1-1] && set_state) { | 565 | if (hdev->children[port1-1] && set_state) |
556 | usb_set_device_state(hdev->children[port1-1], | 566 | usb_set_device_state(hdev->children[port1-1], |
557 | USB_STATE_NOTATTACHED); | 567 | USB_STATE_NOTATTACHED); |
558 | } | 568 | if (!hub->error) |
559 | ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); | 569 | ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); |
560 | if (ret) | 570 | if (ret) |
561 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", | 571 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", |
562 | port1, ret); | 572 | port1, ret); |
563 | |||
564 | return ret; | 573 | return ret; |
565 | } | 574 | } |
566 | 575 | ||
576 | /* | ||
577 | * Disable a port and mark a logical connnect-change event, so that some | ||
578 | * time later khubd will disconnect() any existing usb_device on the port | ||
579 | * and will re-enumerate if there actually is a device attached. | ||
580 | */ | ||
581 | static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) | ||
582 | { | ||
583 | dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1); | ||
584 | hub_port_disable(hub, port1, 1); | ||
585 | |||
586 | /* FIXME let caller ask to power down the port: | ||
587 | * - some devices won't enumerate without a VBUS power cycle | ||
588 | * - SRP saves power that way | ||
589 | * - ... new call, TBD ... | ||
590 | * That's easy if this hub can switch power per-port, and | ||
591 | * khubd reactivates the port later (timer, SRP, etc). | ||
592 | * Powerdown must be optional, because of reset/DFU. | ||
593 | */ | ||
594 | |||
595 | set_bit(port1, hub->change_bits); | ||
596 | kick_khubd(hub); | ||
597 | } | ||
567 | 598 | ||
568 | /* caller has locked the hub device */ | 599 | /* caller has locked the hub device */ |
569 | static void hub_pre_reset(struct usb_interface *intf) | 600 | static int hub_pre_reset(struct usb_interface *intf) |
570 | { | 601 | { |
571 | struct usb_hub *hub = usb_get_intfdata(intf); | 602 | struct usb_hub *hub = usb_get_intfdata(intf); |
572 | struct usb_device *hdev = hub->hdev; | 603 | struct usb_device *hdev = hub->hdev; |
573 | int port1; | 604 | int i; |
574 | 605 | ||
575 | for (port1 = 1; port1 <= hdev->maxchild; ++port1) { | 606 | /* Disconnect all the children */ |
576 | if (hdev->children[port1 - 1]) { | 607 | for (i = 0; i < hdev->maxchild; ++i) { |
577 | usb_disconnect(&hdev->children[port1 - 1]); | 608 | if (hdev->children[i]) |
578 | if (hub->error == 0) | 609 | usb_disconnect(&hdev->children[i]); |
579 | hub_port_disable(hub, port1, 0); | ||
580 | } | ||
581 | } | 610 | } |
582 | hub_quiesce(hub); | 611 | hub_quiesce(hub); |
612 | return 0; | ||
583 | } | 613 | } |
584 | 614 | ||
585 | /* caller has locked the hub device */ | 615 | /* caller has locked the hub device */ |
586 | static void hub_post_reset(struct usb_interface *intf) | 616 | static int hub_post_reset(struct usb_interface *intf) |
587 | { | 617 | { |
588 | struct usb_hub *hub = usb_get_intfdata(intf); | 618 | struct usb_hub *hub = usb_get_intfdata(intf); |
589 | 619 | ||
590 | hub_activate(hub); | ||
591 | hub_power_on(hub); | 620 | hub_power_on(hub); |
621 | hub_activate(hub); | ||
622 | return 0; | ||
592 | } | 623 | } |
593 | 624 | ||
594 | |||
595 | static int hub_configure(struct usb_hub *hub, | 625 | static int hub_configure(struct usb_hub *hub, |
596 | struct usb_endpoint_descriptor *endpoint) | 626 | struct usb_endpoint_descriptor *endpoint) |
597 | { | 627 | { |
@@ -845,43 +875,42 @@ fail: | |||
845 | return ret; | 875 | return ret; |
846 | } | 876 | } |
847 | 877 | ||
878 | static void hub_release(struct kref *kref) | ||
879 | { | ||
880 | struct usb_hub *hub = container_of(kref, struct usb_hub, kref); | ||
881 | |||
882 | usb_put_intf(to_usb_interface(hub->intfdev)); | ||
883 | kfree(hub); | ||
884 | } | ||
885 | |||
848 | static unsigned highspeed_hubs; | 886 | static unsigned highspeed_hubs; |
849 | 887 | ||
850 | static void hub_disconnect(struct usb_interface *intf) | 888 | static void hub_disconnect(struct usb_interface *intf) |
851 | { | 889 | { |
852 | struct usb_hub *hub = usb_get_intfdata (intf); | 890 | struct usb_hub *hub = usb_get_intfdata (intf); |
853 | struct usb_device *hdev; | 891 | |
892 | /* Take the hub off the event list and don't let it be added again */ | ||
893 | spin_lock_irq(&hub_event_lock); | ||
894 | list_del_init(&hub->event_list); | ||
895 | hub->disconnected = 1; | ||
896 | spin_unlock_irq(&hub_event_lock); | ||
854 | 897 | ||
855 | /* Disconnect all children and quiesce the hub */ | 898 | /* Disconnect all children and quiesce the hub */ |
856 | hub->error = 0; | 899 | hub->error = 0; |
857 | hub_pre_reset(intf); | 900 | hub_pre_reset(intf); |
858 | 901 | ||
859 | usb_set_intfdata (intf, NULL); | 902 | usb_set_intfdata (intf, NULL); |
860 | hdev = hub->hdev; | ||
861 | 903 | ||
862 | if (hdev->speed == USB_SPEED_HIGH) | 904 | if (hub->hdev->speed == USB_SPEED_HIGH) |
863 | highspeed_hubs--; | 905 | highspeed_hubs--; |
864 | 906 | ||
865 | usb_free_urb(hub->urb); | 907 | usb_free_urb(hub->urb); |
866 | hub->urb = NULL; | ||
867 | |||
868 | spin_lock_irq(&hub_event_lock); | ||
869 | list_del_init(&hub->event_list); | ||
870 | spin_unlock_irq(&hub_event_lock); | ||
871 | |||
872 | kfree(hub->descriptor); | 908 | kfree(hub->descriptor); |
873 | hub->descriptor = NULL; | ||
874 | |||
875 | kfree(hub->status); | 909 | kfree(hub->status); |
876 | hub->status = NULL; | 910 | usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer, |
877 | 911 | hub->buffer_dma); | |
878 | if (hub->buffer) { | ||
879 | usb_buffer_free(hdev, sizeof(*hub->buffer), hub->buffer, | ||
880 | hub->buffer_dma); | ||
881 | hub->buffer = NULL; | ||
882 | } | ||
883 | 912 | ||
884 | kfree(hub); | 913 | kref_put(&hub->kref, hub_release); |
885 | } | 914 | } |
886 | 915 | ||
887 | static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) | 916 | static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) |
@@ -929,10 +958,12 @@ descriptor_error: | |||
929 | return -ENOMEM; | 958 | return -ENOMEM; |
930 | } | 959 | } |
931 | 960 | ||
961 | kref_init(&hub->kref); | ||
932 | INIT_LIST_HEAD(&hub->event_list); | 962 | INIT_LIST_HEAD(&hub->event_list); |
933 | hub->intfdev = &intf->dev; | 963 | hub->intfdev = &intf->dev; |
934 | hub->hdev = hdev; | 964 | hub->hdev = hdev; |
935 | INIT_DELAYED_WORK(&hub->leds, led_work); | 965 | INIT_DELAYED_WORK(&hub->leds, led_work); |
966 | usb_get_intf(intf); | ||
936 | 967 | ||
937 | usb_set_intfdata (intf, hub); | 968 | usb_set_intfdata (intf, hub); |
938 | intf->needs_remote_wakeup = 1; | 969 | intf->needs_remote_wakeup = 1; |
@@ -982,49 +1013,6 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) | |||
982 | } | 1013 | } |
983 | 1014 | ||
984 | 1015 | ||
985 | /* grab device/port lock, returning index of that port (zero based). | ||
986 | * protects the upstream link used by this device from concurrent | ||
987 | * tree operations like suspend, resume, reset, and disconnect, which | ||
988 | * apply to everything downstream of a given port. | ||
989 | */ | ||
990 | static int locktree(struct usb_device *udev) | ||
991 | { | ||
992 | int t; | ||
993 | struct usb_device *hdev; | ||
994 | |||
995 | if (!udev) | ||
996 | return -ENODEV; | ||
997 | |||
998 | /* root hub is always the first lock in the series */ | ||
999 | hdev = udev->parent; | ||
1000 | if (!hdev) { | ||
1001 | usb_lock_device(udev); | ||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
1005 | /* on the path from root to us, lock everything from | ||
1006 | * top down, dropping parent locks when not needed | ||
1007 | */ | ||
1008 | t = locktree(hdev); | ||
1009 | if (t < 0) | ||
1010 | return t; | ||
1011 | |||
1012 | /* everything is fail-fast once disconnect | ||
1013 | * processing starts | ||
1014 | */ | ||
1015 | if (udev->state == USB_STATE_NOTATTACHED) { | ||
1016 | usb_unlock_device(hdev); | ||
1017 | return -ENODEV; | ||
1018 | } | ||
1019 | |||
1020 | /* when everyone grabs locks top->bottom, | ||
1021 | * non-overlapping work may be concurrent | ||
1022 | */ | ||
1023 | usb_lock_device(udev); | ||
1024 | usb_unlock_device(hdev); | ||
1025 | return udev->portnum; | ||
1026 | } | ||
1027 | |||
1028 | static void recursively_mark_NOTATTACHED(struct usb_device *udev) | 1016 | static void recursively_mark_NOTATTACHED(struct usb_device *udev) |
1029 | { | 1017 | { |
1030 | int i; | 1018 | int i; |
@@ -1089,41 +1077,6 @@ void usb_set_device_state(struct usb_device *udev, | |||
1089 | spin_unlock_irqrestore(&device_state_lock, flags); | 1077 | spin_unlock_irqrestore(&device_state_lock, flags); |
1090 | } | 1078 | } |
1091 | 1079 | ||
1092 | |||
1093 | #ifdef CONFIG_PM | ||
1094 | |||
1095 | /** | ||
1096 | * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power | ||
1097 | * @rhdev: struct usb_device for the root hub | ||
1098 | * | ||
1099 | * The USB host controller driver calls this function when its root hub | ||
1100 | * is resumed and Vbus power has been interrupted or the controller | ||
1101 | * has been reset. The routine marks all the children of the root hub | ||
1102 | * as NOTATTACHED and marks logical connect-change events on their ports. | ||
1103 | */ | ||
1104 | void usb_root_hub_lost_power(struct usb_device *rhdev) | ||
1105 | { | ||
1106 | struct usb_hub *hub; | ||
1107 | int port1; | ||
1108 | unsigned long flags; | ||
1109 | |||
1110 | dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); | ||
1111 | |||
1112 | spin_lock_irqsave(&device_state_lock, flags); | ||
1113 | hub = hdev_to_hub(rhdev); | ||
1114 | for (port1 = 1; port1 <= rhdev->maxchild; ++port1) { | ||
1115 | if (rhdev->children[port1 - 1]) { | ||
1116 | recursively_mark_NOTATTACHED( | ||
1117 | rhdev->children[port1 - 1]); | ||
1118 | set_bit(port1, hub->change_bits); | ||
1119 | } | ||
1120 | } | ||
1121 | spin_unlock_irqrestore(&device_state_lock, flags); | ||
1122 | } | ||
1123 | EXPORT_SYMBOL_GPL(usb_root_hub_lost_power); | ||
1124 | |||
1125 | #endif /* CONFIG_PM */ | ||
1126 | |||
1127 | static void choose_address(struct usb_device *udev) | 1080 | static void choose_address(struct usb_device *udev) |
1128 | { | 1081 | { |
1129 | int devnum; | 1082 | int devnum; |
@@ -1264,7 +1217,6 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) | |||
1264 | 1217 | ||
1265 | #ifdef CONFIG_USB_OTG | 1218 | #ifdef CONFIG_USB_OTG |
1266 | #include "otg_whitelist.h" | 1219 | #include "otg_whitelist.h" |
1267 | static int __usb_port_suspend(struct usb_device *, int port1); | ||
1268 | #endif | 1220 | #endif |
1269 | 1221 | ||
1270 | /** | 1222 | /** |
@@ -1370,11 +1322,11 @@ int usb_new_device(struct usb_device *udev) | |||
1370 | * (Includes HNP test device.) | 1322 | * (Includes HNP test device.) |
1371 | */ | 1323 | */ |
1372 | if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { | 1324 | if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { |
1373 | err = __usb_port_suspend(udev, udev->bus->otg_port); | 1325 | err = usb_port_suspend(udev); |
1374 | if (err < 0) | 1326 | if (err < 0) |
1375 | dev_dbg(&udev->dev, "HNP fail, %d\n", err); | 1327 | dev_dbg(&udev->dev, "HNP fail, %d\n", err); |
1376 | } | 1328 | } |
1377 | err = -ENODEV; | 1329 | err = -ENOTSUPP; |
1378 | goto fail; | 1330 | goto fail; |
1379 | } | 1331 | } |
1380 | #endif | 1332 | #endif |
@@ -1471,9 +1423,9 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
1471 | if (!(portstatus & USB_PORT_STAT_CONNECTION)) | 1423 | if (!(portstatus & USB_PORT_STAT_CONNECTION)) |
1472 | return -ENOTCONN; | 1424 | return -ENOTCONN; |
1473 | 1425 | ||
1474 | /* bomb out completely if something weird happened */ | 1426 | /* bomb out completely if the connection bounced */ |
1475 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) | 1427 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) |
1476 | return -EINVAL; | 1428 | return -ENOTCONN; |
1477 | 1429 | ||
1478 | /* if we`ve finished resetting, then break out of the loop */ | 1430 | /* if we`ve finished resetting, then break out of the loop */ |
1479 | if (!(portstatus & USB_PORT_STAT_RESET) && | 1431 | if (!(portstatus & USB_PORT_STAT_RESET) && |
@@ -1552,34 +1504,24 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
1552 | return status; | 1504 | return status; |
1553 | } | 1505 | } |
1554 | 1506 | ||
1555 | /* | ||
1556 | * Disable a port and mark a logical connnect-change event, so that some | ||
1557 | * time later khubd will disconnect() any existing usb_device on the port | ||
1558 | * and will re-enumerate if there actually is a device attached. | ||
1559 | */ | ||
1560 | static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) | ||
1561 | { | ||
1562 | dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1); | ||
1563 | hub_port_disable(hub, port1, 1); | ||
1564 | |||
1565 | /* FIXME let caller ask to power down the port: | ||
1566 | * - some devices won't enumerate without a VBUS power cycle | ||
1567 | * - SRP saves power that way | ||
1568 | * - ... new call, TBD ... | ||
1569 | * That's easy if this hub can switch power per-port, and | ||
1570 | * khubd reactivates the port later (timer, SRP, etc). | ||
1571 | * Powerdown must be optional, because of reset/DFU. | ||
1572 | */ | ||
1573 | |||
1574 | set_bit(port1, hub->change_bits); | ||
1575 | kick_khubd(hub); | ||
1576 | } | ||
1577 | |||
1578 | #ifdef CONFIG_PM | 1507 | #ifdef CONFIG_PM |
1579 | 1508 | ||
1580 | #ifdef CONFIG_USB_SUSPEND | 1509 | #ifdef CONFIG_USB_SUSPEND |
1581 | 1510 | ||
1582 | /* | 1511 | /* |
1512 | * usb_port_suspend - suspend a usb device's upstream port | ||
1513 | * @udev: device that's no longer in active use, not a root hub | ||
1514 | * Context: must be able to sleep; device not locked; pm locks held | ||
1515 | * | ||
1516 | * Suspends a USB device that isn't in active use, conserving power. | ||
1517 | * Devices may wake out of a suspend, if anything important happens, | ||
1518 | * using the remote wakeup mechanism. They may also be taken out of | ||
1519 | * suspend by the host, using usb_port_resume(). It's also routine | ||
1520 | * to disconnect devices while they are suspended. | ||
1521 | * | ||
1522 | * This only affects the USB hardware for a device; its interfaces | ||
1523 | * (and, for hubs, child devices) must already have been suspended. | ||
1524 | * | ||
1583 | * Selective port suspend reduces power; most suspended devices draw | 1525 | * Selective port suspend reduces power; most suspended devices draw |
1584 | * less than 500 uA. It's also used in OTG, along with remote wakeup. | 1526 | * less than 500 uA. It's also used in OTG, along with remote wakeup. |
1585 | * All devices below the suspended port are also suspended. | 1527 | * All devices below the suspended port are also suspended. |
@@ -1588,11 +1530,35 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) | |||
1588 | * also support "remote wakeup", where the device can activate the USB | 1530 | * also support "remote wakeup", where the device can activate the USB |
1589 | * tree above them to deliver data, such as a keypress or packet. In | 1531 | * tree above them to deliver data, such as a keypress or packet. In |
1590 | * some cases, this wakes the USB host. | 1532 | * some cases, this wakes the USB host. |
1533 | * | ||
1534 | * Suspending OTG devices may trigger HNP, if that's been enabled | ||
1535 | * between a pair of dual-role devices. That will change roles, such | ||
1536 | * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral. | ||
1537 | * | ||
1538 | * Devices on USB hub ports have only one "suspend" state, corresponding | ||
1539 | * to ACPI D2, "may cause the device to lose some context". | ||
1540 | * State transitions include: | ||
1541 | * | ||
1542 | * - suspend, resume ... when the VBUS power link stays live | ||
1543 | * - suspend, disconnect ... VBUS lost | ||
1544 | * | ||
1545 | * Once VBUS drop breaks the circuit, the port it's using has to go through | ||
1546 | * normal re-enumeration procedures, starting with enabling VBUS power. | ||
1547 | * Other than re-initializing the hub (plug/unplug, except for root hubs), | ||
1548 | * Linux (2.6) currently has NO mechanisms to initiate that: no khubd | ||
1549 | * timer, no SRP, no requests through sysfs. | ||
1550 | * | ||
1551 | * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when | ||
1552 | * the root hub for their bus goes into global suspend ... so we don't | ||
1553 | * (falsely) update the device power state to say it suspended. | ||
1554 | * | ||
1555 | * Returns 0 on success, else negative errno. | ||
1591 | */ | 1556 | */ |
1592 | static int hub_port_suspend(struct usb_hub *hub, int port1, | 1557 | int usb_port_suspend(struct usb_device *udev) |
1593 | struct usb_device *udev) | ||
1594 | { | 1558 | { |
1595 | int status; | 1559 | struct usb_hub *hub = hdev_to_hub(udev->parent); |
1560 | int port1 = udev->portnum; | ||
1561 | int status; | ||
1596 | 1562 | ||
1597 | // dev_dbg(hub->intfdev, "suspend port %d\n", port1); | 1563 | // dev_dbg(hub->intfdev, "suspend port %d\n", port1); |
1598 | 1564 | ||
@@ -1609,17 +1575,15 @@ static int hub_port_suspend(struct usb_hub *hub, int port1, | |||
1609 | NULL, 0, | 1575 | NULL, 0, |
1610 | USB_CTRL_SET_TIMEOUT); | 1576 | USB_CTRL_SET_TIMEOUT); |
1611 | if (status) | 1577 | if (status) |
1612 | dev_dbg(&udev->dev, | 1578 | dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", |
1613 | "won't remote wakeup, status %d\n", | 1579 | status); |
1614 | status); | ||
1615 | } | 1580 | } |
1616 | 1581 | ||
1617 | /* see 7.1.7.6 */ | 1582 | /* see 7.1.7.6 */ |
1618 | status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND); | 1583 | status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND); |
1619 | if (status) { | 1584 | if (status) { |
1620 | dev_dbg(hub->intfdev, | 1585 | dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", |
1621 | "can't suspend port %d, status %d\n", | 1586 | port1, status); |
1622 | port1, status); | ||
1623 | /* paranoia: "should not happen" */ | 1587 | /* paranoia: "should not happen" */ |
1624 | (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 1588 | (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), |
1625 | USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, | 1589 | USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, |
@@ -1637,85 +1601,24 @@ static int hub_port_suspend(struct usb_hub *hub, int port1, | |||
1637 | } | 1601 | } |
1638 | 1602 | ||
1639 | /* | 1603 | /* |
1640 | * Devices on USB hub ports have only one "suspend" state, corresponding | ||
1641 | * to ACPI D2, "may cause the device to lose some context". | ||
1642 | * State transitions include: | ||
1643 | * | ||
1644 | * - suspend, resume ... when the VBUS power link stays live | ||
1645 | * - suspend, disconnect ... VBUS lost | ||
1646 | * | ||
1647 | * Once VBUS drop breaks the circuit, the port it's using has to go through | ||
1648 | * normal re-enumeration procedures, starting with enabling VBUS power. | ||
1649 | * Other than re-initializing the hub (plug/unplug, except for root hubs), | ||
1650 | * Linux (2.6) currently has NO mechanisms to initiate that: no khubd | ||
1651 | * timer, no SRP, no requests through sysfs. | ||
1652 | * | ||
1653 | * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when | ||
1654 | * the root hub for their bus goes into global suspend ... so we don't | ||
1655 | * (falsely) update the device power state to say it suspended. | ||
1656 | */ | ||
1657 | static int __usb_port_suspend (struct usb_device *udev, int port1) | ||
1658 | { | ||
1659 | int status = 0; | ||
1660 | |||
1661 | /* caller owns the udev device lock */ | ||
1662 | if (port1 < 0) | ||
1663 | return port1; | ||
1664 | |||
1665 | /* we change the device's upstream USB link, | ||
1666 | * but root hubs have no upstream USB link. | ||
1667 | */ | ||
1668 | if (udev->parent) | ||
1669 | status = hub_port_suspend(hdev_to_hub(udev->parent), port1, | ||
1670 | udev); | ||
1671 | else { | ||
1672 | dev_dbg(&udev->dev, "usb %ssuspend\n", | ||
1673 | udev->auto_pm ? "auto-" : ""); | ||
1674 | usb_set_device_state(udev, USB_STATE_SUSPENDED); | ||
1675 | } | ||
1676 | return status; | ||
1677 | } | ||
1678 | |||
1679 | /* | ||
1680 | * usb_port_suspend - suspend a usb device's upstream port | ||
1681 | * @udev: device that's no longer in active use | ||
1682 | * Context: must be able to sleep; device not locked; pm locks held | ||
1683 | * | ||
1684 | * Suspends a USB device that isn't in active use, conserving power. | ||
1685 | * Devices may wake out of a suspend, if anything important happens, | ||
1686 | * using the remote wakeup mechanism. They may also be taken out of | ||
1687 | * suspend by the host, using usb_port_resume(). It's also routine | ||
1688 | * to disconnect devices while they are suspended. | ||
1689 | * | ||
1690 | * This only affects the USB hardware for a device; its interfaces | ||
1691 | * (and, for hubs, child devices) must already have been suspended. | ||
1692 | * | ||
1693 | * Suspending OTG devices may trigger HNP, if that's been enabled | ||
1694 | * between a pair of dual-role devices. That will change roles, such | ||
1695 | * as from A-Host to A-Peripheral or from B-Host back to B-Peripheral. | ||
1696 | * | ||
1697 | * Returns 0 on success, else negative errno. | ||
1698 | */ | ||
1699 | int usb_port_suspend(struct usb_device *udev) | ||
1700 | { | ||
1701 | return __usb_port_suspend(udev, udev->portnum); | ||
1702 | } | ||
1703 | |||
1704 | /* | ||
1705 | * If the USB "suspend" state is in use (rather than "global suspend"), | 1604 | * If the USB "suspend" state is in use (rather than "global suspend"), |
1706 | * many devices will be individually taken out of suspend state using | 1605 | * many devices will be individually taken out of suspend state using |
1707 | * special" resume" signaling. These routines kick in shortly after | 1606 | * special "resume" signaling. This routine kicks in shortly after |
1708 | * hardware resume signaling is finished, either because of selective | 1607 | * hardware resume signaling is finished, either because of selective |
1709 | * resume (by host) or remote wakeup (by device) ... now see what changed | 1608 | * resume (by host) or remote wakeup (by device) ... now see what changed |
1710 | * in the tree that's rooted at this device. | 1609 | * in the tree that's rooted at this device. |
1610 | * | ||
1611 | * If @udev->reset_resume is set then the device is reset before the | ||
1612 | * status check is done. | ||
1711 | */ | 1613 | */ |
1712 | static int finish_port_resume(struct usb_device *udev) | 1614 | static int finish_port_resume(struct usb_device *udev) |
1713 | { | 1615 | { |
1714 | int status; | 1616 | int status = 0; |
1715 | u16 devstatus; | 1617 | u16 devstatus; |
1716 | 1618 | ||
1717 | /* caller owns the udev device lock */ | 1619 | /* caller owns the udev device lock */ |
1718 | dev_dbg(&udev->dev, "finish resume\n"); | 1620 | dev_dbg(&udev->dev, "finish %sresume\n", |
1621 | udev->reset_resume ? "reset-" : ""); | ||
1719 | 1622 | ||
1720 | /* usb ch9 identifies four variants of SUSPENDED, based on what | 1623 | /* usb ch9 identifies four variants of SUSPENDED, based on what |
1721 | * state the device resumes to. Linux currently won't see the | 1624 | * state the device resumes to. Linux currently won't see the |
@@ -1726,22 +1629,30 @@ static int finish_port_resume(struct usb_device *udev) | |||
1726 | ? USB_STATE_CONFIGURED | 1629 | ? USB_STATE_CONFIGURED |
1727 | : USB_STATE_ADDRESS); | 1630 | : USB_STATE_ADDRESS); |
1728 | 1631 | ||
1632 | /* 10.5.4.5 says not to reset a suspended port if the attached | ||
1633 | * device is enabled for remote wakeup. Hence the reset | ||
1634 | * operation is carried out here, after the port has been | ||
1635 | * resumed. | ||
1636 | */ | ||
1637 | if (udev->reset_resume) | ||
1638 | status = usb_reset_device(udev); | ||
1639 | |||
1729 | /* 10.5.4.5 says be sure devices in the tree are still there. | 1640 | /* 10.5.4.5 says be sure devices in the tree are still there. |
1730 | * For now let's assume the device didn't go crazy on resume, | 1641 | * For now let's assume the device didn't go crazy on resume, |
1731 | * and device drivers will know about any resume quirks. | 1642 | * and device drivers will know about any resume quirks. |
1732 | */ | 1643 | */ |
1733 | status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); | 1644 | if (status == 0) { |
1734 | if (status >= 0) | 1645 | status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); |
1735 | status = (status == 2 ? 0 : -ENODEV); | 1646 | if (status >= 0) |
1647 | status = (status == 2 ? 0 : -ENODEV); | ||
1648 | } | ||
1736 | 1649 | ||
1737 | if (status) | 1650 | if (status) { |
1738 | dev_dbg(&udev->dev, | 1651 | dev_dbg(&udev->dev, "gone after usb resume? status %d\n", |
1739 | "gone after usb resume? status %d\n", | 1652 | status); |
1740 | status); | 1653 | } else if (udev->actconfig) { |
1741 | else if (udev->actconfig) { | ||
1742 | le16_to_cpus(&devstatus); | 1654 | le16_to_cpus(&devstatus); |
1743 | if ((devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) | 1655 | if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { |
1744 | && udev->parent) { | ||
1745 | status = usb_control_msg(udev, | 1656 | status = usb_control_msg(udev, |
1746 | usb_sndctrlpipe(udev, 0), | 1657 | usb_sndctrlpipe(udev, 0), |
1747 | USB_REQ_CLEAR_FEATURE, | 1658 | USB_REQ_CLEAR_FEATURE, |
@@ -1754,19 +1665,52 @@ static int finish_port_resume(struct usb_device *udev) | |||
1754 | "wakeup, status %d\n", status); | 1665 | "wakeup, status %d\n", status); |
1755 | } | 1666 | } |
1756 | status = 0; | 1667 | status = 0; |
1757 | |||
1758 | } else if (udev->devnum <= 0) { | ||
1759 | dev_dbg(&udev->dev, "bogus resume!\n"); | ||
1760 | status = -EINVAL; | ||
1761 | } | 1668 | } |
1762 | return status; | 1669 | return status; |
1763 | } | 1670 | } |
1764 | 1671 | ||
1765 | static int | 1672 | /* |
1766 | hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) | 1673 | * usb_port_resume - re-activate a suspended usb device's upstream port |
1674 | * @udev: device to re-activate, not a root hub | ||
1675 | * Context: must be able to sleep; device not locked; pm locks held | ||
1676 | * | ||
1677 | * This will re-activate the suspended device, increasing power usage | ||
1678 | * while letting drivers communicate again with its endpoints. | ||
1679 | * USB resume explicitly guarantees that the power session between | ||
1680 | * the host and the device is the same as it was when the device | ||
1681 | * suspended. | ||
1682 | * | ||
1683 | * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this | ||
1684 | * routine won't check that the port is still enabled. Furthermore, | ||
1685 | * if @udev->reset_resume is set then finish_port_resume() above will | ||
1686 | * reset @udev. The end result is that a broken power session can be | ||
1687 | * recovered and @udev will appear to persist across a loss of VBUS power. | ||
1688 | * | ||
1689 | * For example, if a host controller doesn't maintain VBUS suspend current | ||
1690 | * during a system sleep or is reset when the system wakes up, all the USB | ||
1691 | * power sessions below it will be broken. This is especially troublesome | ||
1692 | * for mass-storage devices containing mounted filesystems, since the | ||
1693 | * device will appear to have disconnected and all the memory mappings | ||
1694 | * to it will be lost. Using the USB_PERSIST facility, the device can be | ||
1695 | * made to appear as if it had not disconnected. | ||
1696 | * | ||
1697 | * This facility is inherently dangerous. Although usb_reset_device() | ||
1698 | * makes every effort to insure that the same device is present after the | ||
1699 | * reset as before, it cannot provide a 100% guarantee. Furthermore it's | ||
1700 | * quite possible for a device to remain unaltered but its media to be | ||
1701 | * changed. If the user replaces a flash memory card while the system is | ||
1702 | * asleep, he will have only himself to blame when the filesystem on the | ||
1703 | * new card is corrupted and the system crashes. | ||
1704 | * | ||
1705 | * Returns 0 on success, else negative errno. | ||
1706 | */ | ||
1707 | int usb_port_resume(struct usb_device *udev) | ||
1767 | { | 1708 | { |
1768 | int status; | 1709 | struct usb_hub *hub = hdev_to_hub(udev->parent); |
1769 | u16 portchange, portstatus; | 1710 | int port1 = udev->portnum; |
1711 | int status; | ||
1712 | u16 portchange, portstatus; | ||
1713 | unsigned mask_flags, want_flags; | ||
1770 | 1714 | ||
1771 | /* Skip the initial Clear-Suspend step for a remote wakeup */ | 1715 | /* Skip the initial Clear-Suspend step for a remote wakeup */ |
1772 | status = hub_port_status(hub, port1, &portstatus, &portchange); | 1716 | status = hub_port_status(hub, port1, &portstatus, &portchange); |
@@ -1781,30 +1725,31 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) | |||
1781 | status = clear_port_feature(hub->hdev, | 1725 | status = clear_port_feature(hub->hdev, |
1782 | port1, USB_PORT_FEAT_SUSPEND); | 1726 | port1, USB_PORT_FEAT_SUSPEND); |
1783 | if (status) { | 1727 | if (status) { |
1784 | dev_dbg(hub->intfdev, | 1728 | dev_dbg(hub->intfdev, "can't resume port %d, status %d\n", |
1785 | "can't resume port %d, status %d\n", | 1729 | port1, status); |
1786 | port1, status); | ||
1787 | } else { | 1730 | } else { |
1788 | /* drive resume for at least 20 msec */ | 1731 | /* drive resume for at least 20 msec */ |
1789 | if (udev) | 1732 | dev_dbg(&udev->dev, "usb %sresume\n", |
1790 | dev_dbg(&udev->dev, "usb %sresume\n", | 1733 | udev->auto_pm ? "auto-" : ""); |
1791 | udev->auto_pm ? "auto-" : ""); | ||
1792 | msleep(25); | 1734 | msleep(25); |
1793 | 1735 | ||
1794 | #define LIVE_FLAGS ( USB_PORT_STAT_POWER \ | ||
1795 | | USB_PORT_STAT_ENABLE \ | ||
1796 | | USB_PORT_STAT_CONNECTION) | ||
1797 | |||
1798 | /* Virtual root hubs can trigger on GET_PORT_STATUS to | 1736 | /* Virtual root hubs can trigger on GET_PORT_STATUS to |
1799 | * stop resume signaling. Then finish the resume | 1737 | * stop resume signaling. Then finish the resume |
1800 | * sequence. | 1738 | * sequence. |
1801 | */ | 1739 | */ |
1802 | status = hub_port_status(hub, port1, &portstatus, &portchange); | 1740 | status = hub_port_status(hub, port1, &portstatus, &portchange); |
1803 | SuspendCleared: | 1741 | |
1804 | if (status < 0 | 1742 | SuspendCleared: |
1805 | || (portstatus & LIVE_FLAGS) != LIVE_FLAGS | 1743 | if (USB_PERSIST && udev->reset_resume) |
1806 | || (portstatus & USB_PORT_STAT_SUSPEND) != 0 | 1744 | want_flags = USB_PORT_STAT_POWER |
1807 | ) { | 1745 | | USB_PORT_STAT_CONNECTION; |
1746 | else | ||
1747 | want_flags = USB_PORT_STAT_POWER | ||
1748 | | USB_PORT_STAT_CONNECTION | ||
1749 | | USB_PORT_STAT_ENABLE; | ||
1750 | mask_flags = want_flags | USB_PORT_STAT_SUSPEND; | ||
1751 | |||
1752 | if (status < 0 || (portstatus & mask_flags) != want_flags) { | ||
1808 | dev_dbg(hub->intfdev, | 1753 | dev_dbg(hub->intfdev, |
1809 | "port %d status %04x.%04x after resume, %d\n", | 1754 | "port %d status %04x.%04x after resume, %d\n", |
1810 | port1, portchange, portstatus, status); | 1755 | port1, portchange, portstatus, status); |
@@ -1816,51 +1761,19 @@ SuspendCleared: | |||
1816 | USB_PORT_FEAT_C_SUSPEND); | 1761 | USB_PORT_FEAT_C_SUSPEND); |
1817 | /* TRSMRCY = 10 msec */ | 1762 | /* TRSMRCY = 10 msec */ |
1818 | msleep(10); | 1763 | msleep(10); |
1819 | if (udev) | ||
1820 | status = finish_port_resume(udev); | ||
1821 | } | 1764 | } |
1822 | } | 1765 | } |
1823 | if (status < 0) | ||
1824 | hub_port_logical_disconnect(hub, port1); | ||
1825 | 1766 | ||
1826 | clear_bit(port1, hub->busy_bits); | 1767 | clear_bit(port1, hub->busy_bits); |
1827 | if (!hub->hdev->parent && !hub->busy_bits[0]) | 1768 | if (!hub->hdev->parent && !hub->busy_bits[0]) |
1828 | usb_enable_root_hub_irq(hub->hdev->bus); | 1769 | usb_enable_root_hub_irq(hub->hdev->bus); |
1829 | 1770 | ||
1830 | return status; | 1771 | if (status == 0) |
1831 | } | ||
1832 | |||
1833 | /* | ||
1834 | * usb_port_resume - re-activate a suspended usb device's upstream port | ||
1835 | * @udev: device to re-activate | ||
1836 | * Context: must be able to sleep; device not locked; pm locks held | ||
1837 | * | ||
1838 | * This will re-activate the suspended device, increasing power usage | ||
1839 | * while letting drivers communicate again with its endpoints. | ||
1840 | * USB resume explicitly guarantees that the power session between | ||
1841 | * the host and the device is the same as it was when the device | ||
1842 | * suspended. | ||
1843 | * | ||
1844 | * Returns 0 on success, else negative errno. | ||
1845 | */ | ||
1846 | int usb_port_resume(struct usb_device *udev) | ||
1847 | { | ||
1848 | int status; | ||
1849 | |||
1850 | /* we change the device's upstream USB link, | ||
1851 | * but root hubs have no upstream USB link. | ||
1852 | */ | ||
1853 | if (udev->parent) { | ||
1854 | // NOTE this fails if parent is also suspended... | ||
1855 | status = hub_port_resume(hdev_to_hub(udev->parent), | ||
1856 | udev->portnum, udev); | ||
1857 | } else { | ||
1858 | dev_dbg(&udev->dev, "usb %sresume\n", | ||
1859 | udev->auto_pm ? "auto-" : ""); | ||
1860 | status = finish_port_resume(udev); | 1772 | status = finish_port_resume(udev); |
1861 | } | 1773 | if (status < 0) { |
1862 | if (status < 0) | ||
1863 | dev_dbg(&udev->dev, "can't resume, status %d\n", status); | 1774 | dev_dbg(&udev->dev, "can't resume, status %d\n", status); |
1775 | hub_port_logical_disconnect(hub, port1); | ||
1776 | } | ||
1864 | return status; | 1777 | return status; |
1865 | } | 1778 | } |
1866 | 1779 | ||
@@ -1887,21 +1800,16 @@ int usb_port_suspend(struct usb_device *udev) | |||
1887 | return 0; | 1800 | return 0; |
1888 | } | 1801 | } |
1889 | 1802 | ||
1890 | static inline int | ||
1891 | finish_port_resume(struct usb_device *udev) | ||
1892 | { | ||
1893 | return 0; | ||
1894 | } | ||
1895 | |||
1896 | static inline int | ||
1897 | hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) | ||
1898 | { | ||
1899 | return 0; | ||
1900 | } | ||
1901 | |||
1902 | int usb_port_resume(struct usb_device *udev) | 1803 | int usb_port_resume(struct usb_device *udev) |
1903 | { | 1804 | { |
1904 | return 0; | 1805 | int status = 0; |
1806 | |||
1807 | /* However we may need to do a reset-resume */ | ||
1808 | if (udev->reset_resume) { | ||
1809 | dev_dbg(&udev->dev, "reset-resume\n"); | ||
1810 | status = usb_reset_device(udev); | ||
1811 | } | ||
1812 | return status; | ||
1905 | } | 1813 | } |
1906 | 1814 | ||
1907 | static inline int remote_wakeup(struct usb_device *udev) | 1815 | static inline int remote_wakeup(struct usb_device *udev) |
@@ -1916,7 +1824,6 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
1916 | struct usb_hub *hub = usb_get_intfdata (intf); | 1824 | struct usb_hub *hub = usb_get_intfdata (intf); |
1917 | struct usb_device *hdev = hub->hdev; | 1825 | struct usb_device *hdev = hub->hdev; |
1918 | unsigned port1; | 1826 | unsigned port1; |
1919 | int status = 0; | ||
1920 | 1827 | ||
1921 | /* fail if children aren't already suspended */ | 1828 | /* fail if children aren't already suspended */ |
1922 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { | 1829 | for (port1 = 1; port1 <= hdev->maxchild; port1++) { |
@@ -1942,49 +1849,75 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) | |||
1942 | 1849 | ||
1943 | /* stop khubd and related activity */ | 1850 | /* stop khubd and related activity */ |
1944 | hub_quiesce(hub); | 1851 | hub_quiesce(hub); |
1945 | 1852 | return 0; | |
1946 | /* "global suspend" of the downstream HC-to-USB interface */ | ||
1947 | if (!hdev->parent) { | ||
1948 | status = hcd_bus_suspend(hdev->bus); | ||
1949 | if (status != 0) { | ||
1950 | dev_dbg(&hdev->dev, "'global' suspend %d\n", status); | ||
1951 | hub_activate(hub); | ||
1952 | } | ||
1953 | } | ||
1954 | return status; | ||
1955 | } | 1853 | } |
1956 | 1854 | ||
1957 | static int hub_resume(struct usb_interface *intf) | 1855 | static int hub_resume(struct usb_interface *intf) |
1958 | { | 1856 | { |
1959 | struct usb_hub *hub = usb_get_intfdata (intf); | 1857 | struct usb_hub *hub = usb_get_intfdata (intf); |
1960 | struct usb_device *hdev = hub->hdev; | ||
1961 | int status; | ||
1962 | 1858 | ||
1963 | dev_dbg(&intf->dev, "%s\n", __FUNCTION__); | 1859 | dev_dbg(&intf->dev, "%s\n", __FUNCTION__); |
1964 | 1860 | ||
1965 | /* "global resume" of the downstream HC-to-USB interface */ | 1861 | /* tell khubd to look for changes on this hub */ |
1966 | if (!hdev->parent) { | 1862 | hub_activate(hub); |
1967 | struct usb_bus *bus = hdev->bus; | 1863 | return 0; |
1968 | if (bus) { | 1864 | } |
1969 | status = hcd_bus_resume (bus); | 1865 | |
1970 | if (status) { | 1866 | static int hub_reset_resume(struct usb_interface *intf) |
1971 | dev_dbg(&intf->dev, "'global' resume %d\n", | 1867 | { |
1972 | status); | 1868 | struct usb_hub *hub = usb_get_intfdata(intf); |
1973 | return status; | 1869 | struct usb_device *hdev = hub->hdev; |
1870 | int port1; | ||
1871 | |||
1872 | hub_power_on(hub); | ||
1873 | |||
1874 | for (port1 = 1; port1 <= hdev->maxchild; ++port1) { | ||
1875 | struct usb_device *child = hdev->children[port1-1]; | ||
1876 | |||
1877 | if (child) { | ||
1878 | |||
1879 | /* For "USB_PERSIST"-enabled children we must | ||
1880 | * mark the child device for reset-resume and | ||
1881 | * turn off the connect-change status to prevent | ||
1882 | * khubd from disconnecting it later. | ||
1883 | */ | ||
1884 | if (USB_PERSIST && child->persist_enabled) { | ||
1885 | child->reset_resume = 1; | ||
1886 | clear_port_feature(hdev, port1, | ||
1887 | USB_PORT_FEAT_C_CONNECTION); | ||
1888 | |||
1889 | /* Otherwise we must disconnect the child, | ||
1890 | * but as we may not lock the child device here | ||
1891 | * we have to do a "logical" disconnect. | ||
1892 | */ | ||
1893 | } else { | ||
1894 | hub_port_logical_disconnect(hub, port1); | ||
1974 | } | 1895 | } |
1975 | } else | ||
1976 | return -EOPNOTSUPP; | ||
1977 | if (status == 0) { | ||
1978 | /* TRSMRCY = 10 msec */ | ||
1979 | msleep(10); | ||
1980 | } | 1896 | } |
1981 | } | 1897 | } |
1982 | 1898 | ||
1983 | /* tell khubd to look for changes on this hub */ | ||
1984 | hub_activate(hub); | 1899 | hub_activate(hub); |
1985 | return 0; | 1900 | return 0; |
1986 | } | 1901 | } |
1987 | 1902 | ||
1903 | /** | ||
1904 | * usb_root_hub_lost_power - called by HCD if the root hub lost Vbus power | ||
1905 | * @rhdev: struct usb_device for the root hub | ||
1906 | * | ||
1907 | * The USB host controller driver calls this function when its root hub | ||
1908 | * is resumed and Vbus power has been interrupted or the controller | ||
1909 | * has been reset. The routine marks @rhdev as having lost power. When | ||
1910 | * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST | ||
1911 | * is enabled then it will carry out power-session recovery, otherwise | ||
1912 | * it will disconnect all the child devices. | ||
1913 | */ | ||
1914 | void usb_root_hub_lost_power(struct usb_device *rhdev) | ||
1915 | { | ||
1916 | dev_warn(&rhdev->dev, "root hub lost power or was reset\n"); | ||
1917 | rhdev->reset_resume = 1; | ||
1918 | } | ||
1919 | EXPORT_SYMBOL_GPL(usb_root_hub_lost_power); | ||
1920 | |||
1988 | #else /* CONFIG_PM */ | 1921 | #else /* CONFIG_PM */ |
1989 | 1922 | ||
1990 | static inline int remote_wakeup(struct usb_device *udev) | 1923 | static inline int remote_wakeup(struct usb_device *udev) |
@@ -1992,8 +1925,9 @@ static inline int remote_wakeup(struct usb_device *udev) | |||
1992 | return 0; | 1925 | return 0; |
1993 | } | 1926 | } |
1994 | 1927 | ||
1995 | #define hub_suspend NULL | 1928 | #define hub_suspend NULL |
1996 | #define hub_resume NULL | 1929 | #define hub_resume NULL |
1930 | #define hub_reset_resume NULL | ||
1997 | #endif | 1931 | #endif |
1998 | 1932 | ||
1999 | 1933 | ||
@@ -2456,19 +2390,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, | |||
2456 | return; | 2390 | return; |
2457 | } | 2391 | } |
2458 | 2392 | ||
2459 | #ifdef CONFIG_USB_SUSPEND | ||
2460 | /* If something is connected, but the port is suspended, wake it up. */ | ||
2461 | if (portstatus & USB_PORT_STAT_SUSPEND) { | ||
2462 | status = hub_port_resume(hub, port1, NULL); | ||
2463 | if (status < 0) { | ||
2464 | dev_dbg(hub_dev, | ||
2465 | "can't clear suspend on port %d; %d\n", | ||
2466 | port1, status); | ||
2467 | goto done; | ||
2468 | } | ||
2469 | } | ||
2470 | #endif | ||
2471 | |||
2472 | for (i = 0; i < SET_CONFIG_TRIES; i++) { | 2393 | for (i = 0; i < SET_CONFIG_TRIES; i++) { |
2473 | struct usb_device *udev; | 2394 | struct usb_device *udev; |
2474 | 2395 | ||
@@ -2579,7 +2500,7 @@ loop: | |||
2579 | ep0_reinit(udev); | 2500 | ep0_reinit(udev); |
2580 | release_address(udev); | 2501 | release_address(udev); |
2581 | usb_put_dev(udev); | 2502 | usb_put_dev(udev); |
2582 | if (status == -ENOTCONN) | 2503 | if ((status == -ENOTCONN) || (status == -ENOTSUPP)) |
2583 | break; | 2504 | break; |
2584 | } | 2505 | } |
2585 | 2506 | ||
@@ -2620,10 +2541,12 @@ static void hub_events(void) | |||
2620 | list_del_init(tmp); | 2541 | list_del_init(tmp); |
2621 | 2542 | ||
2622 | hub = list_entry(tmp, struct usb_hub, event_list); | 2543 | hub = list_entry(tmp, struct usb_hub, event_list); |
2623 | hdev = hub->hdev; | 2544 | kref_get(&hub->kref); |
2624 | intf = to_usb_interface(hub->intfdev); | 2545 | spin_unlock_irq(&hub_event_lock); |
2625 | hub_dev = &intf->dev; | ||
2626 | 2546 | ||
2547 | hdev = hub->hdev; | ||
2548 | hub_dev = hub->intfdev; | ||
2549 | intf = to_usb_interface(hub_dev); | ||
2627 | dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", | 2550 | dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", |
2628 | hdev->state, hub->descriptor | 2551 | hdev->state, hub->descriptor |
2629 | ? hub->descriptor->bNbrPorts | 2552 | ? hub->descriptor->bNbrPorts |
@@ -2632,16 +2555,10 @@ static void hub_events(void) | |||
2632 | (u16) hub->change_bits[0], | 2555 | (u16) hub->change_bits[0], |
2633 | (u16) hub->event_bits[0]); | 2556 | (u16) hub->event_bits[0]); |
2634 | 2557 | ||
2635 | usb_get_intf(intf); | ||
2636 | spin_unlock_irq(&hub_event_lock); | ||
2637 | |||
2638 | /* Lock the device, then check to see if we were | 2558 | /* Lock the device, then check to see if we were |
2639 | * disconnected while waiting for the lock to succeed. */ | 2559 | * disconnected while waiting for the lock to succeed. */ |
2640 | if (locktree(hdev) < 0) { | 2560 | usb_lock_device(hdev); |
2641 | usb_put_intf(intf); | 2561 | if (unlikely(hub->disconnected)) |
2642 | continue; | ||
2643 | } | ||
2644 | if (hub != usb_get_intfdata(intf)) | ||
2645 | goto loop; | 2562 | goto loop; |
2646 | 2563 | ||
2647 | /* If the hub has died, clean up after it */ | 2564 | /* If the hub has died, clean up after it */ |
@@ -2804,7 +2721,7 @@ loop_autopm: | |||
2804 | usb_autopm_enable(intf); | 2721 | usb_autopm_enable(intf); |
2805 | loop: | 2722 | loop: |
2806 | usb_unlock_device(hdev); | 2723 | usb_unlock_device(hdev); |
2807 | usb_put_intf(intf); | 2724 | kref_put(&hub->kref, hub_release); |
2808 | 2725 | ||
2809 | } /* end while (1) */ | 2726 | } /* end while (1) */ |
2810 | } | 2727 | } |
@@ -2839,6 +2756,7 @@ static struct usb_driver hub_driver = { | |||
2839 | .disconnect = hub_disconnect, | 2756 | .disconnect = hub_disconnect, |
2840 | .suspend = hub_suspend, | 2757 | .suspend = hub_suspend, |
2841 | .resume = hub_resume, | 2758 | .resume = hub_resume, |
2759 | .reset_resume = hub_reset_resume, | ||
2842 | .pre_reset = hub_pre_reset, | 2760 | .pre_reset = hub_pre_reset, |
2843 | .post_reset = hub_post_reset, | 2761 | .post_reset = hub_post_reset, |
2844 | .ioctl = hub_ioctl, | 2762 | .ioctl = hub_ioctl, |
@@ -2941,6 +2859,11 @@ static int config_descriptors_changed(struct usb_device *udev) | |||
2941 | * this from a driver probe() routine after downloading new firmware. | 2859 | * this from a driver probe() routine after downloading new firmware. |
2942 | * For calls that might not occur during probe(), drivers should lock | 2860 | * For calls that might not occur during probe(), drivers should lock |
2943 | * the device using usb_lock_device_for_reset(). | 2861 | * the device using usb_lock_device_for_reset(). |
2862 | * | ||
2863 | * Locking exception: This routine may also be called from within an | ||
2864 | * autoresume handler. Such usage won't conflict with other tasks | ||
2865 | * holding the device lock because these tasks should always call | ||
2866 | * usb_autopm_resume_device(), thereby preventing any unwanted autoresume. | ||
2944 | */ | 2867 | */ |
2945 | int usb_reset_device(struct usb_device *udev) | 2868 | int usb_reset_device(struct usb_device *udev) |
2946 | { | 2869 | { |
@@ -2971,7 +2894,7 @@ int usb_reset_device(struct usb_device *udev) | |||
2971 | * Other endpoints will be handled by re-enumeration. */ | 2894 | * Other endpoints will be handled by re-enumeration. */ |
2972 | ep0_reinit(udev); | 2895 | ep0_reinit(udev); |
2973 | ret = hub_port_init(parent_hub, udev, port1, i); | 2896 | ret = hub_port_init(parent_hub, udev, port1, i); |
2974 | if (ret >= 0) | 2897 | if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV) |
2975 | break; | 2898 | break; |
2976 | } | 2899 | } |
2977 | clear_bit(port1, parent_hub->busy_bits); | 2900 | clear_bit(port1, parent_hub->busy_bits); |
@@ -3087,6 +3010,7 @@ int usb_reset_composite_device(struct usb_device *udev, | |||
3087 | drv = to_usb_driver(cintf->dev.driver); | 3010 | drv = to_usb_driver(cintf->dev.driver); |
3088 | if (drv->pre_reset) | 3011 | if (drv->pre_reset) |
3089 | (drv->pre_reset)(cintf); | 3012 | (drv->pre_reset)(cintf); |
3013 | /* FIXME: Unbind if pre_reset returns an error or isn't defined */ | ||
3090 | } | 3014 | } |
3091 | } | 3015 | } |
3092 | } | 3016 | } |
@@ -3105,6 +3029,7 @@ int usb_reset_composite_device(struct usb_device *udev, | |||
3105 | drv = to_usb_driver(cintf->dev.driver); | 3029 | drv = to_usb_driver(cintf->dev.driver); |
3106 | if (drv->post_reset) | 3030 | if (drv->post_reset) |
3107 | (drv->post_reset)(cintf); | 3031 | (drv->post_reset)(cintf); |
3032 | /* FIXME: Unbind if post_reset returns an error or isn't defined */ | ||
3108 | } | 3033 | } |
3109 | if (cintf != iface) | 3034 | if (cintf != iface) |
3110 | up(&cintf->dev.sem); | 3035 | up(&cintf->dev.sem); |
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f9fed34bf7d8..530e854961ce 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c | |||
@@ -404,8 +404,6 @@ int usb_sg_init ( | |||
404 | 404 | ||
405 | io->urbs [i]->complete = sg_complete; | 405 | io->urbs [i]->complete = sg_complete; |
406 | io->urbs [i]->context = io; | 406 | io->urbs [i]->context = io; |
407 | io->urbs [i]->status = -EINPROGRESS; | ||
408 | io->urbs [i]->actual_length = 0; | ||
409 | 407 | ||
410 | /* | 408 | /* |
411 | * Some systems need to revert to PIO when DMA is temporarily | 409 | * Some systems need to revert to PIO when DMA is temporarily |
@@ -499,7 +497,8 @@ void usb_sg_wait (struct usb_sg_request *io) | |||
499 | 497 | ||
500 | /* queue the urbs. */ | 498 | /* queue the urbs. */ |
501 | spin_lock_irq (&io->lock); | 499 | spin_lock_irq (&io->lock); |
502 | for (i = 0; i < entries && !io->status; i++) { | 500 | i = 0; |
501 | while (i < entries && !io->status) { | ||
503 | int retval; | 502 | int retval; |
504 | 503 | ||
505 | io->urbs [i]->dev = io->dev; | 504 | io->urbs [i]->dev = io->dev; |
@@ -516,7 +515,6 @@ void usb_sg_wait (struct usb_sg_request *io) | |||
516 | case -ENOMEM: | 515 | case -ENOMEM: |
517 | io->urbs[i]->dev = NULL; | 516 | io->urbs[i]->dev = NULL; |
518 | retval = 0; | 517 | retval = 0; |
519 | i--; | ||
520 | yield (); | 518 | yield (); |
521 | break; | 519 | break; |
522 | 520 | ||
@@ -527,6 +525,7 @@ void usb_sg_wait (struct usb_sg_request *io) | |||
527 | * URBs are queued at once; N milliseconds? | 525 | * URBs are queued at once; N milliseconds? |
528 | */ | 526 | */ |
529 | case 0: | 527 | case 0: |
528 | ++i; | ||
530 | cpu_relax (); | 529 | cpu_relax (); |
531 | break; | 530 | break; |
532 | 531 | ||
@@ -1385,6 +1384,36 @@ struct device_type usb_if_device_type = { | |||
1385 | .uevent = usb_if_uevent, | 1384 | .uevent = usb_if_uevent, |
1386 | }; | 1385 | }; |
1387 | 1386 | ||
1387 | static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev, | ||
1388 | struct usb_host_config *config, | ||
1389 | u8 inum) | ||
1390 | { | ||
1391 | struct usb_interface_assoc_descriptor *retval = NULL; | ||
1392 | struct usb_interface_assoc_descriptor *intf_assoc; | ||
1393 | int first_intf; | ||
1394 | int last_intf; | ||
1395 | int i; | ||
1396 | |||
1397 | for (i = 0; (i < USB_MAXIADS && config->intf_assoc[i]); i++) { | ||
1398 | intf_assoc = config->intf_assoc[i]; | ||
1399 | if (intf_assoc->bInterfaceCount == 0) | ||
1400 | continue; | ||
1401 | |||
1402 | first_intf = intf_assoc->bFirstInterface; | ||
1403 | last_intf = first_intf + (intf_assoc->bInterfaceCount - 1); | ||
1404 | if (inum >= first_intf && inum <= last_intf) { | ||
1405 | if (!retval) | ||
1406 | retval = intf_assoc; | ||
1407 | else | ||
1408 | dev_err(&dev->dev, "Interface #%d referenced" | ||
1409 | " by multiple IADs\n", inum); | ||
1410 | } | ||
1411 | } | ||
1412 | |||
1413 | return retval; | ||
1414 | } | ||
1415 | |||
1416 | |||
1388 | /* | 1417 | /* |
1389 | * usb_set_configuration - Makes a particular device setting be current | 1418 | * usb_set_configuration - Makes a particular device setting be current |
1390 | * @dev: the device whose configuration is being updated | 1419 | * @dev: the device whose configuration is being updated |
@@ -1531,6 +1560,7 @@ free_interfaces: | |||
1531 | intfc = cp->intf_cache[i]; | 1560 | intfc = cp->intf_cache[i]; |
1532 | intf->altsetting = intfc->altsetting; | 1561 | intf->altsetting = intfc->altsetting; |
1533 | intf->num_altsetting = intfc->num_altsetting; | 1562 | intf->num_altsetting = intfc->num_altsetting; |
1563 | intf->intf_assoc = find_iad(dev, cp, i); | ||
1534 | kref_get(&intfc->ref); | 1564 | kref_get(&intfc->ref); |
1535 | 1565 | ||
1536 | alt = usb_altnum_to_altsetting(intf, 0); | 1566 | alt = usb_altnum_to_altsetting(intf, 0); |
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 739f520908aa..aa21b38a31ce 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
@@ -30,10 +30,28 @@ | |||
30 | static const struct usb_device_id usb_quirk_list[] = { | 30 | static const struct usb_device_id usb_quirk_list[] = { |
31 | /* HP 5300/5370C scanner */ | 31 | /* HP 5300/5370C scanner */ |
32 | { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, | 32 | { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, |
33 | /* Benq S2W 3300U */ | ||
34 | { USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
35 | /* Seiko Epson Corp. Perfection 1200 */ | ||
36 | { USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
33 | /* Seiko Epson Corp - Perfection 1670 */ | 37 | /* Seiko Epson Corp - Perfection 1670 */ |
34 | { USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | 38 | { USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, |
39 | /* Samsung ML-2510 Series printer */ | ||
40 | { USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
35 | /* Elsa MicroLink 56k (V.250) */ | 41 | /* Elsa MicroLink 56k (V.250) */ |
36 | { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | 42 | { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, |
43 | /* Ultima Electronics Corp.*/ | ||
44 | { USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
45 | /* Umax [hex] Astra 3400U */ | ||
46 | { USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
47 | |||
48 | /* Philips PSC805 audio device */ | ||
49 | { USB_DEVICE(0x0471, 0x0155), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
50 | |||
51 | /* RIM Blackberry */ | ||
52 | { USB_DEVICE(0x0fca, 0x0001), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
53 | { USB_DEVICE(0x0fca, 0x0004), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
54 | { USB_DEVICE(0x0fca, 0x0006), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, | ||
37 | 55 | ||
38 | { } /* terminating entry must be last */ | 56 | { } /* terminating entry must be last */ |
39 | }; | 57 | }; |
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index be37c863fdfb..d47ae89154a7 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c | |||
@@ -169,6 +169,73 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf) | |||
169 | } | 169 | } |
170 | static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); | 170 | static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL); |
171 | 171 | ||
172 | |||
173 | #if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND) | ||
174 | static const char power_group[] = "power"; | ||
175 | #endif | ||
176 | |||
177 | #ifdef CONFIG_USB_PERSIST | ||
178 | |||
179 | static ssize_t | ||
180 | show_persist(struct device *dev, struct device_attribute *attr, char *buf) | ||
181 | { | ||
182 | struct usb_device *udev = to_usb_device(dev); | ||
183 | |||
184 | return sprintf(buf, "%d\n", udev->persist_enabled); | ||
185 | } | ||
186 | |||
187 | static ssize_t | ||
188 | set_persist(struct device *dev, struct device_attribute *attr, | ||
189 | const char *buf, size_t count) | ||
190 | { | ||
191 | struct usb_device *udev = to_usb_device(dev); | ||
192 | int value; | ||
193 | |||
194 | /* Hubs are always enabled for USB_PERSIST */ | ||
195 | if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) | ||
196 | return -EPERM; | ||
197 | |||
198 | if (sscanf(buf, "%d", &value) != 1) | ||
199 | return -EINVAL; | ||
200 | usb_pm_lock(udev); | ||
201 | udev->persist_enabled = !!value; | ||
202 | usb_pm_unlock(udev); | ||
203 | return count; | ||
204 | } | ||
205 | |||
206 | static DEVICE_ATTR(persist, S_IRUGO | S_IWUSR, show_persist, set_persist); | ||
207 | |||
208 | static int add_persist_attributes(struct device *dev) | ||
209 | { | ||
210 | int rc = 0; | ||
211 | |||
212 | if (is_usb_device(dev)) { | ||
213 | struct usb_device *udev = to_usb_device(dev); | ||
214 | |||
215 | /* Hubs are automatically enabled for USB_PERSIST */ | ||
216 | if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) | ||
217 | udev->persist_enabled = 1; | ||
218 | rc = sysfs_add_file_to_group(&dev->kobj, | ||
219 | &dev_attr_persist.attr, | ||
220 | power_group); | ||
221 | } | ||
222 | return rc; | ||
223 | } | ||
224 | |||
225 | static void remove_persist_attributes(struct device *dev) | ||
226 | { | ||
227 | sysfs_remove_file_from_group(&dev->kobj, | ||
228 | &dev_attr_persist.attr, | ||
229 | power_group); | ||
230 | } | ||
231 | |||
232 | #else | ||
233 | |||
234 | #define add_persist_attributes(dev) 0 | ||
235 | #define remove_persist_attributes(dev) do {} while (0) | ||
236 | |||
237 | #endif /* CONFIG_USB_PERSIST */ | ||
238 | |||
172 | #ifdef CONFIG_USB_SUSPEND | 239 | #ifdef CONFIG_USB_SUSPEND |
173 | 240 | ||
174 | static ssize_t | 241 | static ssize_t |
@@ -276,8 +343,6 @@ set_level(struct device *dev, struct device_attribute *attr, | |||
276 | 343 | ||
277 | static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level); | 344 | static DEVICE_ATTR(level, S_IRUGO | S_IWUSR, show_level, set_level); |
278 | 345 | ||
279 | static char power_group[] = "power"; | ||
280 | |||
281 | static int add_power_attributes(struct device *dev) | 346 | static int add_power_attributes(struct device *dev) |
282 | { | 347 | { |
283 | int rc = 0; | 348 | int rc = 0; |
@@ -311,6 +376,7 @@ static void remove_power_attributes(struct device *dev) | |||
311 | 376 | ||
312 | #endif /* CONFIG_USB_SUSPEND */ | 377 | #endif /* CONFIG_USB_SUSPEND */ |
313 | 378 | ||
379 | |||
314 | /* Descriptor fields */ | 380 | /* Descriptor fields */ |
315 | #define usb_descriptor_attr_le16(field, format_string) \ | 381 | #define usb_descriptor_attr_le16(field, format_string) \ |
316 | static ssize_t \ | 382 | static ssize_t \ |
@@ -384,6 +450,10 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) | |||
384 | if (retval) | 450 | if (retval) |
385 | return retval; | 451 | return retval; |
386 | 452 | ||
453 | retval = add_persist_attributes(dev); | ||
454 | if (retval) | ||
455 | goto error; | ||
456 | |||
387 | retval = add_power_attributes(dev); | 457 | retval = add_power_attributes(dev); |
388 | if (retval) | 458 | if (retval) |
389 | goto error; | 459 | goto error; |
@@ -421,9 +491,29 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) | |||
421 | device_remove_file(dev, &dev_attr_product); | 491 | device_remove_file(dev, &dev_attr_product); |
422 | device_remove_file(dev, &dev_attr_serial); | 492 | device_remove_file(dev, &dev_attr_serial); |
423 | remove_power_attributes(dev); | 493 | remove_power_attributes(dev); |
494 | remove_persist_attributes(dev); | ||
424 | sysfs_remove_group(&dev->kobj, &dev_attr_grp); | 495 | sysfs_remove_group(&dev->kobj, &dev_attr_grp); |
425 | } | 496 | } |
426 | 497 | ||
498 | /* Interface Accociation Descriptor fields */ | ||
499 | #define usb_intf_assoc_attr(field, format_string) \ | ||
500 | static ssize_t \ | ||
501 | show_iad_##field (struct device *dev, struct device_attribute *attr, \ | ||
502 | char *buf) \ | ||
503 | { \ | ||
504 | struct usb_interface *intf = to_usb_interface (dev); \ | ||
505 | \ | ||
506 | return sprintf (buf, format_string, \ | ||
507 | intf->intf_assoc->field); \ | ||
508 | } \ | ||
509 | static DEVICE_ATTR(iad_##field, S_IRUGO, show_iad_##field, NULL); | ||
510 | |||
511 | usb_intf_assoc_attr (bFirstInterface, "%02x\n") | ||
512 | usb_intf_assoc_attr (bInterfaceCount, "%02d\n") | ||
513 | usb_intf_assoc_attr (bFunctionClass, "%02x\n") | ||
514 | usb_intf_assoc_attr (bFunctionSubClass, "%02x\n") | ||
515 | usb_intf_assoc_attr (bFunctionProtocol, "%02x\n") | ||
516 | |||
427 | /* Interface fields */ | 517 | /* Interface fields */ |
428 | #define usb_intf_attr(field, format_string) \ | 518 | #define usb_intf_attr(field, format_string) \ |
429 | static ssize_t \ | 519 | static ssize_t \ |
@@ -487,6 +577,18 @@ static ssize_t show_modalias(struct device *dev, | |||
487 | } | 577 | } |
488 | static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); | 578 | static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); |
489 | 579 | ||
580 | static struct attribute *intf_assoc_attrs[] = { | ||
581 | &dev_attr_iad_bFirstInterface.attr, | ||
582 | &dev_attr_iad_bInterfaceCount.attr, | ||
583 | &dev_attr_iad_bFunctionClass.attr, | ||
584 | &dev_attr_iad_bFunctionSubClass.attr, | ||
585 | &dev_attr_iad_bFunctionProtocol.attr, | ||
586 | NULL, | ||
587 | }; | ||
588 | static struct attribute_group intf_assoc_attr_grp = { | ||
589 | .attrs = intf_assoc_attrs, | ||
590 | }; | ||
591 | |||
490 | static struct attribute *intf_attrs[] = { | 592 | static struct attribute *intf_attrs[] = { |
491 | &dev_attr_bInterfaceNumber.attr, | 593 | &dev_attr_bInterfaceNumber.attr, |
492 | &dev_attr_bAlternateSetting.attr, | 594 | &dev_attr_bAlternateSetting.attr, |
@@ -538,6 +640,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) | |||
538 | alt->string = usb_cache_string(udev, alt->desc.iInterface); | 640 | alt->string = usb_cache_string(udev, alt->desc.iInterface); |
539 | if (alt->string) | 641 | if (alt->string) |
540 | retval = device_create_file(dev, &dev_attr_interface); | 642 | retval = device_create_file(dev, &dev_attr_interface); |
643 | if (intf->intf_assoc) | ||
644 | retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp); | ||
541 | usb_create_intf_ep_files(intf, udev); | 645 | usb_create_intf_ep_files(intf, udev); |
542 | return 0; | 646 | return 0; |
543 | } | 647 | } |
@@ -549,4 +653,5 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf) | |||
549 | usb_remove_intf_ep_files(intf); | 653 | usb_remove_intf_ep_files(intf); |
550 | device_remove_file(dev, &dev_attr_interface); | 654 | device_remove_file(dev, &dev_attr_interface); |
551 | sysfs_remove_group(&dev->kobj, &intf_attr_grp); | 655 | sysfs_remove_group(&dev->kobj, &intf_attr_grp); |
656 | sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp); | ||
552 | } | 657 | } |
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 94ea9727ff55..52ec44b828f3 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
5 | #include <linux/init.h> | 5 | #include <linux/init.h> |
6 | #include <linux/usb.h> | 6 | #include <linux/usb.h> |
7 | #include <linux/wait.h> | ||
7 | #include "hcd.h" | 8 | #include "hcd.h" |
8 | 9 | ||
9 | #define to_urb(d) container_of(d, struct urb, kref) | 10 | #define to_urb(d) container_of(d, struct urb, kref) |
@@ -11,6 +12,10 @@ | |||
11 | static void urb_destroy(struct kref *kref) | 12 | static void urb_destroy(struct kref *kref) |
12 | { | 13 | { |
13 | struct urb *urb = to_urb(kref); | 14 | struct urb *urb = to_urb(kref); |
15 | |||
16 | if (urb->transfer_flags & URB_FREE_BUFFER) | ||
17 | kfree(urb->transfer_buffer); | ||
18 | |||
14 | kfree(urb); | 19 | kfree(urb); |
15 | } | 20 | } |
16 | 21 | ||
@@ -34,6 +39,7 @@ void usb_init_urb(struct urb *urb) | |||
34 | memset(urb, 0, sizeof(*urb)); | 39 | memset(urb, 0, sizeof(*urb)); |
35 | kref_init(&urb->kref); | 40 | kref_init(&urb->kref); |
36 | spin_lock_init(&urb->lock); | 41 | spin_lock_init(&urb->lock); |
42 | INIT_LIST_HEAD(&urb->anchor_list); | ||
37 | } | 43 | } |
38 | } | 44 | } |
39 | 45 | ||
@@ -100,8 +106,60 @@ struct urb * usb_get_urb(struct urb *urb) | |||
100 | kref_get(&urb->kref); | 106 | kref_get(&urb->kref); |
101 | return urb; | 107 | return urb; |
102 | } | 108 | } |
103 | 109 | ||
104 | 110 | /** | |
111 | * usb_anchor_urb - anchors an URB while it is processed | ||
112 | * @urb: pointer to the urb to anchor | ||
113 | * @anchor: pointer to the anchor | ||
114 | * | ||
115 | * This can be called to have access to URBs which are to be executed | ||
116 | * without bothering to track them | ||
117 | */ | ||
118 | void usb_anchor_urb(struct urb *urb, struct usb_anchor *anchor) | ||
119 | { | ||
120 | unsigned long flags; | ||
121 | |||
122 | spin_lock_irqsave(&anchor->lock, flags); | ||
123 | usb_get_urb(urb); | ||
124 | list_add_tail(&urb->anchor_list, &anchor->urb_list); | ||
125 | urb->anchor = anchor; | ||
126 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
127 | } | ||
128 | EXPORT_SYMBOL_GPL(usb_anchor_urb); | ||
129 | |||
130 | /** | ||
131 | * usb_unanchor_urb - unanchors an URB | ||
132 | * @urb: pointer to the urb to anchor | ||
133 | * | ||
134 | * Call this to stop the system keeping track of this URB | ||
135 | */ | ||
136 | void usb_unanchor_urb(struct urb *urb) | ||
137 | { | ||
138 | unsigned long flags; | ||
139 | struct usb_anchor *anchor; | ||
140 | |||
141 | if (!urb) | ||
142 | return; | ||
143 | |||
144 | anchor = urb->anchor; | ||
145 | if (!anchor) | ||
146 | return; | ||
147 | |||
148 | spin_lock_irqsave(&anchor->lock, flags); | ||
149 | if (unlikely(anchor != urb->anchor)) { | ||
150 | /* we've lost the race to another thread */ | ||
151 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
152 | return; | ||
153 | } | ||
154 | urb->anchor = NULL; | ||
155 | list_del(&urb->anchor_list); | ||
156 | spin_unlock_irqrestore(&anchor->lock, flags); | ||
157 | usb_put_urb(urb); | ||
158 | if (list_empty(&anchor->urb_list)) | ||
159 | wake_up(&anchor->wait); | ||
160 | } | ||
161 | EXPORT_SYMBOL_GPL(usb_unanchor_urb); | ||
162 | |||
105 | /*-------------------------------------------------------------------*/ | 163 | /*-------------------------------------------------------------------*/ |
106 | 164 | ||
107 | /** | 165 | /** |
@@ -478,6 +536,48 @@ void usb_kill_urb(struct urb *urb) | |||
478 | spin_unlock_irq(&urb->lock); | 536 | spin_unlock_irq(&urb->lock); |
479 | } | 537 | } |
480 | 538 | ||
539 | /** | ||
540 | * usb_kill_anchored_urbs - cancel transfer requests en masse | ||
541 | * @anchor: anchor the requests are bound to | ||
542 | * | ||
543 | * this allows all outstanding URBs to be killed starting | ||
544 | * from the back of the queue | ||
545 | */ | ||
546 | void usb_kill_anchored_urbs(struct usb_anchor *anchor) | ||
547 | { | ||
548 | struct urb *victim; | ||
549 | |||
550 | spin_lock_irq(&anchor->lock); | ||
551 | while (!list_empty(&anchor->urb_list)) { | ||
552 | victim = list_entry(anchor->urb_list.prev, struct urb, anchor_list); | ||
553 | /* we must make sure the URB isn't freed before we kill it*/ | ||
554 | usb_get_urb(victim); | ||
555 | spin_unlock_irq(&anchor->lock); | ||
556 | /* this will unanchor the URB */ | ||
557 | usb_kill_urb(victim); | ||
558 | usb_put_urb(victim); | ||
559 | spin_lock_irq(&anchor->lock); | ||
560 | } | ||
561 | spin_unlock_irq(&anchor->lock); | ||
562 | } | ||
563 | EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); | ||
564 | |||
565 | /** | ||
566 | * usb_wait_anchor_empty_timeout - wait for an anchor to be unused | ||
567 | * @anchor: the anchor you want to become unused | ||
568 | * @timeout: how long you are willing to wait in milliseconds | ||
569 | * | ||
570 | * Call this is you want to be sure all an anchor's | ||
571 | * URBs have finished | ||
572 | */ | ||
573 | int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, | ||
574 | unsigned int timeout) | ||
575 | { | ||
576 | return wait_event_timeout(anchor->wait, list_empty(&anchor->urb_list), | ||
577 | msecs_to_jiffies(timeout)); | ||
578 | } | ||
579 | EXPORT_SYMBOL_GPL(usb_wait_anchor_empty_timeout); | ||
580 | |||
481 | EXPORT_SYMBOL(usb_init_urb); | 581 | EXPORT_SYMBOL(usb_init_urb); |
482 | EXPORT_SYMBOL(usb_alloc_urb); | 582 | EXPORT_SYMBOL(usb_alloc_urb); |
483 | EXPORT_SYMBOL(usb_free_urb); | 583 | EXPORT_SYMBOL(usb_free_urb); |
@@ -485,4 +585,3 @@ EXPORT_SYMBOL(usb_get_urb); | |||
485 | EXPORT_SYMBOL(usb_submit_urb); | 585 | EXPORT_SYMBOL(usb_submit_urb); |
486 | EXPORT_SYMBOL(usb_unlink_urb); | 586 | EXPORT_SYMBOL(usb_unlink_urb); |
487 | EXPORT_SYMBOL(usb_kill_urb); | 587 | EXPORT_SYMBOL(usb_kill_urb); |
488 | |||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 4a6299bd0047..0fee5c66fd64 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -253,6 +253,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1) | |||
253 | dev->dev.bus = &usb_bus_type; | 253 | dev->dev.bus = &usb_bus_type; |
254 | dev->dev.type = &usb_device_type; | 254 | dev->dev.type = &usb_device_type; |
255 | dev->dev.dma_mask = bus->controller->dma_mask; | 255 | dev->dev.dma_mask = bus->controller->dma_mask; |
256 | set_dev_node(&dev->dev, dev_to_node(bus->controller)); | ||
256 | dev->state = USB_STATE_ATTACHED; | 257 | dev->state = USB_STATE_ATTACHED; |
257 | 258 | ||
258 | INIT_LIST_HEAD(&dev->ep0.urb_list); | 259 | INIT_LIST_HEAD(&dev->ep0.urb_list); |
@@ -578,11 +579,12 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, | |||
578 | * address (through the pointer provided). | 579 | * address (through the pointer provided). |
579 | * | 580 | * |
580 | * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags | 581 | * These buffers are used with URB_NO_xxx_DMA_MAP set in urb->transfer_flags |
581 | * to avoid behaviors like using "DMA bounce buffers", or tying down I/O | 582 | * to avoid behaviors like using "DMA bounce buffers", or thrashing IOMMU |
582 | * mapping hardware for long idle periods. The implementation varies between | 583 | * hardware during URB completion/resubmit. The implementation varies between |
583 | * platforms, depending on details of how DMA will work to this device. | 584 | * platforms, depending on details of how DMA will work to this device. |
584 | * Using these buffers also helps prevent cacheline sharing problems on | 585 | * Using these buffers also eliminates cacheline sharing problems on |
585 | * architectures where CPU caches are not DMA-coherent. | 586 | * architectures where CPU caches are not DMA-coherent. On systems without |
587 | * bus-snooping caches, these buffers are uncached. | ||
586 | * | 588 | * |
587 | * When the buffer is no longer used, free it with usb_buffer_free(). | 589 | * When the buffer is no longer used, free it with usb_buffer_free(). |
588 | */ | 590 | */ |
@@ -607,7 +609,7 @@ void *usb_buffer_alloc( | |||
607 | * | 609 | * |
608 | * This reclaims an I/O buffer, letting it be reused. The memory must have | 610 | * This reclaims an I/O buffer, letting it be reused. The memory must have |
609 | * been allocated using usb_buffer_alloc(), and the parameters must match | 611 | * been allocated using usb_buffer_alloc(), and the parameters must match |
610 | * those provided in that allocation request. | 612 | * those provided in that allocation request. |
611 | */ | 613 | */ |
612 | void usb_buffer_free( | 614 | void usb_buffer_free( |
613 | struct usb_device *dev, | 615 | struct usb_device *dev, |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index bf2eb0dae2ec..ad5fa0338f49 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -52,8 +52,16 @@ static inline void usb_pm_unlock(struct usb_device *udev) | |||
52 | 52 | ||
53 | #else | 53 | #else |
54 | 54 | ||
55 | #define usb_port_suspend(dev) 0 | 55 | static inline int usb_port_suspend(struct usb_device *udev) |
56 | #define usb_port_resume(dev) 0 | 56 | { |
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static inline int usb_port_resume(struct usb_device *udev) | ||
61 | { | ||
62 | return 0; | ||
63 | } | ||
64 | |||
57 | static inline void usb_pm_lock(struct usb_device *udev) {} | 65 | static inline void usb_pm_lock(struct usb_device *udev) {} |
58 | static inline void usb_pm_unlock(struct usb_device *udev) {} | 66 | static inline void usb_pm_unlock(struct usb_device *udev) {} |
59 | 67 | ||
@@ -100,11 +108,13 @@ static inline int is_usb_device_driver(struct device_driver *drv) | |||
100 | static inline void mark_active(struct usb_interface *f) | 108 | static inline void mark_active(struct usb_interface *f) |
101 | { | 109 | { |
102 | f->is_active = 1; | 110 | f->is_active = 1; |
111 | f->dev.power.power_state.event = PM_EVENT_ON; | ||
103 | } | 112 | } |
104 | 113 | ||
105 | static inline void mark_quiesced(struct usb_interface *f) | 114 | static inline void mark_quiesced(struct usb_interface *f) |
106 | { | 115 | { |
107 | f->is_active = 0; | 116 | f->is_active = 0; |
117 | f->dev.power.power_state.event = PM_EVENT_SUSPEND; | ||
108 | } | 118 | } |
109 | 119 | ||
110 | static inline int is_active(const struct usb_interface *f) | 120 | static inline int is_active(const struct usb_interface *f) |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index f771a7cae9ec..45e01e289455 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -42,6 +42,20 @@ config USB_GADGET | |||
42 | For more information, see <http://www.linux-usb.org/gadget> and | 42 | For more information, see <http://www.linux-usb.org/gadget> and |
43 | the kernel DocBook documentation for this API. | 43 | the kernel DocBook documentation for this API. |
44 | 44 | ||
45 | config USB_GADGET_DEBUG | ||
46 | boolean "Debugging messages" | ||
47 | depends on USB_GADGET && DEBUG_KERNEL && EXPERIMENTAL | ||
48 | help | ||
49 | Many controller and gadget drivers will print some debugging | ||
50 | messages if you use this option to ask for those messages. | ||
51 | |||
52 | Avoid enabling these messages, even if you're actively | ||
53 | debugging such a driver. Many drivers will emit so many | ||
54 | messages that the driver timings are affected, which will | ||
55 | either create new failure modes or remove the one you're | ||
56 | trying to track down. Never enable these messages for a | ||
57 | production build. | ||
58 | |||
45 | config USB_GADGET_DEBUG_FILES | 59 | config USB_GADGET_DEBUG_FILES |
46 | boolean "Debugging information files" | 60 | boolean "Debugging information files" |
47 | depends on USB_GADGET && PROC_FS | 61 | depends on USB_GADGET && PROC_FS |
@@ -208,6 +222,27 @@ config USB_OTG | |||
208 | 222 | ||
209 | Select this only if your OMAP board has a Mini-AB connector. | 223 | Select this only if your OMAP board has a Mini-AB connector. |
210 | 224 | ||
225 | config USB_GADGET_S3C2410 | ||
226 | boolean "S3C2410 USB Device Controller" | ||
227 | depends on ARCH_S3C2410 | ||
228 | help | ||
229 | Samsung's S3C2410 is an ARM-4 processor with an integrated | ||
230 | full speed USB 1.1 device controller. It has 4 configurable | ||
231 | endpoints, as well as endpoint zero (for control transfers). | ||
232 | |||
233 | This driver has been tested on the S3C2410, S3C2412, and | ||
234 | S3C2440 processors. | ||
235 | |||
236 | config USB_S3C2410 | ||
237 | tristate | ||
238 | depends on USB_GADGET_S3C2410 | ||
239 | default USB_GADGET | ||
240 | select USB_GADGET_SELECTED | ||
241 | |||
242 | config USB_S3C2410_DEBUG | ||
243 | boolean "S3C2410 udc debug messages" | ||
244 | depends on USB_GADGET_S3C2410 | ||
245 | |||
211 | config USB_GADGET_AT91 | 246 | config USB_GADGET_AT91 |
212 | boolean "AT91 USB Device Port" | 247 | boolean "AT91 USB Device Port" |
213 | depends on ARCH_AT91 && !ARCH_AT91SAM9RL | 248 | depends on ARCH_AT91 && !ARCH_AT91SAM9RL |
@@ -226,6 +261,24 @@ config USB_AT91 | |||
226 | depends on USB_GADGET_AT91 | 261 | depends on USB_GADGET_AT91 |
227 | default USB_GADGET | 262 | default USB_GADGET |
228 | 263 | ||
264 | config USB_GADGET_M66592 | ||
265 | boolean "M66592 driver" | ||
266 | select USB_GADGET_DUALSPEED | ||
267 | help | ||
268 | M66592 is a USB 2.0 peripheral controller. | ||
269 | |||
270 | It has seven configurable endpoints, and endpoint zero. | ||
271 | |||
272 | Say "y" to link the driver statically, or "m" to build a | ||
273 | dynamically linked module called "m66592_udc" and force all | ||
274 | gadget drivers to also be dynamically linked. | ||
275 | |||
276 | config USB_M66592 | ||
277 | tristate | ||
278 | depends on USB_GADGET_M66592 | ||
279 | default USB_GADGET | ||
280 | select USB_GADGET_SELECTED | ||
281 | |||
229 | config USB_GADGET_DUMMY_HCD | 282 | config USB_GADGET_DUMMY_HCD |
230 | boolean "Dummy HCD (DEVELOPMENT)" | 283 | boolean "Dummy HCD (DEVELOPMENT)" |
231 | depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL | 284 | depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL |
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 5db19396631c..8ae76f738635 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -1,14 +1,20 @@ | |||
1 | # | 1 | # |
2 | # USB peripheral controller drivers | 2 | # USB peripheral controller drivers |
3 | # | 3 | # |
4 | ifeq ($(CONFIG_USB_GADGET_DEBUG),y) | ||
5 | EXTRA_CFLAGS += -DDEBUG | ||
6 | endif | ||
7 | |||
4 | obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o | 8 | obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o |
5 | obj-$(CONFIG_USB_NET2280) += net2280.o | 9 | obj-$(CONFIG_USB_NET2280) += net2280.o |
6 | obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o | 10 | obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o |
7 | obj-$(CONFIG_USB_GOKU) += goku_udc.o | 11 | obj-$(CONFIG_USB_GOKU) += goku_udc.o |
8 | obj-$(CONFIG_USB_OMAP) += omap_udc.o | 12 | obj-$(CONFIG_USB_OMAP) += omap_udc.o |
9 | obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o | 13 | obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o |
14 | obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o | ||
10 | obj-$(CONFIG_USB_AT91) += at91_udc.o | 15 | obj-$(CONFIG_USB_AT91) += at91_udc.o |
11 | obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o | 16 | obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o |
17 | obj-$(CONFIG_USB_M66592) += m66592-udc.o | ||
12 | 18 | ||
13 | # | 19 | # |
14 | # USB gadget drivers | 20 | # USB gadget drivers |
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index ba163f35bf21..63d7d6568699 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c | |||
@@ -601,25 +601,6 @@ static void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req) | |||
601 | kfree(req); | 601 | kfree(req); |
602 | } | 602 | } |
603 | 603 | ||
604 | static void *at91_ep_alloc_buffer( | ||
605 | struct usb_ep *_ep, | ||
606 | unsigned bytes, | ||
607 | dma_addr_t *dma, | ||
608 | gfp_t gfp_flags) | ||
609 | { | ||
610 | *dma = ~0; | ||
611 | return kmalloc(bytes, gfp_flags); | ||
612 | } | ||
613 | |||
614 | static void at91_ep_free_buffer( | ||
615 | struct usb_ep *ep, | ||
616 | void *buf, | ||
617 | dma_addr_t dma, | ||
618 | unsigned bytes) | ||
619 | { | ||
620 | kfree(buf); | ||
621 | } | ||
622 | |||
623 | static int at91_ep_queue(struct usb_ep *_ep, | 604 | static int at91_ep_queue(struct usb_ep *_ep, |
624 | struct usb_request *_req, gfp_t gfp_flags) | 605 | struct usb_request *_req, gfp_t gfp_flags) |
625 | { | 606 | { |
@@ -788,8 +769,6 @@ static const struct usb_ep_ops at91_ep_ops = { | |||
788 | .disable = at91_ep_disable, | 769 | .disable = at91_ep_disable, |
789 | .alloc_request = at91_ep_alloc_request, | 770 | .alloc_request = at91_ep_alloc_request, |
790 | .free_request = at91_ep_free_request, | 771 | .free_request = at91_ep_free_request, |
791 | .alloc_buffer = at91_ep_alloc_buffer, | ||
792 | .free_buffer = at91_ep_free_buffer, | ||
793 | .queue = at91_ep_queue, | 772 | .queue = at91_ep_queue, |
794 | .dequeue = at91_ep_dequeue, | 773 | .dequeue = at91_ep_dequeue, |
795 | .set_halt = at91_ep_set_halt, | 774 | .set_halt = at91_ep_set_halt, |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index fcb5526cb085..f2fbdc7fe376 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -497,38 +497,6 @@ dummy_free_request (struct usb_ep *_ep, struct usb_request *_req) | |||
497 | kfree (req); | 497 | kfree (req); |
498 | } | 498 | } |
499 | 499 | ||
500 | static void * | ||
501 | dummy_alloc_buffer ( | ||
502 | struct usb_ep *_ep, | ||
503 | unsigned bytes, | ||
504 | dma_addr_t *dma, | ||
505 | gfp_t mem_flags | ||
506 | ) { | ||
507 | char *retval; | ||
508 | struct dummy_ep *ep; | ||
509 | struct dummy *dum; | ||
510 | |||
511 | ep = usb_ep_to_dummy_ep (_ep); | ||
512 | dum = ep_to_dummy (ep); | ||
513 | |||
514 | if (!dum->driver) | ||
515 | return NULL; | ||
516 | retval = kmalloc (bytes, mem_flags); | ||
517 | *dma = (dma_addr_t) retval; | ||
518 | return retval; | ||
519 | } | ||
520 | |||
521 | static void | ||
522 | dummy_free_buffer ( | ||
523 | struct usb_ep *_ep, | ||
524 | void *buf, | ||
525 | dma_addr_t dma, | ||
526 | unsigned bytes | ||
527 | ) { | ||
528 | if (bytes) | ||
529 | kfree (buf); | ||
530 | } | ||
531 | |||
532 | static void | 500 | static void |
533 | fifo_complete (struct usb_ep *ep, struct usb_request *req) | 501 | fifo_complete (struct usb_ep *ep, struct usb_request *req) |
534 | { | 502 | { |
@@ -659,10 +627,6 @@ static const struct usb_ep_ops dummy_ep_ops = { | |||
659 | .alloc_request = dummy_alloc_request, | 627 | .alloc_request = dummy_alloc_request, |
660 | .free_request = dummy_free_request, | 628 | .free_request = dummy_free_request, |
661 | 629 | ||
662 | .alloc_buffer = dummy_alloc_buffer, | ||
663 | .free_buffer = dummy_free_buffer, | ||
664 | /* map, unmap, ... eventually hook the "generic" dma calls */ | ||
665 | |||
666 | .queue = dummy_queue, | 630 | .queue = dummy_queue, |
667 | .dequeue = dummy_dequeue, | 631 | .dequeue = dummy_dequeue, |
668 | 632 | ||
@@ -1784,8 +1748,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd) | |||
1784 | 1748 | ||
1785 | spin_lock_irq (&dum->lock); | 1749 | spin_lock_irq (&dum->lock); |
1786 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 1750 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { |
1787 | dev_warn (&hcd->self.root_hub->dev, "HC isn't running!\n"); | 1751 | rc = -ESHUTDOWN; |
1788 | rc = -ENODEV; | ||
1789 | } else { | 1752 | } else { |
1790 | dum->rh_state = DUMMY_RH_RUNNING; | 1753 | dum->rh_state = DUMMY_RH_RUNNING; |
1791 | set_link_state (dum); | 1754 | set_link_state (dum); |
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 325bf7cfb83f..dbaf867436df 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -277,7 +277,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); | |||
277 | #define DEV_CONFIG_CDC | 277 | #define DEV_CONFIG_CDC |
278 | #endif | 278 | #endif |
279 | 279 | ||
280 | #ifdef CONFIG_USB_GADGET_HUSB2DEV | 280 | #ifdef CONFIG_USB_GADGET_ATMEL_USBA |
281 | #define DEV_CONFIG_CDC | 281 | #define DEV_CONFIG_CDC |
282 | #endif | 282 | #endif |
283 | 283 | ||
@@ -292,7 +292,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); | |||
292 | #define DEV_CONFIG_SUBSET | 292 | #define DEV_CONFIG_SUBSET |
293 | #endif | 293 | #endif |
294 | 294 | ||
295 | #ifdef CONFIG_USB_GADGET_SH | 295 | #ifdef CONFIG_USB_GADGET_SUPERH |
296 | #define DEV_CONFIG_SUBSET | 296 | #define DEV_CONFIG_SUBSET |
297 | #endif | 297 | #endif |
298 | 298 | ||
@@ -301,6 +301,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); | |||
301 | #define DEV_CONFIG_SUBSET | 301 | #define DEV_CONFIG_SUBSET |
302 | #endif | 302 | #endif |
303 | 303 | ||
304 | #ifdef CONFIG_USB_GADGET_M66592 | ||
305 | #define DEV_CONFIG_CDC | ||
306 | #endif | ||
307 | |||
304 | 308 | ||
305 | /*-------------------------------------------------------------------------*/ | 309 | /*-------------------------------------------------------------------------*/ |
306 | 310 | ||
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 4639b629e60c..8712ef987179 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c | |||
@@ -3733,19 +3733,12 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) | |||
3733 | } | 3733 | } |
3734 | 3734 | ||
3735 | /* Free the data buffers */ | 3735 | /* Free the data buffers */ |
3736 | for (i = 0; i < NUM_BUFFERS; ++i) { | 3736 | for (i = 0; i < NUM_BUFFERS; ++i) |
3737 | struct fsg_buffhd *bh = &fsg->buffhds[i]; | 3737 | kfree(fsg->buffhds[i].buf); |
3738 | |||
3739 | if (bh->buf) | ||
3740 | usb_ep_free_buffer(fsg->bulk_in, bh->buf, bh->dma, | ||
3741 | mod_data.buflen); | ||
3742 | } | ||
3743 | 3738 | ||
3744 | /* Free the request and buffer for endpoint 0 */ | 3739 | /* Free the request and buffer for endpoint 0 */ |
3745 | if (req) { | 3740 | if (req) { |
3746 | if (req->buf) | 3741 | kfree(req->buf); |
3747 | usb_ep_free_buffer(fsg->ep0, req->buf, | ||
3748 | req->dma, EP0_BUFSIZE); | ||
3749 | usb_ep_free_request(fsg->ep0, req); | 3742 | usb_ep_free_request(fsg->ep0, req); |
3750 | } | 3743 | } |
3751 | 3744 | ||
@@ -3963,8 +3956,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3963 | #endif | 3956 | #endif |
3964 | 3957 | ||
3965 | if (gadget->is_otg) { | 3958 | if (gadget->is_otg) { |
3966 | otg_desc.bmAttributes |= USB_OTG_HNP, | 3959 | otg_desc.bmAttributes |= USB_OTG_HNP; |
3967 | config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; | ||
3968 | } | 3960 | } |
3969 | 3961 | ||
3970 | rc = -ENOMEM; | 3962 | rc = -ENOMEM; |
@@ -3973,8 +3965,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3973 | fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL); | 3965 | fsg->ep0req = req = usb_ep_alloc_request(fsg->ep0, GFP_KERNEL); |
3974 | if (!req) | 3966 | if (!req) |
3975 | goto out; | 3967 | goto out; |
3976 | req->buf = usb_ep_alloc_buffer(fsg->ep0, EP0_BUFSIZE, | 3968 | req->buf = kmalloc(EP0_BUFSIZE, GFP_KERNEL); |
3977 | &req->dma, GFP_KERNEL); | ||
3978 | if (!req->buf) | 3969 | if (!req->buf) |
3979 | goto out; | 3970 | goto out; |
3980 | req->complete = ep0_complete; | 3971 | req->complete = ep0_complete; |
@@ -3986,8 +3977,7 @@ static int __init fsg_bind(struct usb_gadget *gadget) | |||
3986 | /* Allocate for the bulk-in endpoint. We assume that | 3977 | /* Allocate for the bulk-in endpoint. We assume that |
3987 | * the buffer will also work with the bulk-out (and | 3978 | * the buffer will also work with the bulk-out (and |
3988 | * interrupt-in) endpoint. */ | 3979 | * interrupt-in) endpoint. */ |
3989 | bh->buf = usb_ep_alloc_buffer(fsg->bulk_in, mod_data.buflen, | 3980 | bh->buf = kmalloc(mod_data.buflen, GFP_KERNEL); |
3990 | &bh->dma, GFP_KERNEL); | ||
3991 | if (!bh->buf) | 3981 | if (!bh->buf) |
3992 | goto out; | 3982 | goto out; |
3993 | bh->next = bh + 1; | 3983 | bh->next = bh + 1; |
diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index 3ca2b3159f00..10b2b33b8698 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c | |||
@@ -228,7 +228,7 @@ static int dr_controller_setup(struct fsl_udc *udc) | |||
228 | 228 | ||
229 | /* Config PHY interface */ | 229 | /* Config PHY interface */ |
230 | portctrl = fsl_readl(&dr_regs->portsc1); | 230 | portctrl = fsl_readl(&dr_regs->portsc1); |
231 | portctrl &= ~(PORTSCX_PHY_TYPE_SEL & PORTSCX_PORT_WIDTH); | 231 | portctrl &= ~(PORTSCX_PHY_TYPE_SEL | PORTSCX_PORT_WIDTH); |
232 | switch (udc->phy_mode) { | 232 | switch (udc->phy_mode) { |
233 | case FSL_USB2_PHY_ULPI: | 233 | case FSL_USB2_PHY_ULPI: |
234 | portctrl |= PORTSCX_PTS_ULPI; | 234 | portctrl |= PORTSCX_PTS_ULPI; |
@@ -601,39 +601,6 @@ static void fsl_free_request(struct usb_ep *_ep, struct usb_request *_req) | |||
601 | kfree(req); | 601 | kfree(req); |
602 | } | 602 | } |
603 | 603 | ||
604 | /*------------------------------------------------------------------ | ||
605 | * Allocate an I/O buffer | ||
606 | *---------------------------------------------------------------------*/ | ||
607 | static void *fsl_alloc_buffer(struct usb_ep *_ep, unsigned bytes, | ||
608 | dma_addr_t *dma, gfp_t gfp_flags) | ||
609 | { | ||
610 | struct fsl_ep *ep; | ||
611 | |||
612 | if (!_ep) | ||
613 | return NULL; | ||
614 | |||
615 | ep = container_of(_ep, struct fsl_ep, ep); | ||
616 | |||
617 | return dma_alloc_coherent(ep->udc->gadget.dev.parent, | ||
618 | bytes, dma, gfp_flags); | ||
619 | } | ||
620 | |||
621 | /*------------------------------------------------------------------ | ||
622 | * frees an i/o buffer | ||
623 | *---------------------------------------------------------------------*/ | ||
624 | static void fsl_free_buffer(struct usb_ep *_ep, void *buf, | ||
625 | dma_addr_t dma, unsigned bytes) | ||
626 | { | ||
627 | struct fsl_ep *ep; | ||
628 | |||
629 | if (!_ep) | ||
630 | return; | ||
631 | |||
632 | ep = container_of(_ep, struct fsl_ep, ep); | ||
633 | |||
634 | dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma); | ||
635 | } | ||
636 | |||
637 | /*-------------------------------------------------------------------------*/ | 604 | /*-------------------------------------------------------------------------*/ |
638 | static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) | 605 | static int fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) |
639 | { | 606 | { |
@@ -1047,9 +1014,6 @@ static struct usb_ep_ops fsl_ep_ops = { | |||
1047 | .alloc_request = fsl_alloc_request, | 1014 | .alloc_request = fsl_alloc_request, |
1048 | .free_request = fsl_free_request, | 1015 | .free_request = fsl_free_request, |
1049 | 1016 | ||
1050 | .alloc_buffer = fsl_alloc_buffer, | ||
1051 | .free_buffer = fsl_free_buffer, | ||
1052 | |||
1053 | .queue = fsl_ep_queue, | 1017 | .queue = fsl_ep_queue, |
1054 | .dequeue = fsl_ep_dequeue, | 1018 | .dequeue = fsl_ep_dequeue, |
1055 | 1019 | ||
@@ -2189,27 +2153,19 @@ static void fsl_udc_release(struct device *dev) | |||
2189 | * init resource for globle controller | 2153 | * init resource for globle controller |
2190 | * Return the udc handle on success or NULL on failure | 2154 | * Return the udc handle on success or NULL on failure |
2191 | ------------------------------------------------------------------*/ | 2155 | ------------------------------------------------------------------*/ |
2192 | static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev) | 2156 | static int __init struct_udc_setup(struct fsl_udc *udc, |
2157 | struct platform_device *pdev) | ||
2193 | { | 2158 | { |
2194 | struct fsl_udc *udc; | ||
2195 | struct fsl_usb2_platform_data *pdata; | 2159 | struct fsl_usb2_platform_data *pdata; |
2196 | size_t size; | 2160 | size_t size; |
2197 | 2161 | ||
2198 | udc = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); | ||
2199 | if (udc == NULL) { | ||
2200 | ERR("malloc udc failed\n"); | ||
2201 | return NULL; | ||
2202 | } | ||
2203 | |||
2204 | pdata = pdev->dev.platform_data; | 2162 | pdata = pdev->dev.platform_data; |
2205 | udc->phy_mode = pdata->phy_mode; | 2163 | udc->phy_mode = pdata->phy_mode; |
2206 | /* max_ep_nr is bidirectional ep number, max_ep doubles the number */ | ||
2207 | udc->max_ep = pdata->max_ep_nr * 2; | ||
2208 | 2164 | ||
2209 | udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL); | 2165 | udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL); |
2210 | if (!udc->eps) { | 2166 | if (!udc->eps) { |
2211 | ERR("malloc fsl_ep failed\n"); | 2167 | ERR("malloc fsl_ep failed\n"); |
2212 | goto cleanup; | 2168 | return -1; |
2213 | } | 2169 | } |
2214 | 2170 | ||
2215 | /* initialized QHs, take care of alignment */ | 2171 | /* initialized QHs, take care of alignment */ |
@@ -2225,7 +2181,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev) | |||
2225 | if (!udc->ep_qh) { | 2181 | if (!udc->ep_qh) { |
2226 | ERR("malloc QHs for udc failed\n"); | 2182 | ERR("malloc QHs for udc failed\n"); |
2227 | kfree(udc->eps); | 2183 | kfree(udc->eps); |
2228 | goto cleanup; | 2184 | return -1; |
2229 | } | 2185 | } |
2230 | 2186 | ||
2231 | udc->ep_qh_size = size; | 2187 | udc->ep_qh_size = size; |
@@ -2244,11 +2200,7 @@ static struct fsl_udc *__init struct_udc_setup(struct platform_device *pdev) | |||
2244 | udc->remote_wakeup = 0; /* default to 0 on reset */ | 2200 | udc->remote_wakeup = 0; /* default to 0 on reset */ |
2245 | spin_lock_init(&udc->lock); | 2201 | spin_lock_init(&udc->lock); |
2246 | 2202 | ||
2247 | return udc; | 2203 | return 0; |
2248 | |||
2249 | cleanup: | ||
2250 | kfree(udc); | ||
2251 | return NULL; | ||
2252 | } | 2204 | } |
2253 | 2205 | ||
2254 | /*---------------------------------------------------------------- | 2206 | /*---------------------------------------------------------------- |
@@ -2287,35 +2239,37 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index, | |||
2287 | } | 2239 | } |
2288 | 2240 | ||
2289 | /* Driver probe function | 2241 | /* Driver probe function |
2290 | * all intialize operations implemented here except enabling usb_intr reg | 2242 | * all intialization operations implemented here except enabling usb_intr reg |
2243 | * board setup should have been done in the platform code | ||
2291 | */ | 2244 | */ |
2292 | static int __init fsl_udc_probe(struct platform_device *pdev) | 2245 | static int __init fsl_udc_probe(struct platform_device *pdev) |
2293 | { | 2246 | { |
2294 | struct resource *res; | 2247 | struct resource *res; |
2295 | int ret = -ENODEV; | 2248 | int ret = -ENODEV; |
2296 | unsigned int i; | 2249 | unsigned int i; |
2250 | u32 dccparams; | ||
2297 | 2251 | ||
2298 | if (strcmp(pdev->name, driver_name)) { | 2252 | if (strcmp(pdev->name, driver_name)) { |
2299 | VDBG("Wrong device\n"); | 2253 | VDBG("Wrong device\n"); |
2300 | return -ENODEV; | 2254 | return -ENODEV; |
2301 | } | 2255 | } |
2302 | 2256 | ||
2303 | /* board setup should have been done in the platform code */ | 2257 | udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); |
2304 | 2258 | if (udc_controller == NULL) { | |
2305 | /* Initialize the udc structure including QH member and other member */ | 2259 | ERR("malloc udc failed\n"); |
2306 | udc_controller = struct_udc_setup(pdev); | ||
2307 | if (!udc_controller) { | ||
2308 | VDBG("udc_controller is NULL \n"); | ||
2309 | return -ENOMEM; | 2260 | return -ENOMEM; |
2310 | } | 2261 | } |
2311 | 2262 | ||
2312 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 2263 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
2313 | if (!res) | 2264 | if (!res) { |
2265 | kfree(udc_controller); | ||
2314 | return -ENXIO; | 2266 | return -ENXIO; |
2267 | } | ||
2315 | 2268 | ||
2316 | if (!request_mem_region(res->start, res->end - res->start + 1, | 2269 | if (!request_mem_region(res->start, res->end - res->start + 1, |
2317 | driver_name)) { | 2270 | driver_name)) { |
2318 | ERR("request mem region for %s failed \n", pdev->name); | 2271 | ERR("request mem region for %s failed \n", pdev->name); |
2272 | kfree(udc_controller); | ||
2319 | return -EBUSY; | 2273 | return -EBUSY; |
2320 | } | 2274 | } |
2321 | 2275 | ||
@@ -2328,13 +2282,24 @@ static int __init fsl_udc_probe(struct platform_device *pdev) | |||
2328 | usb_sys_regs = (struct usb_sys_interface *) | 2282 | usb_sys_regs = (struct usb_sys_interface *) |
2329 | ((u32)dr_regs + USB_DR_SYS_OFFSET); | 2283 | ((u32)dr_regs + USB_DR_SYS_OFFSET); |
2330 | 2284 | ||
2285 | /* Read Device Controller Capability Parameters register */ | ||
2286 | dccparams = fsl_readl(&dr_regs->dccparams); | ||
2287 | if (!(dccparams & DCCPARAMS_DC)) { | ||
2288 | ERR("This SOC doesn't support device role\n"); | ||
2289 | ret = -ENODEV; | ||
2290 | goto err2; | ||
2291 | } | ||
2292 | /* Get max device endpoints */ | ||
2293 | /* DEN is bidirectional ep number, max_ep doubles the number */ | ||
2294 | udc_controller->max_ep = (dccparams & DCCPARAMS_DEN_MASK) * 2; | ||
2295 | |||
2331 | udc_controller->irq = platform_get_irq(pdev, 0); | 2296 | udc_controller->irq = platform_get_irq(pdev, 0); |
2332 | if (!udc_controller->irq) { | 2297 | if (!udc_controller->irq) { |
2333 | ret = -ENODEV; | 2298 | ret = -ENODEV; |
2334 | goto err2; | 2299 | goto err2; |
2335 | } | 2300 | } |
2336 | 2301 | ||
2337 | ret = request_irq(udc_controller->irq, fsl_udc_irq, SA_SHIRQ, | 2302 | ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED, |
2338 | driver_name, udc_controller); | 2303 | driver_name, udc_controller); |
2339 | if (ret != 0) { | 2304 | if (ret != 0) { |
2340 | ERR("cannot request irq %d err %d \n", | 2305 | ERR("cannot request irq %d err %d \n", |
@@ -2342,6 +2307,13 @@ static int __init fsl_udc_probe(struct platform_device *pdev) | |||
2342 | goto err2; | 2307 | goto err2; |
2343 | } | 2308 | } |
2344 | 2309 | ||
2310 | /* Initialize the udc structure including QH member and other member */ | ||
2311 | if (struct_udc_setup(udc_controller, pdev)) { | ||
2312 | ERR("Can't initialize udc data structure\n"); | ||
2313 | ret = -ENOMEM; | ||
2314 | goto err3; | ||
2315 | } | ||
2316 | |||
2345 | /* initialize usb hw reg except for regs for EP, | 2317 | /* initialize usb hw reg except for regs for EP, |
2346 | * leave usbintr reg untouched */ | 2318 | * leave usbintr reg untouched */ |
2347 | dr_controller_setup(udc_controller); | 2319 | dr_controller_setup(udc_controller); |
@@ -2403,6 +2375,7 @@ err2: | |||
2403 | iounmap(dr_regs); | 2375 | iounmap(dr_regs); |
2404 | err1: | 2376 | err1: |
2405 | release_mem_region(res->start, res->end - res->start + 1); | 2377 | release_mem_region(res->start, res->end - res->start + 1); |
2378 | kfree(udc_controller); | ||
2406 | return ret; | 2379 | return ret; |
2407 | } | 2380 | } |
2408 | 2381 | ||
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index c6291e046507..832ab82b4882 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h | |||
@@ -101,6 +101,10 @@ struct usb_sys_interface { | |||
101 | #define WAIT_FOR_OUT_STATUS 3 | 101 | #define WAIT_FOR_OUT_STATUS 3 |
102 | #define DATA_STATE_RECV 4 | 102 | #define DATA_STATE_RECV 4 |
103 | 103 | ||
104 | /* Device Controller Capability Parameter register */ | ||
105 | #define DCCPARAMS_DC 0x00000080 | ||
106 | #define DCCPARAMS_DEN_MASK 0x0000001f | ||
107 | |||
104 | /* Frame Index Register Bit Masks */ | 108 | /* Frame Index Register Bit Masks */ |
105 | #define USB_FRINDEX_MASKS 0x3fff | 109 | #define USB_FRINDEX_MASKS 0x3fff |
106 | /* USB CMD Register Bit Masks */ | 110 | /* USB CMD Register Bit Masks */ |
diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index d041b919e7b8..53e9139ba388 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h | |||
@@ -8,6 +8,8 @@ | |||
8 | * (And avoiding all runtime comparisons in typical one-choice configs!) | 8 | * (And avoiding all runtime comparisons in typical one-choice configs!) |
9 | * | 9 | * |
10 | * NOTE: some of these controller drivers may not be available yet. | 10 | * NOTE: some of these controller drivers may not be available yet. |
11 | * Some are available on 2.4 kernels; several are available, but not | ||
12 | * yet pushed in the 2.6 mainline tree. | ||
11 | */ | 13 | */ |
12 | #ifdef CONFIG_USB_GADGET_NET2280 | 14 | #ifdef CONFIG_USB_GADGET_NET2280 |
13 | #define gadget_is_net2280(g) !strcmp("net2280", (g)->name) | 15 | #define gadget_is_net2280(g) !strcmp("net2280", (g)->name) |
@@ -33,12 +35,14 @@ | |||
33 | #define gadget_is_goku(g) 0 | 35 | #define gadget_is_goku(g) 0 |
34 | #endif | 36 | #endif |
35 | 37 | ||
38 | /* SH3 UDC -- not yet ported 2.4 --> 2.6 */ | ||
36 | #ifdef CONFIG_USB_GADGET_SUPERH | 39 | #ifdef CONFIG_USB_GADGET_SUPERH |
37 | #define gadget_is_sh(g) !strcmp("sh_udc", (g)->name) | 40 | #define gadget_is_sh(g) !strcmp("sh_udc", (g)->name) |
38 | #else | 41 | #else |
39 | #define gadget_is_sh(g) 0 | 42 | #define gadget_is_sh(g) 0 |
40 | #endif | 43 | #endif |
41 | 44 | ||
45 | /* not yet stable on 2.6 (would help "original Zaurus") */ | ||
42 | #ifdef CONFIG_USB_GADGET_SA1100 | 46 | #ifdef CONFIG_USB_GADGET_SA1100 |
43 | #define gadget_is_sa1100(g) !strcmp("sa1100_udc", (g)->name) | 47 | #define gadget_is_sa1100(g) !strcmp("sa1100_udc", (g)->name) |
44 | #else | 48 | #else |
@@ -51,6 +55,7 @@ | |||
51 | #define gadget_is_lh7a40x(g) 0 | 55 | #define gadget_is_lh7a40x(g) 0 |
52 | #endif | 56 | #endif |
53 | 57 | ||
58 | /* handhelds.org tree (?) */ | ||
54 | #ifdef CONFIG_USB_GADGET_MQ11XX | 59 | #ifdef CONFIG_USB_GADGET_MQ11XX |
55 | #define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name) | 60 | #define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name) |
56 | #else | 61 | #else |
@@ -63,22 +68,24 @@ | |||
63 | #define gadget_is_omap(g) 0 | 68 | #define gadget_is_omap(g) 0 |
64 | #endif | 69 | #endif |
65 | 70 | ||
71 | /* not yet ported 2.4 --> 2.6 */ | ||
66 | #ifdef CONFIG_USB_GADGET_N9604 | 72 | #ifdef CONFIG_USB_GADGET_N9604 |
67 | #define gadget_is_n9604(g) !strcmp("n9604_udc", (g)->name) | 73 | #define gadget_is_n9604(g) !strcmp("n9604_udc", (g)->name) |
68 | #else | 74 | #else |
69 | #define gadget_is_n9604(g) 0 | 75 | #define gadget_is_n9604(g) 0 |
70 | #endif | 76 | #endif |
71 | 77 | ||
78 | /* various unstable versions available */ | ||
72 | #ifdef CONFIG_USB_GADGET_PXA27X | 79 | #ifdef CONFIG_USB_GADGET_PXA27X |
73 | #define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name) | 80 | #define gadget_is_pxa27x(g) !strcmp("pxa27x_udc", (g)->name) |
74 | #else | 81 | #else |
75 | #define gadget_is_pxa27x(g) 0 | 82 | #define gadget_is_pxa27x(g) 0 |
76 | #endif | 83 | #endif |
77 | 84 | ||
78 | #ifdef CONFIG_USB_GADGET_HUSB2DEV | 85 | #ifdef CONFIG_USB_GADGET_ATMEL_USBA |
79 | #define gadget_is_husb2dev(g) !strcmp("husb2_udc", (g)->name) | 86 | #define gadget_is_atmel_usba(g) !strcmp("atmel_usba_udc", (g)->name) |
80 | #else | 87 | #else |
81 | #define gadget_is_husb2dev(g) 0 | 88 | #define gadget_is_atmel_usba(g) 0 |
82 | #endif | 89 | #endif |
83 | 90 | ||
84 | #ifdef CONFIG_USB_GADGET_S3C2410 | 91 | #ifdef CONFIG_USB_GADGET_S3C2410 |
@@ -93,6 +100,7 @@ | |||
93 | #define gadget_is_at91(g) 0 | 100 | #define gadget_is_at91(g) 0 |
94 | #endif | 101 | #endif |
95 | 102 | ||
103 | /* status unclear */ | ||
96 | #ifdef CONFIG_USB_GADGET_IMX | 104 | #ifdef CONFIG_USB_GADGET_IMX |
97 | #define gadget_is_imx(g) !strcmp("imx_udc", (g)->name) | 105 | #define gadget_is_imx(g) !strcmp("imx_udc", (g)->name) |
98 | #else | 106 | #else |
@@ -106,6 +114,7 @@ | |||
106 | #endif | 114 | #endif |
107 | 115 | ||
108 | /* Mentor high speed function controller */ | 116 | /* Mentor high speed function controller */ |
117 | /* from Montavista kernel (?) */ | ||
109 | #ifdef CONFIG_USB_GADGET_MUSBHSFC | 118 | #ifdef CONFIG_USB_GADGET_MUSBHSFC |
110 | #define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name) | 119 | #define gadget_is_musbhsfc(g) !strcmp("musbhsfc_udc", (g)->name) |
111 | #else | 120 | #else |
@@ -119,12 +128,20 @@ | |||
119 | #define gadget_is_musbhdrc(g) 0 | 128 | #define gadget_is_musbhdrc(g) 0 |
120 | #endif | 129 | #endif |
121 | 130 | ||
131 | /* from Montavista kernel (?) */ | ||
122 | #ifdef CONFIG_USB_GADGET_MPC8272 | 132 | #ifdef CONFIG_USB_GADGET_MPC8272 |
123 | #define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name) | 133 | #define gadget_is_mpc8272(g) !strcmp("mpc8272_udc", (g)->name) |
124 | #else | 134 | #else |
125 | #define gadget_is_mpc8272(g) 0 | 135 | #define gadget_is_mpc8272(g) 0 |
126 | #endif | 136 | #endif |
127 | 137 | ||
138 | #ifdef CONFIG_USB_GADGET_M66592 | ||
139 | #define gadget_is_m66592(g) !strcmp("m66592_udc", (g)->name) | ||
140 | #else | ||
141 | #define gadget_is_m66592(g) 0 | ||
142 | #endif | ||
143 | |||
144 | |||
128 | // CONFIG_USB_GADGET_SX2 | 145 | // CONFIG_USB_GADGET_SX2 |
129 | // CONFIG_USB_GADGET_AU1X00 | 146 | // CONFIG_USB_GADGET_AU1X00 |
130 | // ... | 147 | // ... |
@@ -181,9 +198,11 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) | |||
181 | return 0x16; | 198 | return 0x16; |
182 | else if (gadget_is_mpc8272(gadget)) | 199 | else if (gadget_is_mpc8272(gadget)) |
183 | return 0x17; | 200 | return 0x17; |
184 | else if (gadget_is_husb2dev(gadget)) | 201 | else if (gadget_is_atmel_usba(gadget)) |
185 | return 0x18; | 202 | return 0x18; |
186 | else if (gadget_is_fsl_usb2(gadget)) | 203 | else if (gadget_is_fsl_usb2(gadget)) |
187 | return 0x19; | 204 | return 0x19; |
205 | else if (gadget_is_m66592(gadget)) | ||
206 | return 0x20; | ||
188 | return -ENOENT; | 207 | return -ENOENT; |
189 | } | 208 | } |
diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index d08a8d0e6427..1c5aa49d7432 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c | |||
@@ -1248,17 +1248,11 @@ autoconf_fail: | |||
1248 | tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev); | 1248 | tasklet_init(&dev->tasklet, gmidi_in_tasklet, (unsigned long)dev); |
1249 | 1249 | ||
1250 | /* preallocate control response and buffer */ | 1250 | /* preallocate control response and buffer */ |
1251 | dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); | 1251 | dev->req = alloc_ep_req(gadget->ep0, USB_BUFSIZ); |
1252 | if (!dev->req) { | 1252 | if (!dev->req) { |
1253 | err = -ENOMEM; | 1253 | err = -ENOMEM; |
1254 | goto fail; | 1254 | goto fail; |
1255 | } | 1255 | } |
1256 | dev->req->buf = usb_ep_alloc_buffer(gadget->ep0, USB_BUFSIZ, | ||
1257 | &dev->req->dma, GFP_KERNEL); | ||
1258 | if (!dev->req->buf) { | ||
1259 | err = -ENOMEM; | ||
1260 | goto fail; | ||
1261 | } | ||
1262 | 1256 | ||
1263 | dev->req->complete = gmidi_setup_complete; | 1257 | dev->req->complete = gmidi_setup_complete; |
1264 | 1258 | ||
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index ae931af05cef..d6c5f1150ae7 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c | |||
@@ -20,7 +20,6 @@ | |||
20 | * - DMA works with ep1 (OUT transfers) and ep2 (IN transfers). | 20 | * - DMA works with ep1 (OUT transfers) and ep2 (IN transfers). |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #undef DEBUG | ||
24 | // #define VERBOSE /* extra debug messages (success too) */ | 23 | // #define VERBOSE /* extra debug messages (success too) */ |
25 | // #define USB_TRACE /* packet-level success messages */ | 24 | // #define USB_TRACE /* packet-level success messages */ |
26 | 25 | ||
@@ -296,51 +295,6 @@ goku_free_request(struct usb_ep *_ep, struct usb_request *_req) | |||
296 | 295 | ||
297 | /*-------------------------------------------------------------------------*/ | 296 | /*-------------------------------------------------------------------------*/ |
298 | 297 | ||
299 | /* allocating buffers this way eliminates dma mapping overhead, which | ||
300 | * on some platforms will mean eliminating a per-io buffer copy. with | ||
301 | * some kinds of system caches, further tweaks may still be needed. | ||
302 | */ | ||
303 | static void * | ||
304 | goku_alloc_buffer(struct usb_ep *_ep, unsigned bytes, | ||
305 | dma_addr_t *dma, gfp_t gfp_flags) | ||
306 | { | ||
307 | void *retval; | ||
308 | struct goku_ep *ep; | ||
309 | |||
310 | ep = container_of(_ep, struct goku_ep, ep); | ||
311 | if (!_ep) | ||
312 | return NULL; | ||
313 | *dma = DMA_ADDR_INVALID; | ||
314 | |||
315 | if (ep->dma) { | ||
316 | /* the main problem with this call is that it wastes memory | ||
317 | * on typical 1/N page allocations: it allocates 1-N pages. | ||
318 | */ | ||
319 | #warning Using dma_alloc_coherent even with buffers smaller than a page. | ||
320 | retval = dma_alloc_coherent(&ep->dev->pdev->dev, | ||
321 | bytes, dma, gfp_flags); | ||
322 | } else | ||
323 | retval = kmalloc(bytes, gfp_flags); | ||
324 | return retval; | ||
325 | } | ||
326 | |||
327 | static void | ||
328 | goku_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, unsigned bytes) | ||
329 | { | ||
330 | /* free memory into the right allocator */ | ||
331 | if (dma != DMA_ADDR_INVALID) { | ||
332 | struct goku_ep *ep; | ||
333 | |||
334 | ep = container_of(_ep, struct goku_ep, ep); | ||
335 | if (!_ep) | ||
336 | return; | ||
337 | dma_free_coherent(&ep->dev->pdev->dev, bytes, buf, dma); | ||
338 | } else | ||
339 | kfree (buf); | ||
340 | } | ||
341 | |||
342 | /*-------------------------------------------------------------------------*/ | ||
343 | |||
344 | static void | 298 | static void |
345 | done(struct goku_ep *ep, struct goku_request *req, int status) | 299 | done(struct goku_ep *ep, struct goku_request *req, int status) |
346 | { | 300 | { |
@@ -485,7 +439,7 @@ top: | |||
485 | /* use ep1/ep2 double-buffering for OUT */ | 439 | /* use ep1/ep2 double-buffering for OUT */ |
486 | if (!(size & PACKET_ACTIVE)) | 440 | if (!(size & PACKET_ACTIVE)) |
487 | size = readl(®s->EPxSizeLB[ep->num]); | 441 | size = readl(®s->EPxSizeLB[ep->num]); |
488 | if (!(size & PACKET_ACTIVE)) // "can't happen" | 442 | if (!(size & PACKET_ACTIVE)) /* "can't happen" */ |
489 | break; | 443 | break; |
490 | size &= DATASIZE; /* EPxSizeH == 0 */ | 444 | size &= DATASIZE; /* EPxSizeH == 0 */ |
491 | 445 | ||
@@ -1026,9 +980,6 @@ static struct usb_ep_ops goku_ep_ops = { | |||
1026 | .alloc_request = goku_alloc_request, | 980 | .alloc_request = goku_alloc_request, |
1027 | .free_request = goku_free_request, | 981 | .free_request = goku_free_request, |
1028 | 982 | ||
1029 | .alloc_buffer = goku_alloc_buffer, | ||
1030 | .free_buffer = goku_free_buffer, | ||
1031 | |||
1032 | .queue = goku_queue, | 983 | .queue = goku_queue, |
1033 | .dequeue = goku_dequeue, | 984 | .dequeue = goku_dequeue, |
1034 | 985 | ||
@@ -1140,17 +1091,17 @@ udc_proc_read(char *buffer, char **start, off_t off, int count, | |||
1140 | is_usb_connected | 1091 | is_usb_connected |
1141 | ? ((tmp & PW_PULLUP) ? "full speed" : "powered") | 1092 | ? ((tmp & PW_PULLUP) ? "full speed" : "powered") |
1142 | : "disconnected", | 1093 | : "disconnected", |
1143 | ({char *tmp; | 1094 | ({char *state; |
1144 | switch(dev->ep0state){ | 1095 | switch(dev->ep0state){ |
1145 | case EP0_DISCONNECT: tmp = "ep0_disconnect"; break; | 1096 | case EP0_DISCONNECT: state = "ep0_disconnect"; break; |
1146 | case EP0_IDLE: tmp = "ep0_idle"; break; | 1097 | case EP0_IDLE: state = "ep0_idle"; break; |
1147 | case EP0_IN: tmp = "ep0_in"; break; | 1098 | case EP0_IN: state = "ep0_in"; break; |
1148 | case EP0_OUT: tmp = "ep0_out"; break; | 1099 | case EP0_OUT: state = "ep0_out"; break; |
1149 | case EP0_STATUS: tmp = "ep0_status"; break; | 1100 | case EP0_STATUS: state = "ep0_status"; break; |
1150 | case EP0_STALL: tmp = "ep0_stall"; break; | 1101 | case EP0_STALL: state = "ep0_stall"; break; |
1151 | case EP0_SUSPEND: tmp = "ep0_suspend"; break; | 1102 | case EP0_SUSPEND: state = "ep0_suspend"; break; |
1152 | default: tmp = "ep0_?"; break; | 1103 | default: state = "ep0_?"; break; |
1153 | } tmp; }) | 1104 | } state; }) |
1154 | ); | 1105 | ); |
1155 | size -= t; | 1106 | size -= t; |
1156 | next += t; | 1107 | next += t; |
@@ -1195,7 +1146,6 @@ udc_proc_read(char *buffer, char **start, off_t off, int count, | |||
1195 | for (i = 0; i < 4; i++) { | 1146 | for (i = 0; i < 4; i++) { |
1196 | struct goku_ep *ep = &dev->ep [i]; | 1147 | struct goku_ep *ep = &dev->ep [i]; |
1197 | struct goku_request *req; | 1148 | struct goku_request *req; |
1198 | int t; | ||
1199 | 1149 | ||
1200 | if (i && !ep->desc) | 1150 | if (i && !ep->desc) |
1201 | continue; | 1151 | continue; |
@@ -1283,7 +1233,7 @@ done: | |||
1283 | static void udc_reinit (struct goku_udc *dev) | 1233 | static void udc_reinit (struct goku_udc *dev) |
1284 | { | 1234 | { |
1285 | static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" }; | 1235 | static char *names [] = { "ep0", "ep1-bulk", "ep2-bulk", "ep3-bulk" }; |
1286 | 1236 | ||
1287 | unsigned i; | 1237 | unsigned i; |
1288 | 1238 | ||
1289 | INIT_LIST_HEAD (&dev->gadget.ep_list); | 1239 | INIT_LIST_HEAD (&dev->gadget.ep_list); |
@@ -1896,9 +1846,9 @@ static int goku_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1896 | 1846 | ||
1897 | /* done */ | 1847 | /* done */ |
1898 | the_controller = dev; | 1848 | the_controller = dev; |
1899 | device_register(&dev->gadget.dev); | 1849 | retval = device_register(&dev->gadget.dev); |
1900 | 1850 | if (retval == 0) | |
1901 | return 0; | 1851 | return 0; |
1902 | 1852 | ||
1903 | done: | 1853 | done: |
1904 | if (dev) | 1854 | if (dev) |
@@ -1910,8 +1860,8 @@ done: | |||
1910 | /*-------------------------------------------------------------------------*/ | 1860 | /*-------------------------------------------------------------------------*/ |
1911 | 1861 | ||
1912 | static struct pci_device_id pci_ids [] = { { | 1862 | static struct pci_device_id pci_ids [] = { { |
1913 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), | 1863 | .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe), |
1914 | .class_mask = ~0, | 1864 | .class_mask = ~0, |
1915 | .vendor = 0x102f, /* Toshiba */ | 1865 | .vendor = 0x102f, /* Toshiba */ |
1916 | .device = 0x0107, /* this UDC */ | 1866 | .device = 0x0107, /* this UDC */ |
1917 | .subvendor = PCI_ANY_ID, | 1867 | .subvendor = PCI_ANY_ID, |
diff --git a/drivers/usb/gadget/goku_udc.h b/drivers/usb/gadget/goku_udc.h index ea8c8e58cabf..bc4eb1e0b507 100644 --- a/drivers/usb/gadget/goku_udc.h +++ b/drivers/usb/gadget/goku_udc.h | |||
@@ -41,8 +41,10 @@ struct goku_udc_regs { | |||
41 | #define INT_SYSERROR 0x40000 | 41 | #define INT_SYSERROR 0x40000 |
42 | #define INT_PWRDETECT 0x80000 | 42 | #define INT_PWRDETECT 0x80000 |
43 | 43 | ||
44 | #define INT_DEVWIDE (INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND) | 44 | #define INT_DEVWIDE \ |
45 | #define INT_EP0 (INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK) | 45 | (INT_PWRDETECT|INT_SYSERROR/*|INT_ERR*/|INT_USBRESET|INT_SUSPEND) |
46 | #define INT_EP0 \ | ||
47 | (INT_SETUP|INT_ENDPOINT0/*|INT_STATUS*/|INT_STATUSNAK) | ||
46 | 48 | ||
47 | u32 dma_master; | 49 | u32 dma_master; |
48 | #define MST_EOPB_DIS 0x0800 | 50 | #define MST_EOPB_DIS 0x0800 |
@@ -231,7 +233,7 @@ struct goku_request { | |||
231 | enum ep0state { | 233 | enum ep0state { |
232 | EP0_DISCONNECT, /* no host */ | 234 | EP0_DISCONNECT, /* no host */ |
233 | EP0_IDLE, /* between STATUS ack and SETUP report */ | 235 | EP0_IDLE, /* between STATUS ack and SETUP report */ |
234 | EP0_IN, EP0_OUT, /* data stage */ | 236 | EP0_IN, EP0_OUT, /* data stage */ |
235 | EP0_STATUS, /* status stage */ | 237 | EP0_STATUS, /* status stage */ |
236 | EP0_STALL, /* data or status stages */ | 238 | EP0_STALL, /* data or status stages */ |
237 | EP0_SUSPEND, /* usb suspend */ | 239 | EP0_SUSPEND, /* usb suspend */ |
@@ -242,7 +244,7 @@ struct goku_udc { | |||
242 | struct usb_gadget gadget; | 244 | struct usb_gadget gadget; |
243 | spinlock_t lock; | 245 | spinlock_t lock; |
244 | struct goku_ep ep[4]; | 246 | struct goku_ep ep[4]; |
245 | struct usb_gadget_driver *driver; | 247 | struct usb_gadget_driver *driver; |
246 | 248 | ||
247 | enum ep0state ep0state; | 249 | enum ep0state ep0state; |
248 | unsigned got_irq:1, | 250 | unsigned got_irq:1, |
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 46d0e5252744..e60745ffaf8e 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/device.h> | 37 | #include <linux/device.h> |
38 | #include <linux/moduleparam.h> | 38 | #include <linux/moduleparam.h> |
39 | 39 | ||
40 | #include <linux/usb_gadgetfs.h> | 40 | #include <linux/usb/gadgetfs.h> |
41 | #include <linux/usb_gadget.h> | 41 | #include <linux/usb_gadget.h> |
42 | 42 | ||
43 | 43 | ||
@@ -923,7 +923,7 @@ static void clean_req (struct usb_ep *ep, struct usb_request *req) | |||
923 | struct dev_data *dev = ep->driver_data; | 923 | struct dev_data *dev = ep->driver_data; |
924 | 924 | ||
925 | if (req->buf != dev->rbuf) { | 925 | if (req->buf != dev->rbuf) { |
926 | usb_ep_free_buffer (ep, req->buf, req->dma, req->length); | 926 | kfree(req->buf); |
927 | req->buf = dev->rbuf; | 927 | req->buf = dev->rbuf; |
928 | req->dma = DMA_ADDR_INVALID; | 928 | req->dma = DMA_ADDR_INVALID; |
929 | } | 929 | } |
@@ -963,7 +963,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len) | |||
963 | return -EBUSY; | 963 | return -EBUSY; |
964 | } | 964 | } |
965 | if (len > sizeof (dev->rbuf)) | 965 | if (len > sizeof (dev->rbuf)) |
966 | req->buf = usb_ep_alloc_buffer (ep, len, &req->dma, GFP_ATOMIC); | 966 | req->buf = kmalloc(len, GFP_ATOMIC); |
967 | if (req->buf == 0) { | 967 | if (req->buf == 0) { |
968 | req->buf = dev->rbuf; | 968 | req->buf = dev->rbuf; |
969 | return -ENOMEM; | 969 | return -ENOMEM; |
@@ -1505,7 +1505,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) | |||
1505 | } | 1505 | } |
1506 | break; | 1506 | break; |
1507 | 1507 | ||
1508 | #ifndef CONFIG_USB_GADGETFS_PXA2XX | 1508 | #ifndef CONFIG_USB_GADGET_PXA2XX |
1509 | /* PXA automagically handles this request too */ | 1509 | /* PXA automagically handles this request too */ |
1510 | case USB_REQ_GET_CONFIGURATION: | 1510 | case USB_REQ_GET_CONFIGURATION: |
1511 | if (ctrl->bRequestType != 0x80) | 1511 | if (ctrl->bRequestType != 0x80) |
diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index a0a73c08a344..e78c2ddc1f88 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c | |||
@@ -75,10 +75,6 @@ static int lh7a40x_ep_enable(struct usb_ep *ep, | |||
75 | static int lh7a40x_ep_disable(struct usb_ep *ep); | 75 | static int lh7a40x_ep_disable(struct usb_ep *ep); |
76 | static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t); | 76 | static struct usb_request *lh7a40x_alloc_request(struct usb_ep *ep, gfp_t); |
77 | static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *); | 77 | static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *); |
78 | static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned, dma_addr_t *, | ||
79 | gfp_t); | ||
80 | static void lh7a40x_free_buffer(struct usb_ep *ep, void *, dma_addr_t, | ||
81 | unsigned); | ||
82 | static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t); | 78 | static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t); |
83 | static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *); | 79 | static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *); |
84 | static int lh7a40x_set_halt(struct usb_ep *ep, int); | 80 | static int lh7a40x_set_halt(struct usb_ep *ep, int); |
@@ -104,9 +100,6 @@ static struct usb_ep_ops lh7a40x_ep_ops = { | |||
104 | .alloc_request = lh7a40x_alloc_request, | 100 | .alloc_request = lh7a40x_alloc_request, |
105 | .free_request = lh7a40x_free_request, | 101 | .free_request = lh7a40x_free_request, |
106 | 102 | ||
107 | .alloc_buffer = lh7a40x_alloc_buffer, | ||
108 | .free_buffer = lh7a40x_free_buffer, | ||
109 | |||
110 | .queue = lh7a40x_queue, | 103 | .queue = lh7a40x_queue, |
111 | .dequeue = lh7a40x_dequeue, | 104 | .dequeue = lh7a40x_dequeue, |
112 | 105 | ||
@@ -1134,26 +1127,6 @@ static void lh7a40x_free_request(struct usb_ep *ep, struct usb_request *_req) | |||
1134 | kfree(req); | 1127 | kfree(req); |
1135 | } | 1128 | } |
1136 | 1129 | ||
1137 | static void *lh7a40x_alloc_buffer(struct usb_ep *ep, unsigned bytes, | ||
1138 | dma_addr_t * dma, gfp_t gfp_flags) | ||
1139 | { | ||
1140 | char *retval; | ||
1141 | |||
1142 | DEBUG("%s (%p, %d, %d)\n", __FUNCTION__, ep, bytes, gfp_flags); | ||
1143 | |||
1144 | retval = kmalloc(bytes, gfp_flags & ~(__GFP_DMA | __GFP_HIGHMEM)); | ||
1145 | if (retval) | ||
1146 | *dma = virt_to_bus(retval); | ||
1147 | return retval; | ||
1148 | } | ||
1149 | |||
1150 | static void lh7a40x_free_buffer(struct usb_ep *ep, void *buf, dma_addr_t dma, | ||
1151 | unsigned bytes) | ||
1152 | { | ||
1153 | DEBUG("%s, %p\n", __FUNCTION__, ep); | ||
1154 | kfree(buf); | ||
1155 | } | ||
1156 | |||
1157 | /** Queue one request | 1130 | /** Queue one request |
1158 | * Kickstart transfer if needed | 1131 | * Kickstart transfer if needed |
1159 | * NOTE: Sets INDEX register | 1132 | * NOTE: Sets INDEX register |
diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c new file mode 100644 index 000000000000..c0a962bb5f25 --- /dev/null +++ b/drivers/usb/gadget/m66592-udc.c | |||
@@ -0,0 +1,1653 @@ | |||
1 | /* | ||
2 | * M66592 UDC (USB gadget) | ||
3 | * | ||
4 | * Copyright (C) 2006-2007 Renesas Solutions Corp. | ||
5 | * | ||
6 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/smp_lock.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/timer.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/list.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/usb/ch9.h> | ||
35 | #include <linux/usb_gadget.h> | ||
36 | |||
37 | #include <asm/io.h> | ||
38 | #include <asm/irq.h> | ||
39 | #include <asm/system.h> | ||
40 | |||
41 | #include "m66592-udc.h" | ||
42 | |||
43 | MODULE_DESCRIPTION("M66592 USB gadget driiver"); | ||
44 | MODULE_LICENSE("GPL"); | ||
45 | MODULE_AUTHOR("Yoshihiro Shimoda"); | ||
46 | |||
47 | #define DRIVER_VERSION "29 May 2007" | ||
48 | |||
49 | /* module parameters */ | ||
50 | static unsigned short clock = M66592_XTAL24; | ||
51 | module_param(clock, ushort, 0644); | ||
52 | MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=16384)"); | ||
53 | static unsigned short vif = M66592_LDRV; | ||
54 | module_param(vif, ushort, 0644); | ||
55 | MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)"); | ||
56 | static unsigned short endian = 0; | ||
57 | module_param(endian, ushort, 0644); | ||
58 | MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)"); | ||
59 | static unsigned short irq_sense = M66592_INTL; | ||
60 | module_param(irq_sense, ushort, 0644); | ||
61 | MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=2, falling edge=0(default=2)"); | ||
62 | |||
63 | static const char udc_name[] = "m66592_udc"; | ||
64 | static const char *m66592_ep_name[] = { | ||
65 | "ep0", "ep1", "ep2", "ep3", "ep4", "ep5", "ep6", "ep7" | ||
66 | }; | ||
67 | |||
68 | static void disable_controller(struct m66592 *m66592); | ||
69 | static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req); | ||
70 | static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req); | ||
71 | static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req, | ||
72 | gfp_t gfp_flags); | ||
73 | |||
74 | static void transfer_complete(struct m66592_ep *ep, | ||
75 | struct m66592_request *req, | ||
76 | int status); | ||
77 | /*-------------------------------------------------------------------------*/ | ||
78 | static inline u16 get_usb_speed(struct m66592 *m66592) | ||
79 | { | ||
80 | return (m66592_read(m66592, M66592_DVSTCTR) & M66592_RHST); | ||
81 | } | ||
82 | |||
83 | static void enable_pipe_irq(struct m66592 *m66592, u16 pipenum, | ||
84 | unsigned long reg) | ||
85 | { | ||
86 | u16 tmp; | ||
87 | |||
88 | tmp = m66592_read(m66592, M66592_INTENB0); | ||
89 | m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE, | ||
90 | M66592_INTENB0); | ||
91 | m66592_bset(m66592, (1 << pipenum), reg); | ||
92 | m66592_write(m66592, tmp, M66592_INTENB0); | ||
93 | } | ||
94 | |||
95 | static void disable_pipe_irq(struct m66592 *m66592, u16 pipenum, | ||
96 | unsigned long reg) | ||
97 | { | ||
98 | u16 tmp; | ||
99 | |||
100 | tmp = m66592_read(m66592, M66592_INTENB0); | ||
101 | m66592_bclr(m66592, M66592_BEMPE | M66592_NRDYE | M66592_BRDYE, | ||
102 | M66592_INTENB0); | ||
103 | m66592_bclr(m66592, (1 << pipenum), reg); | ||
104 | m66592_write(m66592, tmp, M66592_INTENB0); | ||
105 | } | ||
106 | |||
107 | static void m66592_usb_connect(struct m66592 *m66592) | ||
108 | { | ||
109 | m66592_bset(m66592, M66592_CTRE, M66592_INTENB0); | ||
110 | m66592_bset(m66592, M66592_WDST | M66592_RDST | M66592_CMPL, | ||
111 | M66592_INTENB0); | ||
112 | m66592_bset(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0); | ||
113 | |||
114 | m66592_bset(m66592, M66592_DPRPU, M66592_SYSCFG); | ||
115 | } | ||
116 | |||
117 | static void m66592_usb_disconnect(struct m66592 *m66592) | ||
118 | { | ||
119 | m66592_bclr(m66592, M66592_CTRE, M66592_INTENB0); | ||
120 | m66592_bclr(m66592, M66592_WDST | M66592_RDST | M66592_CMPL, | ||
121 | M66592_INTENB0); | ||
122 | m66592_bclr(m66592, M66592_BEMPE | M66592_BRDYE, M66592_INTENB0); | ||
123 | m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG); | ||
124 | |||
125 | m66592->gadget.speed = USB_SPEED_UNKNOWN; | ||
126 | spin_unlock(&m66592->lock); | ||
127 | m66592->driver->disconnect(&m66592->gadget); | ||
128 | spin_lock(&m66592->lock); | ||
129 | |||
130 | disable_controller(m66592); | ||
131 | INIT_LIST_HEAD(&m66592->ep[0].queue); | ||
132 | } | ||
133 | |||
134 | static inline u16 control_reg_get_pid(struct m66592 *m66592, u16 pipenum) | ||
135 | { | ||
136 | u16 pid = 0; | ||
137 | unsigned long offset; | ||
138 | |||
139 | if (pipenum == 0) | ||
140 | pid = m66592_read(m66592, M66592_DCPCTR) & M66592_PID; | ||
141 | else if (pipenum < M66592_MAX_NUM_PIPE) { | ||
142 | offset = get_pipectr_addr(pipenum); | ||
143 | pid = m66592_read(m66592, offset) & M66592_PID; | ||
144 | } else | ||
145 | printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum); | ||
146 | |||
147 | return pid; | ||
148 | } | ||
149 | |||
150 | static inline void control_reg_set_pid(struct m66592 *m66592, u16 pipenum, | ||
151 | u16 pid) | ||
152 | { | ||
153 | unsigned long offset; | ||
154 | |||
155 | if (pipenum == 0) | ||
156 | m66592_mdfy(m66592, pid, M66592_PID, M66592_DCPCTR); | ||
157 | else if (pipenum < M66592_MAX_NUM_PIPE) { | ||
158 | offset = get_pipectr_addr(pipenum); | ||
159 | m66592_mdfy(m66592, pid, M66592_PID, offset); | ||
160 | } else | ||
161 | printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum); | ||
162 | } | ||
163 | |||
164 | static inline void pipe_start(struct m66592 *m66592, u16 pipenum) | ||
165 | { | ||
166 | control_reg_set_pid(m66592, pipenum, M66592_PID_BUF); | ||
167 | } | ||
168 | |||
169 | static inline void pipe_stop(struct m66592 *m66592, u16 pipenum) | ||
170 | { | ||
171 | control_reg_set_pid(m66592, pipenum, M66592_PID_NAK); | ||
172 | } | ||
173 | |||
174 | static inline void pipe_stall(struct m66592 *m66592, u16 pipenum) | ||
175 | { | ||
176 | control_reg_set_pid(m66592, pipenum, M66592_PID_STALL); | ||
177 | } | ||
178 | |||
179 | static inline u16 control_reg_get(struct m66592 *m66592, u16 pipenum) | ||
180 | { | ||
181 | u16 ret = 0; | ||
182 | unsigned long offset; | ||
183 | |||
184 | if (pipenum == 0) | ||
185 | ret = m66592_read(m66592, M66592_DCPCTR); | ||
186 | else if (pipenum < M66592_MAX_NUM_PIPE) { | ||
187 | offset = get_pipectr_addr(pipenum); | ||
188 | ret = m66592_read(m66592, offset); | ||
189 | } else | ||
190 | printk(KERN_ERR "unexpect pipe num (%d)\n", pipenum); | ||
191 | |||
192 | return ret; | ||
193 | } | ||
194 | |||
195 | static inline void control_reg_sqclr(struct m66592 *m66592, u16 pipenum) | ||
196 | { | ||
197 | unsigned long offset; | ||
198 | |||
199 | pipe_stop(m66592, pipenum); | ||
200 | |||
201 | if (pipenum == 0) | ||
202 | m66592_bset(m66592, M66592_SQCLR, M66592_DCPCTR); | ||
203 | else if (pipenum < M66592_MAX_NUM_PIPE) { | ||
204 | offset = get_pipectr_addr(pipenum); | ||
205 | m66592_bset(m66592, M66592_SQCLR, offset); | ||
206 | } else | ||
207 | printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum); | ||
208 | } | ||
209 | |||
210 | static inline int get_buffer_size(struct m66592 *m66592, u16 pipenum) | ||
211 | { | ||
212 | u16 tmp; | ||
213 | int size; | ||
214 | |||
215 | if (pipenum == 0) { | ||
216 | tmp = m66592_read(m66592, M66592_DCPCFG); | ||
217 | if ((tmp & M66592_CNTMD) != 0) | ||
218 | size = 256; | ||
219 | else { | ||
220 | tmp = m66592_read(m66592, M66592_DCPMAXP); | ||
221 | size = tmp & M66592_MAXP; | ||
222 | } | ||
223 | } else { | ||
224 | m66592_write(m66592, pipenum, M66592_PIPESEL); | ||
225 | tmp = m66592_read(m66592, M66592_PIPECFG); | ||
226 | if ((tmp & M66592_CNTMD) != 0) { | ||
227 | tmp = m66592_read(m66592, M66592_PIPEBUF); | ||
228 | size = ((tmp >> 10) + 1) * 64; | ||
229 | } else { | ||
230 | tmp = m66592_read(m66592, M66592_PIPEMAXP); | ||
231 | size = tmp & M66592_MXPS; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | return size; | ||
236 | } | ||
237 | |||
238 | static inline void pipe_change(struct m66592 *m66592, u16 pipenum) | ||
239 | { | ||
240 | struct m66592_ep *ep = m66592->pipenum2ep[pipenum]; | ||
241 | |||
242 | if (ep->use_dma) | ||
243 | return; | ||
244 | |||
245 | m66592_mdfy(m66592, pipenum, M66592_CURPIPE, ep->fifosel); | ||
246 | |||
247 | ndelay(450); | ||
248 | |||
249 | m66592_bset(m66592, M66592_MBW, ep->fifosel); | ||
250 | } | ||
251 | |||
252 | static int pipe_buffer_setting(struct m66592 *m66592, | ||
253 | struct m66592_pipe_info *info) | ||
254 | { | ||
255 | u16 bufnum = 0, buf_bsize = 0; | ||
256 | u16 pipecfg = 0; | ||
257 | |||
258 | if (info->pipe == 0) | ||
259 | return -EINVAL; | ||
260 | |||
261 | m66592_write(m66592, info->pipe, M66592_PIPESEL); | ||
262 | |||
263 | if (info->dir_in) | ||
264 | pipecfg |= M66592_DIR; | ||
265 | pipecfg |= info->type; | ||
266 | pipecfg |= info->epnum; | ||
267 | switch (info->type) { | ||
268 | case M66592_INT: | ||
269 | bufnum = 4 + (info->pipe - M66592_BASE_PIPENUM_INT); | ||
270 | buf_bsize = 0; | ||
271 | break; | ||
272 | case M66592_BULK: | ||
273 | bufnum = m66592->bi_bufnum + | ||
274 | (info->pipe - M66592_BASE_PIPENUM_BULK) * 16; | ||
275 | m66592->bi_bufnum += 16; | ||
276 | buf_bsize = 7; | ||
277 | pipecfg |= M66592_DBLB; | ||
278 | if (!info->dir_in) | ||
279 | pipecfg |= M66592_SHTNAK; | ||
280 | break; | ||
281 | case M66592_ISO: | ||
282 | bufnum = m66592->bi_bufnum + | ||
283 | (info->pipe - M66592_BASE_PIPENUM_ISOC) * 16; | ||
284 | m66592->bi_bufnum += 16; | ||
285 | buf_bsize = 7; | ||
286 | break; | ||
287 | } | ||
288 | if (m66592->bi_bufnum > M66592_MAX_BUFNUM) { | ||
289 | printk(KERN_ERR "m66592 pipe memory is insufficient(%d)\n", | ||
290 | m66592->bi_bufnum); | ||
291 | return -ENOMEM; | ||
292 | } | ||
293 | |||
294 | m66592_write(m66592, pipecfg, M66592_PIPECFG); | ||
295 | m66592_write(m66592, (buf_bsize << 10) | (bufnum), M66592_PIPEBUF); | ||
296 | m66592_write(m66592, info->maxpacket, M66592_PIPEMAXP); | ||
297 | if (info->interval) | ||
298 | info->interval--; | ||
299 | m66592_write(m66592, info->interval, M66592_PIPEPERI); | ||
300 | |||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static void pipe_buffer_release(struct m66592 *m66592, | ||
305 | struct m66592_pipe_info *info) | ||
306 | { | ||
307 | if (info->pipe == 0) | ||
308 | return; | ||
309 | |||
310 | switch (info->type) { | ||
311 | case M66592_BULK: | ||
312 | if (is_bulk_pipe(info->pipe)) | ||
313 | m66592->bi_bufnum -= 16; | ||
314 | break; | ||
315 | case M66592_ISO: | ||
316 | if (is_isoc_pipe(info->pipe)) | ||
317 | m66592->bi_bufnum -= 16; | ||
318 | break; | ||
319 | } | ||
320 | |||
321 | if (is_bulk_pipe(info->pipe)) { | ||
322 | m66592->bulk--; | ||
323 | } else if (is_interrupt_pipe(info->pipe)) | ||
324 | m66592->interrupt--; | ||
325 | else if (is_isoc_pipe(info->pipe)) { | ||
326 | m66592->isochronous--; | ||
327 | if (info->type == M66592_BULK) | ||
328 | m66592->bulk--; | ||
329 | } else | ||
330 | printk(KERN_ERR "ep_release: unexpect pipenum (%d)\n", | ||
331 | info->pipe); | ||
332 | } | ||
333 | |||
334 | static void pipe_initialize(struct m66592_ep *ep) | ||
335 | { | ||
336 | struct m66592 *m66592 = ep->m66592; | ||
337 | |||
338 | m66592_mdfy(m66592, 0, M66592_CURPIPE, ep->fifosel); | ||
339 | |||
340 | m66592_write(m66592, M66592_ACLRM, ep->pipectr); | ||
341 | m66592_write(m66592, 0, ep->pipectr); | ||
342 | m66592_write(m66592, M66592_SQCLR, ep->pipectr); | ||
343 | if (ep->use_dma) { | ||
344 | m66592_mdfy(m66592, ep->pipenum, M66592_CURPIPE, ep->fifosel); | ||
345 | |||
346 | ndelay(450); | ||
347 | |||
348 | m66592_bset(m66592, M66592_MBW, ep->fifosel); | ||
349 | } | ||
350 | } | ||
351 | |||
352 | static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, | ||
353 | const struct usb_endpoint_descriptor *desc, | ||
354 | u16 pipenum, int dma) | ||
355 | { | ||
356 | if ((pipenum != 0) && dma) { | ||
357 | if (m66592->num_dma == 0) { | ||
358 | m66592->num_dma++; | ||
359 | ep->use_dma = 1; | ||
360 | ep->fifoaddr = M66592_D0FIFO; | ||
361 | ep->fifosel = M66592_D0FIFOSEL; | ||
362 | ep->fifoctr = M66592_D0FIFOCTR; | ||
363 | ep->fifotrn = M66592_D0FIFOTRN; | ||
364 | } else if (m66592->num_dma == 1) { | ||
365 | m66592->num_dma++; | ||
366 | ep->use_dma = 1; | ||
367 | ep->fifoaddr = M66592_D1FIFO; | ||
368 | ep->fifosel = M66592_D1FIFOSEL; | ||
369 | ep->fifoctr = M66592_D1FIFOCTR; | ||
370 | ep->fifotrn = M66592_D1FIFOTRN; | ||
371 | } else { | ||
372 | ep->use_dma = 0; | ||
373 | ep->fifoaddr = M66592_CFIFO; | ||
374 | ep->fifosel = M66592_CFIFOSEL; | ||
375 | ep->fifoctr = M66592_CFIFOCTR; | ||
376 | ep->fifotrn = 0; | ||
377 | } | ||
378 | } else { | ||
379 | ep->use_dma = 0; | ||
380 | ep->fifoaddr = M66592_CFIFO; | ||
381 | ep->fifosel = M66592_CFIFOSEL; | ||
382 | ep->fifoctr = M66592_CFIFOCTR; | ||
383 | ep->fifotrn = 0; | ||
384 | } | ||
385 | |||
386 | ep->pipectr = get_pipectr_addr(pipenum); | ||
387 | ep->pipenum = pipenum; | ||
388 | ep->ep.maxpacket = desc->wMaxPacketSize; | ||
389 | m66592->pipenum2ep[pipenum] = ep; | ||
390 | m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep; | ||
391 | INIT_LIST_HEAD(&ep->queue); | ||
392 | } | ||
393 | |||
394 | static void m66592_ep_release(struct m66592_ep *ep) | ||
395 | { | ||
396 | struct m66592 *m66592 = ep->m66592; | ||
397 | u16 pipenum = ep->pipenum; | ||
398 | |||
399 | if (pipenum == 0) | ||
400 | return; | ||
401 | |||
402 | if (ep->use_dma) | ||
403 | m66592->num_dma--; | ||
404 | ep->pipenum = 0; | ||
405 | ep->busy = 0; | ||
406 | ep->use_dma = 0; | ||
407 | } | ||
408 | |||
409 | static int alloc_pipe_config(struct m66592_ep *ep, | ||
410 | const struct usb_endpoint_descriptor *desc) | ||
411 | { | ||
412 | struct m66592 *m66592 = ep->m66592; | ||
413 | struct m66592_pipe_info info; | ||
414 | int dma = 0; | ||
415 | int *counter; | ||
416 | int ret; | ||
417 | |||
418 | ep->desc = desc; | ||
419 | |||
420 | BUG_ON(ep->pipenum); | ||
421 | |||
422 | switch(desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
423 | case USB_ENDPOINT_XFER_BULK: | ||
424 | if (m66592->bulk >= M66592_MAX_NUM_BULK) { | ||
425 | if (m66592->isochronous >= M66592_MAX_NUM_ISOC) { | ||
426 | printk(KERN_ERR "bulk pipe is insufficient\n"); | ||
427 | return -ENODEV; | ||
428 | } else { | ||
429 | info.pipe = M66592_BASE_PIPENUM_ISOC + | ||
430 | m66592->isochronous; | ||
431 | counter = &m66592->isochronous; | ||
432 | } | ||
433 | } else { | ||
434 | info.pipe = M66592_BASE_PIPENUM_BULK + m66592->bulk; | ||
435 | counter = &m66592->bulk; | ||
436 | } | ||
437 | info.type = M66592_BULK; | ||
438 | dma = 1; | ||
439 | break; | ||
440 | case USB_ENDPOINT_XFER_INT: | ||
441 | if (m66592->interrupt >= M66592_MAX_NUM_INT) { | ||
442 | printk(KERN_ERR "interrupt pipe is insufficient\n"); | ||
443 | return -ENODEV; | ||
444 | } | ||
445 | info.pipe = M66592_BASE_PIPENUM_INT + m66592->interrupt; | ||
446 | info.type = M66592_INT; | ||
447 | counter = &m66592->interrupt; | ||
448 | break; | ||
449 | case USB_ENDPOINT_XFER_ISOC: | ||
450 | if (m66592->isochronous >= M66592_MAX_NUM_ISOC) { | ||
451 | printk(KERN_ERR "isochronous pipe is insufficient\n"); | ||
452 | return -ENODEV; | ||
453 | } | ||
454 | info.pipe = M66592_BASE_PIPENUM_ISOC + m66592->isochronous; | ||
455 | info.type = M66592_ISO; | ||
456 | counter = &m66592->isochronous; | ||
457 | break; | ||
458 | default: | ||
459 | printk(KERN_ERR "unexpect xfer type\n"); | ||
460 | return -EINVAL; | ||
461 | } | ||
462 | ep->type = info.type; | ||
463 | |||
464 | info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | ||
465 | info.maxpacket = desc->wMaxPacketSize; | ||
466 | info.interval = desc->bInterval; | ||
467 | if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | ||
468 | info.dir_in = 1; | ||
469 | else | ||
470 | info.dir_in = 0; | ||
471 | |||
472 | ret = pipe_buffer_setting(m66592, &info); | ||
473 | if (ret < 0) { | ||
474 | printk(KERN_ERR "pipe_buffer_setting fail\n"); | ||
475 | return ret; | ||
476 | } | ||
477 | |||
478 | (*counter)++; | ||
479 | if ((counter == &m66592->isochronous) && info.type == M66592_BULK) | ||
480 | m66592->bulk++; | ||
481 | |||
482 | m66592_ep_setting(m66592, ep, desc, info.pipe, dma); | ||
483 | pipe_initialize(ep); | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | static int free_pipe_config(struct m66592_ep *ep) | ||
489 | { | ||
490 | struct m66592 *m66592 = ep->m66592; | ||
491 | struct m66592_pipe_info info; | ||
492 | |||
493 | info.pipe = ep->pipenum; | ||
494 | info.type = ep->type; | ||
495 | pipe_buffer_release(m66592, &info); | ||
496 | m66592_ep_release(ep); | ||
497 | |||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | /*-------------------------------------------------------------------------*/ | ||
502 | static void pipe_irq_enable(struct m66592 *m66592, u16 pipenum) | ||
503 | { | ||
504 | enable_irq_ready(m66592, pipenum); | ||
505 | enable_irq_nrdy(m66592, pipenum); | ||
506 | } | ||
507 | |||
508 | static void pipe_irq_disable(struct m66592 *m66592, u16 pipenum) | ||
509 | { | ||
510 | disable_irq_ready(m66592, pipenum); | ||
511 | disable_irq_nrdy(m66592, pipenum); | ||
512 | } | ||
513 | |||
514 | /* if complete is true, gadget driver complete function is not call */ | ||
515 | static void control_end(struct m66592 *m66592, unsigned ccpl) | ||
516 | { | ||
517 | m66592->ep[0].internal_ccpl = ccpl; | ||
518 | pipe_start(m66592, 0); | ||
519 | m66592_bset(m66592, M66592_CCPL, M66592_DCPCTR); | ||
520 | } | ||
521 | |||
522 | static void start_ep0_write(struct m66592_ep *ep, struct m66592_request *req) | ||
523 | { | ||
524 | struct m66592 *m66592 = ep->m66592; | ||
525 | |||
526 | pipe_change(m66592, ep->pipenum); | ||
527 | m66592_mdfy(m66592, M66592_ISEL | M66592_PIPE0, | ||
528 | (M66592_ISEL | M66592_CURPIPE), | ||
529 | M66592_CFIFOSEL); | ||
530 | m66592_write(m66592, M66592_BCLR, ep->fifoctr); | ||
531 | if (req->req.length == 0) { | ||
532 | m66592_bset(m66592, M66592_BVAL, ep->fifoctr); | ||
533 | pipe_start(m66592, 0); | ||
534 | transfer_complete(ep, req, 0); | ||
535 | } else { | ||
536 | m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS); | ||
537 | irq_ep0_write(ep, req); | ||
538 | } | ||
539 | } | ||
540 | |||
541 | static void start_packet_write(struct m66592_ep *ep, struct m66592_request *req) | ||
542 | { | ||
543 | struct m66592 *m66592 = ep->m66592; | ||
544 | u16 tmp; | ||
545 | |||
546 | pipe_change(m66592, ep->pipenum); | ||
547 | disable_irq_empty(m66592, ep->pipenum); | ||
548 | pipe_start(m66592, ep->pipenum); | ||
549 | |||
550 | tmp = m66592_read(m66592, ep->fifoctr); | ||
551 | if (unlikely((tmp & M66592_FRDY) == 0)) | ||
552 | pipe_irq_enable(m66592, ep->pipenum); | ||
553 | else | ||
554 | irq_packet_write(ep, req); | ||
555 | } | ||
556 | |||
557 | static void start_packet_read(struct m66592_ep *ep, struct m66592_request *req) | ||
558 | { | ||
559 | struct m66592 *m66592 = ep->m66592; | ||
560 | u16 pipenum = ep->pipenum; | ||
561 | |||
562 | if (ep->pipenum == 0) { | ||
563 | m66592_mdfy(m66592, M66592_PIPE0, | ||
564 | (M66592_ISEL | M66592_CURPIPE), | ||
565 | M66592_CFIFOSEL); | ||
566 | m66592_write(m66592, M66592_BCLR, ep->fifoctr); | ||
567 | pipe_start(m66592, pipenum); | ||
568 | pipe_irq_enable(m66592, pipenum); | ||
569 | } else { | ||
570 | if (ep->use_dma) { | ||
571 | m66592_bset(m66592, M66592_TRCLR, ep->fifosel); | ||
572 | pipe_change(m66592, pipenum); | ||
573 | m66592_bset(m66592, M66592_TRENB, ep->fifosel); | ||
574 | m66592_write(m66592, | ||
575 | (req->req.length + ep->ep.maxpacket - 1) / | ||
576 | ep->ep.maxpacket, ep->fifotrn); | ||
577 | } | ||
578 | pipe_start(m66592, pipenum); /* trigger once */ | ||
579 | pipe_irq_enable(m66592, pipenum); | ||
580 | } | ||
581 | } | ||
582 | |||
583 | static void start_packet(struct m66592_ep *ep, struct m66592_request *req) | ||
584 | { | ||
585 | if (ep->desc->bEndpointAddress & USB_DIR_IN) | ||
586 | start_packet_write(ep, req); | ||
587 | else | ||
588 | start_packet_read(ep, req); | ||
589 | } | ||
590 | |||
591 | static void start_ep0(struct m66592_ep *ep, struct m66592_request *req) | ||
592 | { | ||
593 | u16 ctsq; | ||
594 | |||
595 | ctsq = m66592_read(ep->m66592, M66592_INTSTS0) & M66592_CTSQ; | ||
596 | |||
597 | switch (ctsq) { | ||
598 | case M66592_CS_RDDS: | ||
599 | start_ep0_write(ep, req); | ||
600 | break; | ||
601 | case M66592_CS_WRDS: | ||
602 | start_packet_read(ep, req); | ||
603 | break; | ||
604 | |||
605 | case M66592_CS_WRND: | ||
606 | control_end(ep->m66592, 0); | ||
607 | break; | ||
608 | default: | ||
609 | printk(KERN_ERR "start_ep0: unexpect ctsq(%x)\n", ctsq); | ||
610 | break; | ||
611 | } | ||
612 | } | ||
613 | |||
614 | static void init_controller(struct m66592 *m66592) | ||
615 | { | ||
616 | m66592_bset(m66592, (vif & M66592_LDRV) | (endian & M66592_BIGEND), | ||
617 | M66592_PINCFG); | ||
618 | m66592_bset(m66592, M66592_HSE, M66592_SYSCFG); /* High spd */ | ||
619 | m66592_mdfy(m66592, clock & M66592_XTAL, M66592_XTAL, M66592_SYSCFG); | ||
620 | |||
621 | m66592_bclr(m66592, M66592_USBE, M66592_SYSCFG); | ||
622 | m66592_bclr(m66592, M66592_DPRPU, M66592_SYSCFG); | ||
623 | m66592_bset(m66592, M66592_USBE, M66592_SYSCFG); | ||
624 | |||
625 | m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG); | ||
626 | |||
627 | msleep(3); | ||
628 | |||
629 | m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG); | ||
630 | |||
631 | msleep(1); | ||
632 | |||
633 | m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG); | ||
634 | |||
635 | m66592_bset(m66592, irq_sense & M66592_INTL, M66592_INTENB1); | ||
636 | m66592_write(m66592, M66592_BURST | M66592_CPU_ADR_RD_WR, | ||
637 | M66592_DMA0CFG); | ||
638 | } | ||
639 | |||
640 | static void disable_controller(struct m66592 *m66592) | ||
641 | { | ||
642 | m66592_bclr(m66592, M66592_SCKE, M66592_SYSCFG); | ||
643 | udelay(1); | ||
644 | m66592_bclr(m66592, M66592_PLLC, M66592_SYSCFG); | ||
645 | udelay(1); | ||
646 | m66592_bclr(m66592, M66592_RCKE, M66592_SYSCFG); | ||
647 | udelay(1); | ||
648 | m66592_bclr(m66592, M66592_XCKE, M66592_SYSCFG); | ||
649 | } | ||
650 | |||
651 | static void m66592_start_xclock(struct m66592 *m66592) | ||
652 | { | ||
653 | u16 tmp; | ||
654 | |||
655 | tmp = m66592_read(m66592, M66592_SYSCFG); | ||
656 | if (!(tmp & M66592_XCKE)) | ||
657 | m66592_bset(m66592, M66592_XCKE, M66592_SYSCFG); | ||
658 | } | ||
659 | |||
660 | /*-------------------------------------------------------------------------*/ | ||
661 | static void transfer_complete(struct m66592_ep *ep, | ||
662 | struct m66592_request *req, | ||
663 | int status) | ||
664 | { | ||
665 | int restart = 0; | ||
666 | |||
667 | if (unlikely(ep->pipenum == 0)) { | ||
668 | if (ep->internal_ccpl) { | ||
669 | ep->internal_ccpl = 0; | ||
670 | return; | ||
671 | } | ||
672 | } | ||
673 | |||
674 | list_del_init(&req->queue); | ||
675 | if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN) | ||
676 | req->req.status = -ESHUTDOWN; | ||
677 | else | ||
678 | req->req.status = status; | ||
679 | |||
680 | if (!list_empty(&ep->queue)) | ||
681 | restart = 1; | ||
682 | |||
683 | if (likely(req->req.complete)) | ||
684 | req->req.complete(&ep->ep, &req->req); | ||
685 | |||
686 | if (restart) { | ||
687 | req = list_entry(ep->queue.next, struct m66592_request, queue); | ||
688 | if (ep->desc) | ||
689 | start_packet(ep, req); | ||
690 | } | ||
691 | } | ||
692 | |||
693 | static void irq_ep0_write(struct m66592_ep *ep, struct m66592_request *req) | ||
694 | { | ||
695 | int i; | ||
696 | volatile u16 tmp; | ||
697 | unsigned bufsize; | ||
698 | size_t size; | ||
699 | void *buf; | ||
700 | u16 pipenum = ep->pipenum; | ||
701 | struct m66592 *m66592 = ep->m66592; | ||
702 | |||
703 | pipe_change(m66592, pipenum); | ||
704 | m66592_bset(m66592, M66592_ISEL, ep->fifosel); | ||
705 | |||
706 | i = 0; | ||
707 | do { | ||
708 | tmp = m66592_read(m66592, ep->fifoctr); | ||
709 | if (i++ > 100000) { | ||
710 | printk(KERN_ERR "pipe0 is busy. maybe cpu i/o bus" | ||
711 | "conflict. please power off this controller."); | ||
712 | return; | ||
713 | } | ||
714 | ndelay(1); | ||
715 | } while ((tmp & M66592_FRDY) == 0); | ||
716 | |||
717 | /* prepare parameters */ | ||
718 | bufsize = get_buffer_size(m66592, pipenum); | ||
719 | buf = req->req.buf + req->req.actual; | ||
720 | size = min(bufsize, req->req.length - req->req.actual); | ||
721 | |||
722 | /* write fifo */ | ||
723 | if (req->req.buf) { | ||
724 | if (size > 0) | ||
725 | m66592_write_fifo(m66592, ep->fifoaddr, buf, size); | ||
726 | if ((size == 0) || ((size % ep->ep.maxpacket) != 0)) | ||
727 | m66592_bset(m66592, M66592_BVAL, ep->fifoctr); | ||
728 | } | ||
729 | |||
730 | /* update parameters */ | ||
731 | req->req.actual += size; | ||
732 | |||
733 | /* check transfer finish */ | ||
734 | if ((!req->req.zero && (req->req.actual == req->req.length)) || | ||
735 | (size % ep->ep.maxpacket) || (size == 0)) { | ||
736 | disable_irq_ready(m66592, pipenum); | ||
737 | disable_irq_empty(m66592, pipenum); | ||
738 | } else { | ||
739 | disable_irq_ready(m66592, pipenum); | ||
740 | enable_irq_empty(m66592, pipenum); | ||
741 | } | ||
742 | pipe_start(m66592, pipenum); | ||
743 | } | ||
744 | |||
745 | static void irq_packet_write(struct m66592_ep *ep, struct m66592_request *req) | ||
746 | { | ||
747 | u16 tmp; | ||
748 | unsigned bufsize; | ||
749 | size_t size; | ||
750 | void *buf; | ||
751 | u16 pipenum = ep->pipenum; | ||
752 | struct m66592 *m66592 = ep->m66592; | ||
753 | |||
754 | pipe_change(m66592, pipenum); | ||
755 | tmp = m66592_read(m66592, ep->fifoctr); | ||
756 | if (unlikely((tmp & M66592_FRDY) == 0)) { | ||
757 | pipe_stop(m66592, pipenum); | ||
758 | pipe_irq_disable(m66592, pipenum); | ||
759 | printk(KERN_ERR "write fifo not ready. pipnum=%d\n", pipenum); | ||
760 | return; | ||
761 | } | ||
762 | |||
763 | /* prepare parameters */ | ||
764 | bufsize = get_buffer_size(m66592, pipenum); | ||
765 | buf = req->req.buf + req->req.actual; | ||
766 | size = min(bufsize, req->req.length - req->req.actual); | ||
767 | |||
768 | /* write fifo */ | ||
769 | if (req->req.buf) { | ||
770 | m66592_write_fifo(m66592, ep->fifoaddr, buf, size); | ||
771 | if ((size == 0) || ((size % ep->ep.maxpacket) != 0) || | ||
772 | ((bufsize != ep->ep.maxpacket) && (bufsize > size))) | ||
773 | m66592_bset(m66592, M66592_BVAL, ep->fifoctr); | ||
774 | } | ||
775 | |||
776 | /* update parameters */ | ||
777 | req->req.actual += size; | ||
778 | /* check transfer finish */ | ||
779 | if ((!req->req.zero && (req->req.actual == req->req.length)) || | ||
780 | (size % ep->ep.maxpacket) || (size == 0)) { | ||
781 | disable_irq_ready(m66592, pipenum); | ||
782 | enable_irq_empty(m66592, pipenum); | ||
783 | } else { | ||
784 | disable_irq_empty(m66592, pipenum); | ||
785 | pipe_irq_enable(m66592, pipenum); | ||
786 | } | ||
787 | } | ||
788 | |||
789 | static void irq_packet_read(struct m66592_ep *ep, struct m66592_request *req) | ||
790 | { | ||
791 | u16 tmp; | ||
792 | int rcv_len, bufsize, req_len; | ||
793 | int size; | ||
794 | void *buf; | ||
795 | u16 pipenum = ep->pipenum; | ||
796 | struct m66592 *m66592 = ep->m66592; | ||
797 | int finish = 0; | ||
798 | |||
799 | pipe_change(m66592, pipenum); | ||
800 | tmp = m66592_read(m66592, ep->fifoctr); | ||
801 | if (unlikely((tmp & M66592_FRDY) == 0)) { | ||
802 | req->req.status = -EPIPE; | ||
803 | pipe_stop(m66592, pipenum); | ||
804 | pipe_irq_disable(m66592, pipenum); | ||
805 | printk(KERN_ERR "read fifo not ready"); | ||
806 | return; | ||
807 | } | ||
808 | |||
809 | /* prepare parameters */ | ||
810 | rcv_len = tmp & M66592_DTLN; | ||
811 | bufsize = get_buffer_size(m66592, pipenum); | ||
812 | |||
813 | buf = req->req.buf + req->req.actual; | ||
814 | req_len = req->req.length - req->req.actual; | ||
815 | if (rcv_len < bufsize) | ||
816 | size = min(rcv_len, req_len); | ||
817 | else | ||
818 | size = min(bufsize, req_len); | ||
819 | |||
820 | /* update parameters */ | ||
821 | req->req.actual += size; | ||
822 | |||
823 | /* check transfer finish */ | ||
824 | if ((!req->req.zero && (req->req.actual == req->req.length)) || | ||
825 | (size % ep->ep.maxpacket) || (size == 0)) { | ||
826 | pipe_stop(m66592, pipenum); | ||
827 | pipe_irq_disable(m66592, pipenum); | ||
828 | finish = 1; | ||
829 | } | ||
830 | |||
831 | /* read fifo */ | ||
832 | if (req->req.buf) { | ||
833 | if (size == 0) | ||
834 | m66592_write(m66592, M66592_BCLR, ep->fifoctr); | ||
835 | else | ||
836 | m66592_read_fifo(m66592, ep->fifoaddr, buf, size); | ||
837 | } | ||
838 | |||
839 | if ((ep->pipenum != 0) && finish) | ||
840 | transfer_complete(ep, req, 0); | ||
841 | } | ||
842 | |||
843 | static void irq_pipe_ready(struct m66592 *m66592, u16 status, u16 enb) | ||
844 | { | ||
845 | u16 check; | ||
846 | u16 pipenum; | ||
847 | struct m66592_ep *ep; | ||
848 | struct m66592_request *req; | ||
849 | |||
850 | if ((status & M66592_BRDY0) && (enb & M66592_BRDY0)) { | ||
851 | m66592_write(m66592, ~M66592_BRDY0, M66592_BRDYSTS); | ||
852 | m66592_mdfy(m66592, M66592_PIPE0, M66592_CURPIPE, | ||
853 | M66592_CFIFOSEL); | ||
854 | |||
855 | ep = &m66592->ep[0]; | ||
856 | req = list_entry(ep->queue.next, struct m66592_request, queue); | ||
857 | irq_packet_read(ep, req); | ||
858 | } else { | ||
859 | for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) { | ||
860 | check = 1 << pipenum; | ||
861 | if ((status & check) && (enb & check)) { | ||
862 | m66592_write(m66592, ~check, M66592_BRDYSTS); | ||
863 | ep = m66592->pipenum2ep[pipenum]; | ||
864 | req = list_entry(ep->queue.next, | ||
865 | struct m66592_request, queue); | ||
866 | if (ep->desc->bEndpointAddress & USB_DIR_IN) | ||
867 | irq_packet_write(ep, req); | ||
868 | else | ||
869 | irq_packet_read(ep, req); | ||
870 | } | ||
871 | } | ||
872 | } | ||
873 | } | ||
874 | |||
875 | static void irq_pipe_empty(struct m66592 *m66592, u16 status, u16 enb) | ||
876 | { | ||
877 | u16 tmp; | ||
878 | u16 check; | ||
879 | u16 pipenum; | ||
880 | struct m66592_ep *ep; | ||
881 | struct m66592_request *req; | ||
882 | |||
883 | if ((status & M66592_BEMP0) && (enb & M66592_BEMP0)) { | ||
884 | m66592_write(m66592, ~M66592_BEMP0, M66592_BEMPSTS); | ||
885 | |||
886 | ep = &m66592->ep[0]; | ||
887 | req = list_entry(ep->queue.next, struct m66592_request, queue); | ||
888 | irq_ep0_write(ep, req); | ||
889 | } else { | ||
890 | for (pipenum = 1; pipenum < M66592_MAX_NUM_PIPE; pipenum++) { | ||
891 | check = 1 << pipenum; | ||
892 | if ((status & check) && (enb & check)) { | ||
893 | m66592_write(m66592, ~check, M66592_BEMPSTS); | ||
894 | tmp = control_reg_get(m66592, pipenum); | ||
895 | if ((tmp & M66592_INBUFM) == 0) { | ||
896 | disable_irq_empty(m66592, pipenum); | ||
897 | pipe_irq_disable(m66592, pipenum); | ||
898 | pipe_stop(m66592, pipenum); | ||
899 | ep = m66592->pipenum2ep[pipenum]; | ||
900 | req = list_entry(ep->queue.next, | ||
901 | struct m66592_request, | ||
902 | queue); | ||
903 | if (!list_empty(&ep->queue)) | ||
904 | transfer_complete(ep, req, 0); | ||
905 | } | ||
906 | } | ||
907 | } | ||
908 | } | ||
909 | } | ||
910 | |||
911 | static void get_status(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) | ||
912 | { | ||
913 | struct m66592_ep *ep; | ||
914 | u16 pid; | ||
915 | u16 status = 0; | ||
916 | |||
917 | switch (ctrl->bRequestType & USB_RECIP_MASK) { | ||
918 | case USB_RECIP_DEVICE: | ||
919 | status = 1; /* selfpower */ | ||
920 | break; | ||
921 | case USB_RECIP_INTERFACE: | ||
922 | status = 0; | ||
923 | break; | ||
924 | case USB_RECIP_ENDPOINT: | ||
925 | ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK]; | ||
926 | pid = control_reg_get_pid(m66592, ep->pipenum); | ||
927 | if (pid == M66592_PID_STALL) | ||
928 | status = 1; | ||
929 | else | ||
930 | status = 0; | ||
931 | break; | ||
932 | default: | ||
933 | pipe_stall(m66592, 0); | ||
934 | return; /* exit */ | ||
935 | } | ||
936 | |||
937 | *m66592->ep0_buf = status; | ||
938 | m66592->ep0_req->buf = m66592->ep0_buf; | ||
939 | m66592->ep0_req->length = 2; | ||
940 | m66592_queue(m66592->gadget.ep0, m66592->ep0_req, GFP_KERNEL); | ||
941 | } | ||
942 | |||
943 | static void clear_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) | ||
944 | { | ||
945 | switch (ctrl->bRequestType & USB_RECIP_MASK) { | ||
946 | case USB_RECIP_DEVICE: | ||
947 | control_end(m66592, 1); | ||
948 | break; | ||
949 | case USB_RECIP_INTERFACE: | ||
950 | control_end(m66592, 1); | ||
951 | break; | ||
952 | case USB_RECIP_ENDPOINT: { | ||
953 | struct m66592_ep *ep; | ||
954 | struct m66592_request *req; | ||
955 | |||
956 | ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK]; | ||
957 | pipe_stop(m66592, ep->pipenum); | ||
958 | control_reg_sqclr(m66592, ep->pipenum); | ||
959 | |||
960 | control_end(m66592, 1); | ||
961 | |||
962 | req = list_entry(ep->queue.next, | ||
963 | struct m66592_request, queue); | ||
964 | if (ep->busy) { | ||
965 | ep->busy = 0; | ||
966 | if (list_empty(&ep->queue)) | ||
967 | break; | ||
968 | start_packet(ep, req); | ||
969 | } else if (!list_empty(&ep->queue)) | ||
970 | pipe_start(m66592, ep->pipenum); | ||
971 | } | ||
972 | break; | ||
973 | default: | ||
974 | pipe_stall(m66592, 0); | ||
975 | break; | ||
976 | } | ||
977 | } | ||
978 | |||
979 | static void set_feature(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) | ||
980 | { | ||
981 | |||
982 | switch (ctrl->bRequestType & USB_RECIP_MASK) { | ||
983 | case USB_RECIP_DEVICE: | ||
984 | control_end(m66592, 1); | ||
985 | break; | ||
986 | case USB_RECIP_INTERFACE: | ||
987 | control_end(m66592, 1); | ||
988 | break; | ||
989 | case USB_RECIP_ENDPOINT: { | ||
990 | struct m66592_ep *ep; | ||
991 | |||
992 | ep = m66592->epaddr2ep[ctrl->wIndex&USB_ENDPOINT_NUMBER_MASK]; | ||
993 | pipe_stall(m66592, ep->pipenum); | ||
994 | |||
995 | control_end(m66592, 1); | ||
996 | } | ||
997 | break; | ||
998 | default: | ||
999 | pipe_stall(m66592, 0); | ||
1000 | break; | ||
1001 | } | ||
1002 | } | ||
1003 | |||
1004 | /* if return value is true, call class driver's setup() */ | ||
1005 | static int setup_packet(struct m66592 *m66592, struct usb_ctrlrequest *ctrl) | ||
1006 | { | ||
1007 | u16 *p = (u16 *)ctrl; | ||
1008 | unsigned long offset = M66592_USBREQ; | ||
1009 | int i, ret = 0; | ||
1010 | |||
1011 | /* read fifo */ | ||
1012 | m66592_write(m66592, ~M66592_VALID, M66592_INTSTS0); | ||
1013 | |||
1014 | for (i = 0; i < 4; i++) | ||
1015 | p[i] = m66592_read(m66592, offset + i*2); | ||
1016 | |||
1017 | /* check request */ | ||
1018 | if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { | ||
1019 | switch (ctrl->bRequest) { | ||
1020 | case USB_REQ_GET_STATUS: | ||
1021 | get_status(m66592, ctrl); | ||
1022 | break; | ||
1023 | case USB_REQ_CLEAR_FEATURE: | ||
1024 | clear_feature(m66592, ctrl); | ||
1025 | break; | ||
1026 | case USB_REQ_SET_FEATURE: | ||
1027 | set_feature(m66592, ctrl); | ||
1028 | break; | ||
1029 | default: | ||
1030 | ret = 1; | ||
1031 | break; | ||
1032 | } | ||
1033 | } else | ||
1034 | ret = 1; | ||
1035 | return ret; | ||
1036 | } | ||
1037 | |||
1038 | static void m66592_update_usb_speed(struct m66592 *m66592) | ||
1039 | { | ||
1040 | u16 speed = get_usb_speed(m66592); | ||
1041 | |||
1042 | switch (speed) { | ||
1043 | case M66592_HSMODE: | ||
1044 | m66592->gadget.speed = USB_SPEED_HIGH; | ||
1045 | break; | ||
1046 | case M66592_FSMODE: | ||
1047 | m66592->gadget.speed = USB_SPEED_FULL; | ||
1048 | break; | ||
1049 | default: | ||
1050 | m66592->gadget.speed = USB_SPEED_UNKNOWN; | ||
1051 | printk(KERN_ERR "USB speed unknown\n"); | ||
1052 | } | ||
1053 | } | ||
1054 | |||
1055 | static void irq_device_state(struct m66592 *m66592) | ||
1056 | { | ||
1057 | u16 dvsq; | ||
1058 | |||
1059 | dvsq = m66592_read(m66592, M66592_INTSTS0) & M66592_DVSQ; | ||
1060 | m66592_write(m66592, ~M66592_DVST, M66592_INTSTS0); | ||
1061 | |||
1062 | if (dvsq == M66592_DS_DFLT) { /* bus reset */ | ||
1063 | m66592->driver->disconnect(&m66592->gadget); | ||
1064 | m66592_update_usb_speed(m66592); | ||
1065 | } | ||
1066 | if (m66592->old_dvsq == M66592_DS_CNFG && dvsq != M66592_DS_CNFG) | ||
1067 | m66592_update_usb_speed(m66592); | ||
1068 | if ((dvsq == M66592_DS_CNFG || dvsq == M66592_DS_ADDS) && | ||
1069 | m66592->gadget.speed == USB_SPEED_UNKNOWN) | ||
1070 | m66592_update_usb_speed(m66592); | ||
1071 | |||
1072 | m66592->old_dvsq = dvsq; | ||
1073 | } | ||
1074 | |||
1075 | static void irq_control_stage(struct m66592 *m66592) | ||
1076 | { | ||
1077 | struct usb_ctrlrequest ctrl; | ||
1078 | u16 ctsq; | ||
1079 | |||
1080 | ctsq = m66592_read(m66592, M66592_INTSTS0) & M66592_CTSQ; | ||
1081 | m66592_write(m66592, ~M66592_CTRT, M66592_INTSTS0); | ||
1082 | |||
1083 | switch (ctsq) { | ||
1084 | case M66592_CS_IDST: { | ||
1085 | struct m66592_ep *ep; | ||
1086 | struct m66592_request *req; | ||
1087 | ep = &m66592->ep[0]; | ||
1088 | req = list_entry(ep->queue.next, struct m66592_request, queue); | ||
1089 | transfer_complete(ep, req, 0); | ||
1090 | } | ||
1091 | break; | ||
1092 | |||
1093 | case M66592_CS_RDDS: | ||
1094 | case M66592_CS_WRDS: | ||
1095 | case M66592_CS_WRND: | ||
1096 | if (setup_packet(m66592, &ctrl)) { | ||
1097 | if (m66592->driver->setup(&m66592->gadget, &ctrl) < 0) | ||
1098 | pipe_stall(m66592, 0); | ||
1099 | } | ||
1100 | break; | ||
1101 | case M66592_CS_RDSS: | ||
1102 | case M66592_CS_WRSS: | ||
1103 | control_end(m66592, 0); | ||
1104 | break; | ||
1105 | default: | ||
1106 | printk(KERN_ERR "ctrl_stage: unexpect ctsq(%x)\n", ctsq); | ||
1107 | break; | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | static irqreturn_t m66592_irq(int irq, void *_m66592) | ||
1112 | { | ||
1113 | struct m66592 *m66592 = _m66592; | ||
1114 | u16 intsts0; | ||
1115 | u16 intenb0; | ||
1116 | u16 brdysts, nrdysts, bempsts; | ||
1117 | u16 brdyenb, nrdyenb, bempenb; | ||
1118 | u16 savepipe; | ||
1119 | u16 mask0; | ||
1120 | |||
1121 | intsts0 = m66592_read(m66592, M66592_INTSTS0); | ||
1122 | intenb0 = m66592_read(m66592, M66592_INTENB0); | ||
1123 | |||
1124 | savepipe = m66592_read(m66592, M66592_CFIFOSEL); | ||
1125 | |||
1126 | mask0 = intsts0 & intenb0; | ||
1127 | if (mask0) { | ||
1128 | brdysts = m66592_read(m66592, M66592_BRDYSTS); | ||
1129 | nrdysts = m66592_read(m66592, M66592_NRDYSTS); | ||
1130 | bempsts = m66592_read(m66592, M66592_BEMPSTS); | ||
1131 | brdyenb = m66592_read(m66592, M66592_BRDYENB); | ||
1132 | nrdyenb = m66592_read(m66592, M66592_NRDYENB); | ||
1133 | bempenb = m66592_read(m66592, M66592_BEMPENB); | ||
1134 | |||
1135 | if (mask0 & M66592_VBINT) { | ||
1136 | m66592_write(m66592, (u16)~M66592_VBINT, | ||
1137 | M66592_INTSTS0); | ||
1138 | m66592_start_xclock(m66592); | ||
1139 | |||
1140 | /* start vbus sampling */ | ||
1141 | m66592->old_vbus = m66592_read(m66592, M66592_INTSTS0) | ||
1142 | & M66592_VBSTS; | ||
1143 | m66592->scount = M66592_MAX_SAMPLING; | ||
1144 | |||
1145 | mod_timer(&m66592->timer, | ||
1146 | jiffies + msecs_to_jiffies(50)); | ||
1147 | } | ||
1148 | if (intsts0 & M66592_DVSQ) | ||
1149 | irq_device_state(m66592); | ||
1150 | |||
1151 | if ((intsts0 & M66592_BRDY) && (intenb0 & M66592_BRDYE) && | ||
1152 | (brdysts & brdyenb)) { | ||
1153 | irq_pipe_ready(m66592, brdysts, brdyenb); | ||
1154 | } | ||
1155 | if ((intsts0 & M66592_BEMP) && (intenb0 & M66592_BEMPE) && | ||
1156 | (bempsts & bempenb)) { | ||
1157 | irq_pipe_empty(m66592, bempsts, bempenb); | ||
1158 | } | ||
1159 | |||
1160 | if (intsts0 & M66592_CTRT) | ||
1161 | irq_control_stage(m66592); | ||
1162 | } | ||
1163 | |||
1164 | m66592_write(m66592, savepipe, M66592_CFIFOSEL); | ||
1165 | |||
1166 | return IRQ_HANDLED; | ||
1167 | } | ||
1168 | |||
1169 | static void m66592_timer(unsigned long _m66592) | ||
1170 | { | ||
1171 | struct m66592 *m66592 = (struct m66592 *)_m66592; | ||
1172 | unsigned long flags; | ||
1173 | u16 tmp; | ||
1174 | |||
1175 | spin_lock_irqsave(&m66592->lock, flags); | ||
1176 | tmp = m66592_read(m66592, M66592_SYSCFG); | ||
1177 | if (!(tmp & M66592_RCKE)) { | ||
1178 | m66592_bset(m66592, M66592_RCKE | M66592_PLLC, M66592_SYSCFG); | ||
1179 | udelay(10); | ||
1180 | m66592_bset(m66592, M66592_SCKE, M66592_SYSCFG); | ||
1181 | } | ||
1182 | if (m66592->scount > 0) { | ||
1183 | tmp = m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS; | ||
1184 | if (tmp == m66592->old_vbus) { | ||
1185 | m66592->scount--; | ||
1186 | if (m66592->scount == 0) { | ||
1187 | if (tmp == M66592_VBSTS) | ||
1188 | m66592_usb_connect(m66592); | ||
1189 | else | ||
1190 | m66592_usb_disconnect(m66592); | ||
1191 | } else { | ||
1192 | mod_timer(&m66592->timer, | ||
1193 | jiffies + msecs_to_jiffies(50)); | ||
1194 | } | ||
1195 | } else { | ||
1196 | m66592->scount = M66592_MAX_SAMPLING; | ||
1197 | m66592->old_vbus = tmp; | ||
1198 | mod_timer(&m66592->timer, | ||
1199 | jiffies + msecs_to_jiffies(50)); | ||
1200 | } | ||
1201 | } | ||
1202 | spin_unlock_irqrestore(&m66592->lock, flags); | ||
1203 | } | ||
1204 | |||
1205 | /*-------------------------------------------------------------------------*/ | ||
1206 | static int m66592_enable(struct usb_ep *_ep, | ||
1207 | const struct usb_endpoint_descriptor *desc) | ||
1208 | { | ||
1209 | struct m66592_ep *ep; | ||
1210 | |||
1211 | ep = container_of(_ep, struct m66592_ep, ep); | ||
1212 | return alloc_pipe_config(ep, desc); | ||
1213 | } | ||
1214 | |||
1215 | static int m66592_disable(struct usb_ep *_ep) | ||
1216 | { | ||
1217 | struct m66592_ep *ep; | ||
1218 | struct m66592_request *req; | ||
1219 | unsigned long flags; | ||
1220 | |||
1221 | ep = container_of(_ep, struct m66592_ep, ep); | ||
1222 | BUG_ON(!ep); | ||
1223 | |||
1224 | while (!list_empty(&ep->queue)) { | ||
1225 | req = list_entry(ep->queue.next, struct m66592_request, queue); | ||
1226 | spin_lock_irqsave(&ep->m66592->lock, flags); | ||
1227 | transfer_complete(ep, req, -ECONNRESET); | ||
1228 | spin_unlock_irqrestore(&ep->m66592->lock, flags); | ||
1229 | } | ||
1230 | |||
1231 | pipe_irq_disable(ep->m66592, ep->pipenum); | ||
1232 | return free_pipe_config(ep); | ||
1233 | } | ||
1234 | |||
1235 | static struct usb_request *m66592_alloc_request(struct usb_ep *_ep, | ||
1236 | gfp_t gfp_flags) | ||
1237 | { | ||
1238 | struct m66592_request *req; | ||
1239 | |||
1240 | req = kzalloc(sizeof(struct m66592_request), gfp_flags); | ||
1241 | if (!req) | ||
1242 | return NULL; | ||
1243 | |||
1244 | INIT_LIST_HEAD(&req->queue); | ||
1245 | |||
1246 | return &req->req; | ||
1247 | } | ||
1248 | |||
1249 | static void m66592_free_request(struct usb_ep *_ep, struct usb_request *_req) | ||
1250 | { | ||
1251 | struct m66592_request *req; | ||
1252 | |||
1253 | req = container_of(_req, struct m66592_request, req); | ||
1254 | kfree(req); | ||
1255 | } | ||
1256 | |||
1257 | static void *m66592_alloc_buffer(struct usb_ep *_ep, unsigned bytes, | ||
1258 | dma_addr_t *dma, gfp_t gfp_flags) | ||
1259 | { | ||
1260 | void *buf; | ||
1261 | |||
1262 | buf = kzalloc(bytes, gfp_flags); | ||
1263 | if (dma) | ||
1264 | *dma = virt_to_bus(buf); | ||
1265 | |||
1266 | return buf; | ||
1267 | } | ||
1268 | |||
1269 | static void m66592_free_buffer(struct usb_ep *_ep, void *buf, | ||
1270 | dma_addr_t dma, unsigned bytes) | ||
1271 | { | ||
1272 | kfree(buf); | ||
1273 | } | ||
1274 | |||
1275 | static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req, | ||
1276 | gfp_t gfp_flags) | ||
1277 | { | ||
1278 | struct m66592_ep *ep; | ||
1279 | struct m66592_request *req; | ||
1280 | unsigned long flags; | ||
1281 | int request = 0; | ||
1282 | |||
1283 | ep = container_of(_ep, struct m66592_ep, ep); | ||
1284 | req = container_of(_req, struct m66592_request, req); | ||
1285 | |||
1286 | if (ep->m66592->gadget.speed == USB_SPEED_UNKNOWN) | ||
1287 | return -ESHUTDOWN; | ||
1288 | |||
1289 | spin_lock_irqsave(&ep->m66592->lock, flags); | ||
1290 | |||
1291 | if (list_empty(&ep->queue)) | ||
1292 | request = 1; | ||
1293 | |||
1294 | list_add_tail(&req->queue, &ep->queue); | ||
1295 | req->req.actual = 0; | ||
1296 | req->req.status = -EINPROGRESS; | ||
1297 | |||
1298 | if (ep->desc == 0) /* control */ | ||
1299 | start_ep0(ep, req); | ||
1300 | else { | ||
1301 | if (request && !ep->busy) | ||
1302 | start_packet(ep, req); | ||
1303 | } | ||
1304 | |||
1305 | spin_unlock_irqrestore(&ep->m66592->lock, flags); | ||
1306 | |||
1307 | return 0; | ||
1308 | } | ||
1309 | |||
1310 | static int m66592_dequeue(struct usb_ep *_ep, struct usb_request *_req) | ||
1311 | { | ||
1312 | struct m66592_ep *ep; | ||
1313 | struct m66592_request *req; | ||
1314 | unsigned long flags; | ||
1315 | |||
1316 | ep = container_of(_ep, struct m66592_ep, ep); | ||
1317 | req = container_of(_req, struct m66592_request, req); | ||
1318 | |||
1319 | spin_lock_irqsave(&ep->m66592->lock, flags); | ||
1320 | if (!list_empty(&ep->queue)) | ||
1321 | transfer_complete(ep, req, -ECONNRESET); | ||
1322 | spin_unlock_irqrestore(&ep->m66592->lock, flags); | ||
1323 | |||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | static int m66592_set_halt(struct usb_ep *_ep, int value) | ||
1328 | { | ||
1329 | struct m66592_ep *ep; | ||
1330 | struct m66592_request *req; | ||
1331 | unsigned long flags; | ||
1332 | int ret = 0; | ||
1333 | |||
1334 | ep = container_of(_ep, struct m66592_ep, ep); | ||
1335 | req = list_entry(ep->queue.next, struct m66592_request, queue); | ||
1336 | |||
1337 | spin_lock_irqsave(&ep->m66592->lock, flags); | ||
1338 | if (!list_empty(&ep->queue)) { | ||
1339 | ret = -EAGAIN; | ||
1340 | goto out; | ||
1341 | } | ||
1342 | if (value) { | ||
1343 | ep->busy = 1; | ||
1344 | pipe_stall(ep->m66592, ep->pipenum); | ||
1345 | } else { | ||
1346 | ep->busy = 0; | ||
1347 | pipe_stop(ep->m66592, ep->pipenum); | ||
1348 | } | ||
1349 | |||
1350 | out: | ||
1351 | spin_unlock_irqrestore(&ep->m66592->lock, flags); | ||
1352 | return ret; | ||
1353 | } | ||
1354 | |||
1355 | static int m66592_fifo_status(struct usb_ep *_ep) | ||
1356 | { | ||
1357 | return -EOPNOTSUPP; | ||
1358 | } | ||
1359 | |||
1360 | static void m66592_fifo_flush(struct usb_ep *_ep) | ||
1361 | { | ||
1362 | struct m66592_ep *ep; | ||
1363 | unsigned long flags; | ||
1364 | |||
1365 | ep = container_of(_ep, struct m66592_ep, ep); | ||
1366 | spin_lock_irqsave(&ep->m66592->lock, flags); | ||
1367 | if (list_empty(&ep->queue) && !ep->busy) { | ||
1368 | pipe_stop(ep->m66592, ep->pipenum); | ||
1369 | m66592_bclr(ep->m66592, M66592_BCLR, ep->fifoctr); | ||
1370 | } | ||
1371 | spin_unlock_irqrestore(&ep->m66592->lock, flags); | ||
1372 | } | ||
1373 | |||
1374 | static struct usb_ep_ops m66592_ep_ops = { | ||
1375 | .enable = m66592_enable, | ||
1376 | .disable = m66592_disable, | ||
1377 | |||
1378 | .alloc_request = m66592_alloc_request, | ||
1379 | .free_request = m66592_free_request, | ||
1380 | |||
1381 | .alloc_buffer = m66592_alloc_buffer, | ||
1382 | .free_buffer = m66592_free_buffer, | ||
1383 | |||
1384 | .queue = m66592_queue, | ||
1385 | .dequeue = m66592_dequeue, | ||
1386 | |||
1387 | .set_halt = m66592_set_halt, | ||
1388 | .fifo_status = m66592_fifo_status, | ||
1389 | .fifo_flush = m66592_fifo_flush, | ||
1390 | }; | ||
1391 | |||
1392 | /*-------------------------------------------------------------------------*/ | ||
1393 | static struct m66592 *the_controller; | ||
1394 | |||
1395 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) | ||
1396 | { | ||
1397 | struct m66592 *m66592 = the_controller; | ||
1398 | int retval; | ||
1399 | |||
1400 | if (!driver || | ||
1401 | driver->speed != USB_SPEED_HIGH || | ||
1402 | !driver->bind || | ||
1403 | !driver->unbind || | ||
1404 | !driver->setup) | ||
1405 | return -EINVAL; | ||
1406 | if (!m66592) | ||
1407 | return -ENODEV; | ||
1408 | if (m66592->driver) | ||
1409 | return -EBUSY; | ||
1410 | |||
1411 | /* hook up the driver */ | ||
1412 | driver->driver.bus = NULL; | ||
1413 | m66592->driver = driver; | ||
1414 | m66592->gadget.dev.driver = &driver->driver; | ||
1415 | |||
1416 | retval = device_add(&m66592->gadget.dev); | ||
1417 | if (retval) { | ||
1418 | printk(KERN_ERR "device_add error (%d)\n", retval); | ||
1419 | goto error; | ||
1420 | } | ||
1421 | |||
1422 | retval = driver->bind (&m66592->gadget); | ||
1423 | if (retval) { | ||
1424 | printk(KERN_ERR "bind to driver error (%d)\n", retval); | ||
1425 | device_del(&m66592->gadget.dev); | ||
1426 | goto error; | ||
1427 | } | ||
1428 | |||
1429 | m66592_bset(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0); | ||
1430 | if (m66592_read(m66592, M66592_INTSTS0) & M66592_VBSTS) { | ||
1431 | m66592_start_xclock(m66592); | ||
1432 | /* start vbus sampling */ | ||
1433 | m66592->old_vbus = m66592_read(m66592, | ||
1434 | M66592_INTSTS0) & M66592_VBSTS; | ||
1435 | m66592->scount = M66592_MAX_SAMPLING; | ||
1436 | mod_timer(&m66592->timer, | ||
1437 | jiffies + msecs_to_jiffies(50)); | ||
1438 | } | ||
1439 | |||
1440 | return 0; | ||
1441 | |||
1442 | error: | ||
1443 | m66592->driver = NULL; | ||
1444 | m66592->gadget.dev.driver = NULL; | ||
1445 | |||
1446 | return retval; | ||
1447 | } | ||
1448 | EXPORT_SYMBOL(usb_gadget_register_driver); | ||
1449 | |||
1450 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | ||
1451 | { | ||
1452 | struct m66592 *m66592 = the_controller; | ||
1453 | unsigned long flags; | ||
1454 | |||
1455 | spin_lock_irqsave(&m66592->lock, flags); | ||
1456 | if (m66592->gadget.speed != USB_SPEED_UNKNOWN) | ||
1457 | m66592_usb_disconnect(m66592); | ||
1458 | spin_unlock_irqrestore(&m66592->lock, flags); | ||
1459 | |||
1460 | m66592_bclr(m66592, M66592_VBSE | M66592_URST, M66592_INTENB0); | ||
1461 | |||
1462 | driver->unbind(&m66592->gadget); | ||
1463 | |||
1464 | init_controller(m66592); | ||
1465 | disable_controller(m66592); | ||
1466 | |||
1467 | device_del(&m66592->gadget.dev); | ||
1468 | m66592->driver = NULL; | ||
1469 | return 0; | ||
1470 | } | ||
1471 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | ||
1472 | |||
1473 | /*-------------------------------------------------------------------------*/ | ||
1474 | static int m66592_get_frame(struct usb_gadget *_gadget) | ||
1475 | { | ||
1476 | struct m66592 *m66592 = gadget_to_m66592(_gadget); | ||
1477 | return m66592_read(m66592, M66592_FRMNUM) & 0x03FF; | ||
1478 | } | ||
1479 | |||
1480 | static struct usb_gadget_ops m66592_gadget_ops = { | ||
1481 | .get_frame = m66592_get_frame, | ||
1482 | }; | ||
1483 | |||
1484 | #if defined(CONFIG_PM) | ||
1485 | static int m66592_suspend(struct platform_device *pdev, pm_message_t state) | ||
1486 | { | ||
1487 | pdev->dev.power.power_state = state; | ||
1488 | return 0; | ||
1489 | } | ||
1490 | |||
1491 | static int m66592_resume(struct platform_device *pdev) | ||
1492 | { | ||
1493 | pdev->dev.power.power_state = PMSG_ON; | ||
1494 | return 0; | ||
1495 | } | ||
1496 | #else /* if defined(CONFIG_PM) */ | ||
1497 | #define m66592_suspend NULL | ||
1498 | #define m66592_resume NULL | ||
1499 | #endif | ||
1500 | |||
1501 | static int __init_or_module m66592_remove(struct platform_device *pdev) | ||
1502 | { | ||
1503 | struct m66592 *m66592 = dev_get_drvdata(&pdev->dev); | ||
1504 | |||
1505 | del_timer_sync(&m66592->timer); | ||
1506 | iounmap(m66592->reg); | ||
1507 | free_irq(platform_get_irq(pdev, 0), m66592); | ||
1508 | kfree(m66592); | ||
1509 | return 0; | ||
1510 | } | ||
1511 | |||
1512 | #define resource_len(r) (((r)->end - (r)->start) + 1) | ||
1513 | static int __init m66592_probe(struct platform_device *pdev) | ||
1514 | { | ||
1515 | struct resource *res = NULL; | ||
1516 | int irq = -1; | ||
1517 | void __iomem *reg = NULL; | ||
1518 | struct m66592 *m66592 = NULL; | ||
1519 | int ret = 0; | ||
1520 | int i; | ||
1521 | |||
1522 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
1523 | (char *)udc_name); | ||
1524 | if (!res) { | ||
1525 | ret = -ENODEV; | ||
1526 | printk(KERN_ERR "platform_get_resource_byname error.\n"); | ||
1527 | goto clean_up; | ||
1528 | } | ||
1529 | |||
1530 | irq = platform_get_irq(pdev, 0); | ||
1531 | if (irq < 0) { | ||
1532 | ret = -ENODEV; | ||
1533 | printk(KERN_ERR "platform_get_irq error.\n"); | ||
1534 | goto clean_up; | ||
1535 | } | ||
1536 | |||
1537 | reg = ioremap(res->start, resource_len(res)); | ||
1538 | if (reg == NULL) { | ||
1539 | ret = -ENOMEM; | ||
1540 | printk(KERN_ERR "ioremap error.\n"); | ||
1541 | goto clean_up; | ||
1542 | } | ||
1543 | |||
1544 | /* initialize ucd */ | ||
1545 | m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL); | ||
1546 | if (m66592 == NULL) { | ||
1547 | printk(KERN_ERR "kzalloc error\n"); | ||
1548 | goto clean_up; | ||
1549 | } | ||
1550 | |||
1551 | spin_lock_init(&m66592->lock); | ||
1552 | dev_set_drvdata(&pdev->dev, m66592); | ||
1553 | |||
1554 | m66592->gadget.ops = &m66592_gadget_ops; | ||
1555 | device_initialize(&m66592->gadget.dev); | ||
1556 | strcpy(m66592->gadget.dev.bus_id, "gadget"); | ||
1557 | m66592->gadget.is_dualspeed = 1; | ||
1558 | m66592->gadget.dev.parent = &pdev->dev; | ||
1559 | m66592->gadget.dev.dma_mask = pdev->dev.dma_mask; | ||
1560 | m66592->gadget.dev.release = pdev->dev.release; | ||
1561 | m66592->gadget.name = udc_name; | ||
1562 | |||
1563 | init_timer(&m66592->timer); | ||
1564 | m66592->timer.function = m66592_timer; | ||
1565 | m66592->timer.data = (unsigned long)m66592; | ||
1566 | m66592->reg = reg; | ||
1567 | |||
1568 | m66592->bi_bufnum = M66592_BASE_BUFNUM; | ||
1569 | |||
1570 | ret = request_irq(irq, m66592_irq, IRQF_DISABLED | IRQF_SHARED, | ||
1571 | udc_name, m66592); | ||
1572 | if (ret < 0) { | ||
1573 | printk(KERN_ERR "request_irq error (%d)\n", ret); | ||
1574 | goto clean_up; | ||
1575 | } | ||
1576 | |||
1577 | INIT_LIST_HEAD(&m66592->gadget.ep_list); | ||
1578 | m66592->gadget.ep0 = &m66592->ep[0].ep; | ||
1579 | INIT_LIST_HEAD(&m66592->gadget.ep0->ep_list); | ||
1580 | for (i = 0; i < M66592_MAX_NUM_PIPE; i++) { | ||
1581 | struct m66592_ep *ep = &m66592->ep[i]; | ||
1582 | |||
1583 | if (i != 0) { | ||
1584 | INIT_LIST_HEAD(&m66592->ep[i].ep.ep_list); | ||
1585 | list_add_tail(&m66592->ep[i].ep.ep_list, | ||
1586 | &m66592->gadget.ep_list); | ||
1587 | } | ||
1588 | ep->m66592 = m66592; | ||
1589 | INIT_LIST_HEAD(&ep->queue); | ||
1590 | ep->ep.name = m66592_ep_name[i]; | ||
1591 | ep->ep.ops = &m66592_ep_ops; | ||
1592 | ep->ep.maxpacket = 512; | ||
1593 | } | ||
1594 | m66592->ep[0].ep.maxpacket = 64; | ||
1595 | m66592->ep[0].pipenum = 0; | ||
1596 | m66592->ep[0].fifoaddr = M66592_CFIFO; | ||
1597 | m66592->ep[0].fifosel = M66592_CFIFOSEL; | ||
1598 | m66592->ep[0].fifoctr = M66592_CFIFOCTR; | ||
1599 | m66592->ep[0].fifotrn = 0; | ||
1600 | m66592->ep[0].pipectr = get_pipectr_addr(0); | ||
1601 | m66592->pipenum2ep[0] = &m66592->ep[0]; | ||
1602 | m66592->epaddr2ep[0] = &m66592->ep[0]; | ||
1603 | |||
1604 | the_controller = m66592; | ||
1605 | |||
1606 | m66592->ep0_req = m66592_alloc_request(&m66592->ep[0].ep, GFP_KERNEL); | ||
1607 | if (m66592->ep0_req == NULL) | ||
1608 | goto clean_up; | ||
1609 | m66592->ep0_buf = m66592_alloc_buffer(&m66592->ep[0].ep, 2, NULL, | ||
1610 | GFP_KERNEL); | ||
1611 | if (m66592->ep0_buf == NULL) | ||
1612 | goto clean_up; | ||
1613 | |||
1614 | init_controller(m66592); | ||
1615 | |||
1616 | printk("driver %s, %s\n", udc_name, DRIVER_VERSION); | ||
1617 | return 0; | ||
1618 | |||
1619 | clean_up: | ||
1620 | if (m66592) { | ||
1621 | if (m66592->ep0_req) | ||
1622 | m66592_free_request(&m66592->ep[0].ep, m66592->ep0_req); | ||
1623 | kfree(m66592); | ||
1624 | } | ||
1625 | if (reg) | ||
1626 | iounmap(reg); | ||
1627 | |||
1628 | return ret; | ||
1629 | } | ||
1630 | |||
1631 | /*-------------------------------------------------------------------------*/ | ||
1632 | static struct platform_driver m66592_driver = { | ||
1633 | .probe = m66592_probe, | ||
1634 | .remove = m66592_remove, | ||
1635 | .suspend = m66592_suspend, | ||
1636 | .resume = m66592_resume, | ||
1637 | .driver = { | ||
1638 | .name = (char *) udc_name, | ||
1639 | }, | ||
1640 | }; | ||
1641 | |||
1642 | static int __init m66592_udc_init(void) | ||
1643 | { | ||
1644 | return platform_driver_register(&m66592_driver); | ||
1645 | } | ||
1646 | module_init(m66592_udc_init); | ||
1647 | |||
1648 | static void __exit m66592_udc_cleanup(void) | ||
1649 | { | ||
1650 | platform_driver_unregister(&m66592_driver); | ||
1651 | } | ||
1652 | module_exit(m66592_udc_cleanup); | ||
1653 | |||
diff --git a/drivers/usb/gadget/m66592-udc.h b/drivers/usb/gadget/m66592-udc.h new file mode 100644 index 000000000000..26b54f8b8945 --- /dev/null +++ b/drivers/usb/gadget/m66592-udc.h | |||
@@ -0,0 +1,577 @@ | |||
1 | /* | ||
2 | * M66592 UDC (USB gadget) | ||
3 | * | ||
4 | * Copyright (C) 2006-2007 Renesas Solutions Corp. | ||
5 | * | ||
6 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #ifndef __M66592_UDC_H__ | ||
24 | #define __M66592_UDC_H__ | ||
25 | |||
26 | #define M66592_SYSCFG 0x00 | ||
27 | #define M66592_XTAL 0xC000 /* b15-14: Crystal selection */ | ||
28 | #define M66592_XTAL48 0x8000 /* 48MHz */ | ||
29 | #define M66592_XTAL24 0x4000 /* 24MHz */ | ||
30 | #define M66592_XTAL12 0x0000 /* 12MHz */ | ||
31 | #define M66592_XCKE 0x2000 /* b13: External clock enable */ | ||
32 | #define M66592_RCKE 0x1000 /* b12: Register clock enable */ | ||
33 | #define M66592_PLLC 0x0800 /* b11: PLL control */ | ||
34 | #define M66592_SCKE 0x0400 /* b10: USB clock enable */ | ||
35 | #define M66592_ATCKM 0x0100 /* b8: Automatic supply functional enable */ | ||
36 | #define M66592_HSE 0x0080 /* b7: Hi-speed enable */ | ||
37 | #define M66592_DCFM 0x0040 /* b6: Controller function select */ | ||
38 | #define M66592_DMRPD 0x0020 /* b5: D- pull down control */ | ||
39 | #define M66592_DPRPU 0x0010 /* b4: D+ pull up control */ | ||
40 | #define M66592_FSRPC 0x0004 /* b2: Full-speed receiver enable */ | ||
41 | #define M66592_PCUT 0x0002 /* b1: Low power sleep enable */ | ||
42 | #define M66592_USBE 0x0001 /* b0: USB module operation enable */ | ||
43 | |||
44 | #define M66592_SYSSTS 0x02 | ||
45 | #define M66592_LNST 0x0003 /* b1-0: D+, D- line status */ | ||
46 | #define M66592_SE1 0x0003 /* SE1 */ | ||
47 | #define M66592_KSTS 0x0002 /* K State */ | ||
48 | #define M66592_JSTS 0x0001 /* J State */ | ||
49 | #define M66592_SE0 0x0000 /* SE0 */ | ||
50 | |||
51 | #define M66592_DVSTCTR 0x04 | ||
52 | #define M66592_WKUP 0x0100 /* b8: Remote wakeup */ | ||
53 | #define M66592_RWUPE 0x0080 /* b7: Remote wakeup sense */ | ||
54 | #define M66592_USBRST 0x0040 /* b6: USB reset enable */ | ||
55 | #define M66592_RESUME 0x0020 /* b5: Resume enable */ | ||
56 | #define M66592_UACT 0x0010 /* b4: USB bus enable */ | ||
57 | #define M66592_RHST 0x0003 /* b1-0: Reset handshake status */ | ||
58 | #define M66592_HSMODE 0x0003 /* Hi-Speed mode */ | ||
59 | #define M66592_FSMODE 0x0002 /* Full-Speed mode */ | ||
60 | #define M66592_HSPROC 0x0001 /* HS handshake is processing */ | ||
61 | |||
62 | #define M66592_TESTMODE 0x06 | ||
63 | #define M66592_UTST 0x000F /* b4-0: Test select */ | ||
64 | #define M66592_H_TST_PACKET 0x000C /* HOST TEST Packet */ | ||
65 | #define M66592_H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */ | ||
66 | #define M66592_H_TST_K 0x000A /* HOST TEST K */ | ||
67 | #define M66592_H_TST_J 0x0009 /* HOST TEST J */ | ||
68 | #define M66592_H_TST_NORMAL 0x0000 /* HOST Normal Mode */ | ||
69 | #define M66592_P_TST_PACKET 0x0004 /* PERI TEST Packet */ | ||
70 | #define M66592_P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */ | ||
71 | #define M66592_P_TST_K 0x0002 /* PERI TEST K */ | ||
72 | #define M66592_P_TST_J 0x0001 /* PERI TEST J */ | ||
73 | #define M66592_P_TST_NORMAL 0x0000 /* PERI Normal Mode */ | ||
74 | |||
75 | #define M66592_PINCFG 0x0A | ||
76 | #define M66592_LDRV 0x8000 /* b15: Drive Current Adjust */ | ||
77 | #define M66592_BIGEND 0x0100 /* b8: Big endian mode */ | ||
78 | |||
79 | #define M66592_DMA0CFG 0x0C | ||
80 | #define M66592_DMA1CFG 0x0E | ||
81 | #define M66592_DREQA 0x4000 /* b14: Dreq active select */ | ||
82 | #define M66592_BURST 0x2000 /* b13: Burst mode */ | ||
83 | #define M66592_DACKA 0x0400 /* b10: Dack active select */ | ||
84 | #define M66592_DFORM 0x0380 /* b9-7: DMA mode select */ | ||
85 | #define M66592_CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */ | ||
86 | #define M66592_CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */ | ||
87 | #define M66592_CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */ | ||
88 | #define M66592_SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */ | ||
89 | #define M66592_SPLIT_DACK_DSTB 0x0300 /* DACK + DSTB0 mode (SPLIT bus) */ | ||
90 | #define M66592_DENDA 0x0040 /* b6: Dend active select */ | ||
91 | #define M66592_PKTM 0x0020 /* b5: Packet mode */ | ||
92 | #define M66592_DENDE 0x0010 /* b4: Dend enable */ | ||
93 | #define M66592_OBUS 0x0004 /* b2: OUTbus mode */ | ||
94 | |||
95 | #define M66592_CFIFO 0x10 | ||
96 | #define M66592_D0FIFO 0x14 | ||
97 | #define M66592_D1FIFO 0x18 | ||
98 | |||
99 | #define M66592_CFIFOSEL 0x1E | ||
100 | #define M66592_D0FIFOSEL 0x24 | ||
101 | #define M66592_D1FIFOSEL 0x2A | ||
102 | #define M66592_RCNT 0x8000 /* b15: Read count mode */ | ||
103 | #define M66592_REW 0x4000 /* b14: Buffer rewind */ | ||
104 | #define M66592_DCLRM 0x2000 /* b13: DMA buffer clear mode */ | ||
105 | #define M66592_DREQE 0x1000 /* b12: DREQ output enable */ | ||
106 | #define M66592_MBW 0x0400 /* b10: Maximum bit width for FIFO access */ | ||
107 | #define M66592_MBW_8 0x0000 /* 8bit */ | ||
108 | #define M66592_MBW_16 0x0400 /* 16bit */ | ||
109 | #define M66592_TRENB 0x0200 /* b9: Transaction counter enable */ | ||
110 | #define M66592_TRCLR 0x0100 /* b8: Transaction counter clear */ | ||
111 | #define M66592_DEZPM 0x0080 /* b7: Zero-length packet additional mode */ | ||
112 | #define M66592_ISEL 0x0020 /* b5: DCP FIFO port direction select */ | ||
113 | #define M66592_CURPIPE 0x0007 /* b2-0: PIPE select */ | ||
114 | |||
115 | #define M66592_CFIFOCTR 0x20 | ||
116 | #define M66592_D0FIFOCTR 0x26 | ||
117 | #define M66592_D1FIFOCTR 0x2c | ||
118 | #define M66592_BVAL 0x8000 /* b15: Buffer valid flag */ | ||
119 | #define M66592_BCLR 0x4000 /* b14: Buffer clear */ | ||
120 | #define M66592_FRDY 0x2000 /* b13: FIFO ready */ | ||
121 | #define M66592_DTLN 0x0FFF /* b11-0: FIFO received data length */ | ||
122 | |||
123 | #define M66592_CFIFOSIE 0x22 | ||
124 | #define M66592_TGL 0x8000 /* b15: Buffer toggle */ | ||
125 | #define M66592_SCLR 0x4000 /* b14: Buffer clear */ | ||
126 | #define M66592_SBUSY 0x2000 /* b13: SIE_FIFO busy */ | ||
127 | |||
128 | #define M66592_D0FIFOTRN 0x28 | ||
129 | #define M66592_D1FIFOTRN 0x2E | ||
130 | #define M66592_TRNCNT 0xFFFF /* b15-0: Transaction counter */ | ||
131 | |||
132 | #define M66592_INTENB0 0x30 | ||
133 | #define M66592_VBSE 0x8000 /* b15: VBUS interrupt */ | ||
134 | #define M66592_RSME 0x4000 /* b14: Resume interrupt */ | ||
135 | #define M66592_SOFE 0x2000 /* b13: Frame update interrupt */ | ||
136 | #define M66592_DVSE 0x1000 /* b12: Device state transition interrupt */ | ||
137 | #define M66592_CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ | ||
138 | #define M66592_BEMPE 0x0400 /* b10: Buffer empty interrupt */ | ||
139 | #define M66592_NRDYE 0x0200 /* b9: Buffer not ready interrupt */ | ||
140 | #define M66592_BRDYE 0x0100 /* b8: Buffer ready interrupt */ | ||
141 | #define M66592_URST 0x0080 /* b7: USB reset detected interrupt */ | ||
142 | #define M66592_SADR 0x0040 /* b6: Set address executed interrupt */ | ||
143 | #define M66592_SCFG 0x0020 /* b5: Set configuration executed interrupt */ | ||
144 | #define M66592_SUSP 0x0010 /* b4: Suspend detected interrupt */ | ||
145 | #define M66592_WDST 0x0008 /* b3: Control write data stage completed interrupt */ | ||
146 | #define M66592_RDST 0x0004 /* b2: Control read data stage completed interrupt */ | ||
147 | #define M66592_CMPL 0x0002 /* b1: Control transfer complete interrupt */ | ||
148 | #define M66592_SERR 0x0001 /* b0: Sequence error interrupt */ | ||
149 | |||
150 | #define M66592_INTENB1 0x32 | ||
151 | #define M66592_BCHGE 0x4000 /* b14: USB us chenge interrupt */ | ||
152 | #define M66592_DTCHE 0x1000 /* b12: Detach sense interrupt */ | ||
153 | #define M66592_SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */ | ||
154 | #define M66592_SACKE 0x0010 /* b4: SETUP ACK interrupt */ | ||
155 | #define M66592_BRDYM 0x0004 /* b2: BRDY clear timing */ | ||
156 | #define M66592_INTL 0x0002 /* b1: Interrupt sense select */ | ||
157 | #define M66592_PCSE 0x0001 /* b0: PCUT enable by CS assert */ | ||
158 | |||
159 | #define M66592_BRDYENB 0x36 | ||
160 | #define M66592_BRDYSTS 0x46 | ||
161 | #define M66592_BRDY7 0x0080 /* b7: PIPE7 */ | ||
162 | #define M66592_BRDY6 0x0040 /* b6: PIPE6 */ | ||
163 | #define M66592_BRDY5 0x0020 /* b5: PIPE5 */ | ||
164 | #define M66592_BRDY4 0x0010 /* b4: PIPE4 */ | ||
165 | #define M66592_BRDY3 0x0008 /* b3: PIPE3 */ | ||
166 | #define M66592_BRDY2 0x0004 /* b2: PIPE2 */ | ||
167 | #define M66592_BRDY1 0x0002 /* b1: PIPE1 */ | ||
168 | #define M66592_BRDY0 0x0001 /* b1: PIPE0 */ | ||
169 | |||
170 | #define M66592_NRDYENB 0x38 | ||
171 | #define M66592_NRDYSTS 0x48 | ||
172 | #define M66592_NRDY7 0x0080 /* b7: PIPE7 */ | ||
173 | #define M66592_NRDY6 0x0040 /* b6: PIPE6 */ | ||
174 | #define M66592_NRDY5 0x0020 /* b5: PIPE5 */ | ||
175 | #define M66592_NRDY4 0x0010 /* b4: PIPE4 */ | ||
176 | #define M66592_NRDY3 0x0008 /* b3: PIPE3 */ | ||
177 | #define M66592_NRDY2 0x0004 /* b2: PIPE2 */ | ||
178 | #define M66592_NRDY1 0x0002 /* b1: PIPE1 */ | ||
179 | #define M66592_NRDY0 0x0001 /* b1: PIPE0 */ | ||
180 | |||
181 | #define M66592_BEMPENB 0x3A | ||
182 | #define M66592_BEMPSTS 0x4A | ||
183 | #define M66592_BEMP7 0x0080 /* b7: PIPE7 */ | ||
184 | #define M66592_BEMP6 0x0040 /* b6: PIPE6 */ | ||
185 | #define M66592_BEMP5 0x0020 /* b5: PIPE5 */ | ||
186 | #define M66592_BEMP4 0x0010 /* b4: PIPE4 */ | ||
187 | #define M66592_BEMP3 0x0008 /* b3: PIPE3 */ | ||
188 | #define M66592_BEMP2 0x0004 /* b2: PIPE2 */ | ||
189 | #define M66592_BEMP1 0x0002 /* b1: PIPE1 */ | ||
190 | #define M66592_BEMP0 0x0001 /* b0: PIPE0 */ | ||
191 | |||
192 | #define M66592_SOFCFG 0x3C | ||
193 | #define M66592_SOFM 0x000C /* b3-2: SOF palse mode */ | ||
194 | #define M66592_SOF_125US 0x0008 /* SOF OUT 125us uFrame Signal */ | ||
195 | #define M66592_SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */ | ||
196 | #define M66592_SOF_DISABLE 0x0000 /* SOF OUT Disable */ | ||
197 | |||
198 | #define M66592_INTSTS0 0x40 | ||
199 | #define M66592_VBINT 0x8000 /* b15: VBUS interrupt */ | ||
200 | #define M66592_RESM 0x4000 /* b14: Resume interrupt */ | ||
201 | #define M66592_SOFR 0x2000 /* b13: SOF frame update interrupt */ | ||
202 | #define M66592_DVST 0x1000 /* b12: Device state transition interrupt */ | ||
203 | #define M66592_CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ | ||
204 | #define M66592_BEMP 0x0400 /* b10: Buffer empty interrupt */ | ||
205 | #define M66592_NRDY 0x0200 /* b9: Buffer not ready interrupt */ | ||
206 | #define M66592_BRDY 0x0100 /* b8: Buffer ready interrupt */ | ||
207 | #define M66592_VBSTS 0x0080 /* b7: VBUS input port */ | ||
208 | #define M66592_DVSQ 0x0070 /* b6-4: Device state */ | ||
209 | #define M66592_DS_SPD_CNFG 0x0070 /* Suspend Configured */ | ||
210 | #define M66592_DS_SPD_ADDR 0x0060 /* Suspend Address */ | ||
211 | #define M66592_DS_SPD_DFLT 0x0050 /* Suspend Default */ | ||
212 | #define M66592_DS_SPD_POWR 0x0040 /* Suspend Powered */ | ||
213 | #define M66592_DS_SUSP 0x0040 /* Suspend */ | ||
214 | #define M66592_DS_CNFG 0x0030 /* Configured */ | ||
215 | #define M66592_DS_ADDS 0x0020 /* Address */ | ||
216 | #define M66592_DS_DFLT 0x0010 /* Default */ | ||
217 | #define M66592_DS_POWR 0x0000 /* Powered */ | ||
218 | #define M66592_DVSQS 0x0030 /* b5-4: Device state */ | ||
219 | #define M66592_VALID 0x0008 /* b3: Setup packet detected flag */ | ||
220 | #define M66592_CTSQ 0x0007 /* b2-0: Control transfer stage */ | ||
221 | #define M66592_CS_SQER 0x0006 /* Sequence error */ | ||
222 | #define M66592_CS_WRND 0x0005 /* Control write nodata status stage */ | ||
223 | #define M66592_CS_WRSS 0x0004 /* Control write status stage */ | ||
224 | #define M66592_CS_WRDS 0x0003 /* Control write data stage */ | ||
225 | #define M66592_CS_RDSS 0x0002 /* Control read status stage */ | ||
226 | #define M66592_CS_RDDS 0x0001 /* Control read data stage */ | ||
227 | #define M66592_CS_IDST 0x0000 /* Idle or setup stage */ | ||
228 | |||
229 | #define M66592_INTSTS1 0x42 | ||
230 | #define M66592_BCHG 0x4000 /* b14: USB bus chenge interrupt */ | ||
231 | #define M66592_DTCH 0x1000 /* b12: Detach sense interrupt */ | ||
232 | #define M66592_SIGN 0x0020 /* b5: SETUP IGNORE interrupt */ | ||
233 | #define M66592_SACK 0x0010 /* b4: SETUP ACK interrupt */ | ||
234 | |||
235 | #define M66592_FRMNUM 0x4C | ||
236 | #define M66592_OVRN 0x8000 /* b15: Overrun error */ | ||
237 | #define M66592_CRCE 0x4000 /* b14: Received data error */ | ||
238 | #define M66592_SOFRM 0x0800 /* b11: SOF output mode */ | ||
239 | #define M66592_FRNM 0x07FF /* b10-0: Frame number */ | ||
240 | |||
241 | #define M66592_UFRMNUM 0x4E | ||
242 | #define M66592_UFRNM 0x0007 /* b2-0: Micro frame number */ | ||
243 | |||
244 | #define M66592_RECOVER 0x50 | ||
245 | #define M66592_STSRECOV 0x0700 /* Status recovery */ | ||
246 | #define M66592_STSR_HI 0x0400 /* FULL(0) or HI(1) Speed */ | ||
247 | #define M66592_STSR_DEFAULT 0x0100 /* Default state */ | ||
248 | #define M66592_STSR_ADDRESS 0x0200 /* Address state */ | ||
249 | #define M66592_STSR_CONFIG 0x0300 /* Configured state */ | ||
250 | #define M66592_USBADDR 0x007F /* b6-0: USB address */ | ||
251 | |||
252 | #define M66592_USBREQ 0x54 | ||
253 | #define M66592_bRequest 0xFF00 /* b15-8: bRequest */ | ||
254 | #define M66592_GET_STATUS 0x0000 | ||
255 | #define M66592_CLEAR_FEATURE 0x0100 | ||
256 | #define M66592_ReqRESERVED 0x0200 | ||
257 | #define M66592_SET_FEATURE 0x0300 | ||
258 | #define M66592_ReqRESERVED1 0x0400 | ||
259 | #define M66592_SET_ADDRESS 0x0500 | ||
260 | #define M66592_GET_DESCRIPTOR 0x0600 | ||
261 | #define M66592_SET_DESCRIPTOR 0x0700 | ||
262 | #define M66592_GET_CONFIGURATION 0x0800 | ||
263 | #define M66592_SET_CONFIGURATION 0x0900 | ||
264 | #define M66592_GET_INTERFACE 0x0A00 | ||
265 | #define M66592_SET_INTERFACE 0x0B00 | ||
266 | #define M66592_SYNCH_FRAME 0x0C00 | ||
267 | #define M66592_bmRequestType 0x00FF /* b7-0: bmRequestType */ | ||
268 | #define M66592_bmRequestTypeDir 0x0080 /* b7 : Data transfer direction */ | ||
269 | #define M66592_HOST_TO_DEVICE 0x0000 | ||
270 | #define M66592_DEVICE_TO_HOST 0x0080 | ||
271 | #define M66592_bmRequestTypeType 0x0060 /* b6-5: Type */ | ||
272 | #define M66592_STANDARD 0x0000 | ||
273 | #define M66592_CLASS 0x0020 | ||
274 | #define M66592_VENDOR 0x0040 | ||
275 | #define M66592_bmRequestTypeRecip 0x001F /* b4-0: Recipient */ | ||
276 | #define M66592_DEVICE 0x0000 | ||
277 | #define M66592_INTERFACE 0x0001 | ||
278 | #define M66592_ENDPOINT 0x0002 | ||
279 | |||
280 | #define M66592_USBVAL 0x56 | ||
281 | #define M66592_wValue 0xFFFF /* b15-0: wValue */ | ||
282 | /* Standard Feature Selector */ | ||
283 | #define M66592_ENDPOINT_HALT 0x0000 | ||
284 | #define M66592_DEVICE_REMOTE_WAKEUP 0x0001 | ||
285 | #define M66592_TEST_MODE 0x0002 | ||
286 | /* Descriptor Types */ | ||
287 | #define M66592_DT_TYPE 0xFF00 | ||
288 | #define M66592_GET_DT_TYPE(v) (((v) & DT_TYPE) >> 8) | ||
289 | #define M66592_DT_DEVICE 0x01 | ||
290 | #define M66592_DT_CONFIGURATION 0x02 | ||
291 | #define M66592_DT_STRING 0x03 | ||
292 | #define M66592_DT_INTERFACE 0x04 | ||
293 | #define M66592_DT_ENDPOINT 0x05 | ||
294 | #define M66592_DT_DEVICE_QUALIFIER 0x06 | ||
295 | #define M66592_DT_OTHER_SPEED_CONFIGURATION 0x07 | ||
296 | #define M66592_DT_INTERFACE_POWER 0x08 | ||
297 | #define M66592_DT_INDEX 0x00FF | ||
298 | #define M66592_CONF_NUM 0x00FF | ||
299 | #define M66592_ALT_SET 0x00FF | ||
300 | |||
301 | #define M66592_USBINDEX 0x58 | ||
302 | #define M66592_wIndex 0xFFFF /* b15-0: wIndex */ | ||
303 | #define M66592_TEST_SELECT 0xFF00 /* b15-b8: Test Mode Selectors */ | ||
304 | #define M66592_TEST_J 0x0100 /* Test_J */ | ||
305 | #define M66592_TEST_K 0x0200 /* Test_K */ | ||
306 | #define M66592_TEST_SE0_NAK 0x0300 /* Test_SE0_NAK */ | ||
307 | #define M66592_TEST_PACKET 0x0400 /* Test_Packet */ | ||
308 | #define M66592_TEST_FORCE_ENABLE 0x0500 /* Test_Force_Enable */ | ||
309 | #define M66592_TEST_STSelectors 0x0600 /* Standard test selectors */ | ||
310 | #define M66592_TEST_Reserved 0x4000 /* Reserved */ | ||
311 | #define M66592_TEST_VSTModes 0xC000 /* Vendor-specific test modes */ | ||
312 | #define M66592_EP_DIR 0x0080 /* b7: Endpoint Direction */ | ||
313 | #define M66592_EP_DIR_IN 0x0080 | ||
314 | #define M66592_EP_DIR_OUT 0x0000 | ||
315 | |||
316 | #define M66592_USBLENG 0x5A | ||
317 | #define M66592_wLength 0xFFFF /* b15-0: wLength */ | ||
318 | |||
319 | #define M66592_DCPCFG 0x5C | ||
320 | #define M66592_CNTMD 0x0100 /* b8: Continuous transfer mode select */ | ||
321 | #define M66592_DIR 0x0010 /* b4: Control transfer DIR select */ | ||
322 | |||
323 | #define M66592_DCPMAXP 0x5E | ||
324 | #define M66592_DEVSEL 0xC000 /* b15-14: Device address select */ | ||
325 | #define M66592_DEVICE_0 0x0000 /* Device address 0 */ | ||
326 | #define M66592_DEVICE_1 0x4000 /* Device address 1 */ | ||
327 | #define M66592_DEVICE_2 0x8000 /* Device address 2 */ | ||
328 | #define M66592_DEVICE_3 0xC000 /* Device address 3 */ | ||
329 | #define M66592_MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ | ||
330 | |||
331 | #define M66592_DCPCTR 0x60 | ||
332 | #define M66592_BSTS 0x8000 /* b15: Buffer status */ | ||
333 | #define M66592_SUREQ 0x4000 /* b14: Send USB request */ | ||
334 | #define M66592_SQCLR 0x0100 /* b8: Sequence toggle bit clear */ | ||
335 | #define M66592_SQSET 0x0080 /* b7: Sequence toggle bit set */ | ||
336 | #define M66592_SQMON 0x0040 /* b6: Sequence toggle bit monitor */ | ||
337 | #define M66592_CCPL 0x0004 /* b2: Enable control transfer complete */ | ||
338 | #define M66592_PID 0x0003 /* b1-0: Response PID */ | ||
339 | #define M66592_PID_STALL 0x0002 /* STALL */ | ||
340 | #define M66592_PID_BUF 0x0001 /* BUF */ | ||
341 | #define M66592_PID_NAK 0x0000 /* NAK */ | ||
342 | |||
343 | #define M66592_PIPESEL 0x64 | ||
344 | #define M66592_PIPENM 0x0007 /* b2-0: Pipe select */ | ||
345 | #define M66592_PIPE0 0x0000 /* PIPE 0 */ | ||
346 | #define M66592_PIPE1 0x0001 /* PIPE 1 */ | ||
347 | #define M66592_PIPE2 0x0002 /* PIPE 2 */ | ||
348 | #define M66592_PIPE3 0x0003 /* PIPE 3 */ | ||
349 | #define M66592_PIPE4 0x0004 /* PIPE 4 */ | ||
350 | #define M66592_PIPE5 0x0005 /* PIPE 5 */ | ||
351 | #define M66592_PIPE6 0x0006 /* PIPE 6 */ | ||
352 | #define M66592_PIPE7 0x0007 /* PIPE 7 */ | ||
353 | |||
354 | #define M66592_PIPECFG 0x66 | ||
355 | #define M66592_TYP 0xC000 /* b15-14: Transfer type */ | ||
356 | #define M66592_ISO 0xC000 /* Isochronous */ | ||
357 | #define M66592_INT 0x8000 /* Interrupt */ | ||
358 | #define M66592_BULK 0x4000 /* Bulk */ | ||
359 | #define M66592_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */ | ||
360 | #define M66592_DBLB 0x0200 /* b9: Double buffer mode select */ | ||
361 | #define M66592_CNTMD 0x0100 /* b8: Continuous transfer mode select */ | ||
362 | #define M66592_SHTNAK 0x0080 /* b7: Transfer end NAK */ | ||
363 | #define M66592_DIR 0x0010 /* b4: Transfer direction select */ | ||
364 | #define M66592_DIR_H_OUT 0x0010 /* HOST OUT */ | ||
365 | #define M66592_DIR_P_IN 0x0010 /* PERI IN */ | ||
366 | #define M66592_DIR_H_IN 0x0000 /* HOST IN */ | ||
367 | #define M66592_DIR_P_OUT 0x0000 /* PERI OUT */ | ||
368 | #define M66592_EPNUM 0x000F /* b3-0: Eendpoint number select */ | ||
369 | #define M66592_EP1 0x0001 | ||
370 | #define M66592_EP2 0x0002 | ||
371 | #define M66592_EP3 0x0003 | ||
372 | #define M66592_EP4 0x0004 | ||
373 | #define M66592_EP5 0x0005 | ||
374 | #define M66592_EP6 0x0006 | ||
375 | #define M66592_EP7 0x0007 | ||
376 | #define M66592_EP8 0x0008 | ||
377 | #define M66592_EP9 0x0009 | ||
378 | #define M66592_EP10 0x000A | ||
379 | #define M66592_EP11 0x000B | ||
380 | #define M66592_EP12 0x000C | ||
381 | #define M66592_EP13 0x000D | ||
382 | #define M66592_EP14 0x000E | ||
383 | #define M66592_EP15 0x000F | ||
384 | |||
385 | #define M66592_PIPEBUF 0x68 | ||
386 | #define M66592_BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */ | ||
387 | #define M66592_BUF_SIZE(x) ((((x) / 64) - 1) << 10) | ||
388 | #define M66592_BUFNMB 0x00FF /* b7-0: Pipe buffer number */ | ||
389 | |||
390 | #define M66592_PIPEMAXP 0x6A | ||
391 | #define M66592_MXPS 0x07FF /* b10-0: Maxpacket size */ | ||
392 | |||
393 | #define M66592_PIPEPERI 0x6C | ||
394 | #define M66592_IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ | ||
395 | #define M66592_IITV 0x0007 /* b2-0: Isochronous interval */ | ||
396 | |||
397 | #define M66592_PIPE1CTR 0x70 | ||
398 | #define M66592_PIPE2CTR 0x72 | ||
399 | #define M66592_PIPE3CTR 0x74 | ||
400 | #define M66592_PIPE4CTR 0x76 | ||
401 | #define M66592_PIPE5CTR 0x78 | ||
402 | #define M66592_PIPE6CTR 0x7A | ||
403 | #define M66592_PIPE7CTR 0x7C | ||
404 | #define M66592_BSTS 0x8000 /* b15: Buffer status */ | ||
405 | #define M66592_INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ | ||
406 | #define M66592_ACLRM 0x0200 /* b9: Out buffer auto clear mode */ | ||
407 | #define M66592_SQCLR 0x0100 /* b8: Sequence toggle bit clear */ | ||
408 | #define M66592_SQSET 0x0080 /* b7: Sequence toggle bit set */ | ||
409 | #define M66592_SQMON 0x0040 /* b6: Sequence toggle bit monitor */ | ||
410 | #define M66592_PID 0x0003 /* b1-0: Response PID */ | ||
411 | |||
412 | #define M66592_INVALID_REG 0x7E | ||
413 | |||
414 | |||
415 | #define __iomem | ||
416 | |||
417 | #define get_pipectr_addr(pipenum) (M66592_PIPE1CTR + (pipenum - 1) * 2) | ||
418 | |||
419 | #define M66592_MAX_SAMPLING 10 | ||
420 | |||
421 | #define M66592_MAX_NUM_PIPE 8 | ||
422 | #define M66592_MAX_NUM_BULK 3 | ||
423 | #define M66592_MAX_NUM_ISOC 2 | ||
424 | #define M66592_MAX_NUM_INT 2 | ||
425 | |||
426 | #define M66592_BASE_PIPENUM_BULK 3 | ||
427 | #define M66592_BASE_PIPENUM_ISOC 1 | ||
428 | #define M66592_BASE_PIPENUM_INT 6 | ||
429 | |||
430 | #define M66592_BASE_BUFNUM 6 | ||
431 | #define M66592_MAX_BUFNUM 0x4F | ||
432 | |||
433 | struct m66592_pipe_info { | ||
434 | u16 pipe; | ||
435 | u16 epnum; | ||
436 | u16 maxpacket; | ||
437 | u16 type; | ||
438 | u16 interval; | ||
439 | u16 dir_in; | ||
440 | }; | ||
441 | |||
442 | struct m66592_request { | ||
443 | struct usb_request req; | ||
444 | struct list_head queue; | ||
445 | }; | ||
446 | |||
447 | struct m66592_ep { | ||
448 | struct usb_ep ep; | ||
449 | struct m66592 *m66592; | ||
450 | |||
451 | struct list_head queue; | ||
452 | unsigned busy:1; | ||
453 | unsigned internal_ccpl:1; /* use only control */ | ||
454 | |||
455 | /* this member can able to after m66592_enable */ | ||
456 | unsigned use_dma:1; | ||
457 | u16 pipenum; | ||
458 | u16 type; | ||
459 | const struct usb_endpoint_descriptor *desc; | ||
460 | /* register address */ | ||
461 | unsigned long fifoaddr; | ||
462 | unsigned long fifosel; | ||
463 | unsigned long fifoctr; | ||
464 | unsigned long fifotrn; | ||
465 | unsigned long pipectr; | ||
466 | }; | ||
467 | |||
468 | struct m66592 { | ||
469 | spinlock_t lock; | ||
470 | void __iomem *reg; | ||
471 | |||
472 | struct usb_gadget gadget; | ||
473 | struct usb_gadget_driver *driver; | ||
474 | |||
475 | struct m66592_ep ep[M66592_MAX_NUM_PIPE]; | ||
476 | struct m66592_ep *pipenum2ep[M66592_MAX_NUM_PIPE]; | ||
477 | struct m66592_ep *epaddr2ep[16]; | ||
478 | |||
479 | struct usb_request *ep0_req; /* for internal request */ | ||
480 | u16 *ep0_buf; /* for internal request */ | ||
481 | |||
482 | struct timer_list timer; | ||
483 | |||
484 | u16 old_vbus; | ||
485 | int scount; | ||
486 | |||
487 | int old_dvsq; | ||
488 | |||
489 | /* pipe config */ | ||
490 | int bulk; | ||
491 | int interrupt; | ||
492 | int isochronous; | ||
493 | int num_dma; | ||
494 | int bi_bufnum; /* bulk and isochronous's bufnum */ | ||
495 | }; | ||
496 | |||
497 | #define gadget_to_m66592(_gadget) container_of(_gadget, struct m66592, gadget) | ||
498 | #define m66592_to_gadget(m66592) (&m66592->gadget) | ||
499 | |||
500 | #define is_bulk_pipe(pipenum) \ | ||
501 | ((pipenum >= M66592_BASE_PIPENUM_BULK) && \ | ||
502 | (pipenum < (M66592_BASE_PIPENUM_BULK + M66592_MAX_NUM_BULK))) | ||
503 | #define is_interrupt_pipe(pipenum) \ | ||
504 | ((pipenum >= M66592_BASE_PIPENUM_INT) && \ | ||
505 | (pipenum < (M66592_BASE_PIPENUM_INT + M66592_MAX_NUM_INT))) | ||
506 | #define is_isoc_pipe(pipenum) \ | ||
507 | ((pipenum >= M66592_BASE_PIPENUM_ISOC) && \ | ||
508 | (pipenum < (M66592_BASE_PIPENUM_ISOC + M66592_MAX_NUM_ISOC))) | ||
509 | |||
510 | #define enable_irq_ready(m66592, pipenum) \ | ||
511 | enable_pipe_irq(m66592, pipenum, M66592_BRDYENB) | ||
512 | #define disable_irq_ready(m66592, pipenum) \ | ||
513 | disable_pipe_irq(m66592, pipenum, M66592_BRDYENB) | ||
514 | #define enable_irq_empty(m66592, pipenum) \ | ||
515 | enable_pipe_irq(m66592, pipenum, M66592_BEMPENB) | ||
516 | #define disable_irq_empty(m66592, pipenum) \ | ||
517 | disable_pipe_irq(m66592, pipenum, M66592_BEMPENB) | ||
518 | #define enable_irq_nrdy(m66592, pipenum) \ | ||
519 | enable_pipe_irq(m66592, pipenum, M66592_NRDYENB) | ||
520 | #define disable_irq_nrdy(m66592, pipenum) \ | ||
521 | disable_pipe_irq(m66592, pipenum, M66592_NRDYENB) | ||
522 | |||
523 | /*-------------------------------------------------------------------------*/ | ||
524 | static inline u16 m66592_read(struct m66592 *m66592, unsigned long offset) | ||
525 | { | ||
526 | return inw((unsigned long)m66592->reg + offset); | ||
527 | } | ||
528 | |||
529 | static inline void m66592_read_fifo(struct m66592 *m66592, | ||
530 | unsigned long offset, | ||
531 | void *buf, unsigned long len) | ||
532 | { | ||
533 | unsigned long fifoaddr = (unsigned long)m66592->reg + offset; | ||
534 | |||
535 | len = (len + 1) / 2; | ||
536 | insw(fifoaddr, buf, len); | ||
537 | } | ||
538 | |||
539 | static inline void m66592_write(struct m66592 *m66592, u16 val, | ||
540 | unsigned long offset) | ||
541 | { | ||
542 | outw(val, (unsigned long)m66592->reg + offset); | ||
543 | } | ||
544 | |||
545 | static inline void m66592_write_fifo(struct m66592 *m66592, | ||
546 | unsigned long offset, | ||
547 | void *buf, unsigned long len) | ||
548 | { | ||
549 | unsigned long fifoaddr = (unsigned long)m66592->reg + offset; | ||
550 | unsigned long odd = len & 0x0001; | ||
551 | |||
552 | len = len / 2; | ||
553 | outsw(fifoaddr, buf, len); | ||
554 | if (odd) { | ||
555 | unsigned char *p = buf + len*2; | ||
556 | outb(*p, fifoaddr); | ||
557 | } | ||
558 | } | ||
559 | |||
560 | static inline void m66592_mdfy(struct m66592 *m66592, u16 val, u16 pat, | ||
561 | unsigned long offset) | ||
562 | { | ||
563 | u16 tmp; | ||
564 | tmp = m66592_read(m66592, offset); | ||
565 | tmp = tmp & (~pat); | ||
566 | tmp = tmp | val; | ||
567 | m66592_write(m66592, tmp, offset); | ||
568 | } | ||
569 | |||
570 | #define m66592_bclr(m66592, val, offset) \ | ||
571 | m66592_mdfy(m66592, 0, val, offset) | ||
572 | #define m66592_bset(m66592, val, offset) \ | ||
573 | m66592_mdfy(m66592, val, 0, offset) | ||
574 | |||
575 | #endif /* ifndef __M66592_UDC_H__ */ | ||
576 | |||
577 | |||
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 00fda334dc72..c3d364ecd4f8 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -450,100 +450,6 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req) | |||
450 | 450 | ||
451 | /*-------------------------------------------------------------------------*/ | 451 | /*-------------------------------------------------------------------------*/ |
452 | 452 | ||
453 | /* | ||
454 | * dma-coherent memory allocation (for dma-capable endpoints) | ||
455 | * | ||
456 | * NOTE: the dma_*_coherent() API calls suck. Most implementations are | ||
457 | * (a) page-oriented, so small buffers lose big; and (b) asymmetric with | ||
458 | * respect to calls with irqs disabled: alloc is safe, free is not. | ||
459 | * We currently work around (b), but not (a). | ||
460 | */ | ||
461 | |||
462 | static void * | ||
463 | net2280_alloc_buffer ( | ||
464 | struct usb_ep *_ep, | ||
465 | unsigned bytes, | ||
466 | dma_addr_t *dma, | ||
467 | gfp_t gfp_flags | ||
468 | ) | ||
469 | { | ||
470 | void *retval; | ||
471 | struct net2280_ep *ep; | ||
472 | |||
473 | ep = container_of (_ep, struct net2280_ep, ep); | ||
474 | if (!_ep) | ||
475 | return NULL; | ||
476 | *dma = DMA_ADDR_INVALID; | ||
477 | |||
478 | if (ep->dma) | ||
479 | retval = dma_alloc_coherent(&ep->dev->pdev->dev, | ||
480 | bytes, dma, gfp_flags); | ||
481 | else | ||
482 | retval = kmalloc(bytes, gfp_flags); | ||
483 | return retval; | ||
484 | } | ||
485 | |||
486 | static DEFINE_SPINLOCK(buflock); | ||
487 | static LIST_HEAD(buffers); | ||
488 | |||
489 | struct free_record { | ||
490 | struct list_head list; | ||
491 | struct device *dev; | ||
492 | unsigned bytes; | ||
493 | dma_addr_t dma; | ||
494 | }; | ||
495 | |||
496 | static void do_free(unsigned long ignored) | ||
497 | { | ||
498 | spin_lock_irq(&buflock); | ||
499 | while (!list_empty(&buffers)) { | ||
500 | struct free_record *buf; | ||
501 | |||
502 | buf = list_entry(buffers.next, struct free_record, list); | ||
503 | list_del(&buf->list); | ||
504 | spin_unlock_irq(&buflock); | ||
505 | |||
506 | dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma); | ||
507 | |||
508 | spin_lock_irq(&buflock); | ||
509 | } | ||
510 | spin_unlock_irq(&buflock); | ||
511 | } | ||
512 | |||
513 | static DECLARE_TASKLET(deferred_free, do_free, 0); | ||
514 | |||
515 | static void | ||
516 | net2280_free_buffer ( | ||
517 | struct usb_ep *_ep, | ||
518 | void *address, | ||
519 | dma_addr_t dma, | ||
520 | unsigned bytes | ||
521 | ) { | ||
522 | /* free memory into the right allocator */ | ||
523 | if (dma != DMA_ADDR_INVALID) { | ||
524 | struct net2280_ep *ep; | ||
525 | struct free_record *buf = address; | ||
526 | unsigned long flags; | ||
527 | |||
528 | ep = container_of(_ep, struct net2280_ep, ep); | ||
529 | if (!_ep) | ||
530 | return; | ||
531 | |||
532 | ep = container_of (_ep, struct net2280_ep, ep); | ||
533 | buf->dev = &ep->dev->pdev->dev; | ||
534 | buf->bytes = bytes; | ||
535 | buf->dma = dma; | ||
536 | |||
537 | spin_lock_irqsave(&buflock, flags); | ||
538 | list_add_tail(&buf->list, &buffers); | ||
539 | tasklet_schedule(&deferred_free); | ||
540 | spin_unlock_irqrestore(&buflock, flags); | ||
541 | } else | ||
542 | kfree (address); | ||
543 | } | ||
544 | |||
545 | /*-------------------------------------------------------------------------*/ | ||
546 | |||
547 | /* load a packet into the fifo we use for usb IN transfers. | 453 | /* load a packet into the fifo we use for usb IN transfers. |
548 | * works for all endpoints. | 454 | * works for all endpoints. |
549 | * | 455 | * |
@@ -1392,9 +1298,6 @@ static const struct usb_ep_ops net2280_ep_ops = { | |||
1392 | .alloc_request = net2280_alloc_request, | 1298 | .alloc_request = net2280_alloc_request, |
1393 | .free_request = net2280_free_request, | 1299 | .free_request = net2280_free_request, |
1394 | 1300 | ||
1395 | .alloc_buffer = net2280_alloc_buffer, | ||
1396 | .free_buffer = net2280_free_buffer, | ||
1397 | |||
1398 | .queue = net2280_queue, | 1301 | .queue = net2280_queue, |
1399 | .dequeue = net2280_dequeue, | 1302 | .dequeue = net2280_dequeue, |
1400 | 1303 | ||
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index c4975a6cf777..9b0f0925dddf 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
@@ -296,111 +296,6 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req) | |||
296 | 296 | ||
297 | /*-------------------------------------------------------------------------*/ | 297 | /*-------------------------------------------------------------------------*/ |
298 | 298 | ||
299 | /* | ||
300 | * dma-coherent memory allocation (for dma-capable endpoints) | ||
301 | * | ||
302 | * NOTE: the dma_*_coherent() API calls suck. Most implementations are | ||
303 | * (a) page-oriented, so small buffers lose big; and (b) asymmetric with | ||
304 | * respect to calls with irqs disabled: alloc is safe, free is not. | ||
305 | * We currently work around (b), but not (a). | ||
306 | */ | ||
307 | |||
308 | static void * | ||
309 | omap_alloc_buffer( | ||
310 | struct usb_ep *_ep, | ||
311 | unsigned bytes, | ||
312 | dma_addr_t *dma, | ||
313 | gfp_t gfp_flags | ||
314 | ) | ||
315 | { | ||
316 | void *retval; | ||
317 | struct omap_ep *ep; | ||
318 | |||
319 | if (!_ep) | ||
320 | return NULL; | ||
321 | |||
322 | ep = container_of(_ep, struct omap_ep, ep); | ||
323 | if (use_dma && ep->has_dma) { | ||
324 | static int warned; | ||
325 | if (!warned && bytes < PAGE_SIZE) { | ||
326 | dev_warn(ep->udc->gadget.dev.parent, | ||
327 | "using dma_alloc_coherent for " | ||
328 | "small allocations wastes memory\n"); | ||
329 | warned++; | ||
330 | } | ||
331 | return dma_alloc_coherent(ep->udc->gadget.dev.parent, | ||
332 | bytes, dma, gfp_flags); | ||
333 | } | ||
334 | |||
335 | retval = kmalloc(bytes, gfp_flags); | ||
336 | if (retval) | ||
337 | *dma = virt_to_phys(retval); | ||
338 | return retval; | ||
339 | } | ||
340 | |||
341 | static DEFINE_SPINLOCK(buflock); | ||
342 | static LIST_HEAD(buffers); | ||
343 | |||
344 | struct free_record { | ||
345 | struct list_head list; | ||
346 | struct device *dev; | ||
347 | unsigned bytes; | ||
348 | dma_addr_t dma; | ||
349 | }; | ||
350 | |||
351 | static void do_free(unsigned long ignored) | ||
352 | { | ||
353 | spin_lock_irq(&buflock); | ||
354 | while (!list_empty(&buffers)) { | ||
355 | struct free_record *buf; | ||
356 | |||
357 | buf = list_entry(buffers.next, struct free_record, list); | ||
358 | list_del(&buf->list); | ||
359 | spin_unlock_irq(&buflock); | ||
360 | |||
361 | dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma); | ||
362 | |||
363 | spin_lock_irq(&buflock); | ||
364 | } | ||
365 | spin_unlock_irq(&buflock); | ||
366 | } | ||
367 | |||
368 | static DECLARE_TASKLET(deferred_free, do_free, 0); | ||
369 | |||
370 | static void omap_free_buffer( | ||
371 | struct usb_ep *_ep, | ||
372 | void *buf, | ||
373 | dma_addr_t dma, | ||
374 | unsigned bytes | ||
375 | ) | ||
376 | { | ||
377 | if (!_ep) { | ||
378 | WARN_ON(1); | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | /* free memory into the right allocator */ | ||
383 | if (dma != DMA_ADDR_INVALID) { | ||
384 | struct omap_ep *ep; | ||
385 | struct free_record *rec = buf; | ||
386 | unsigned long flags; | ||
387 | |||
388 | ep = container_of(_ep, struct omap_ep, ep); | ||
389 | |||
390 | rec->dev = ep->udc->gadget.dev.parent; | ||
391 | rec->bytes = bytes; | ||
392 | rec->dma = dma; | ||
393 | |||
394 | spin_lock_irqsave(&buflock, flags); | ||
395 | list_add_tail(&rec->list, &buffers); | ||
396 | tasklet_schedule(&deferred_free); | ||
397 | spin_unlock_irqrestore(&buflock, flags); | ||
398 | } else | ||
399 | kfree(buf); | ||
400 | } | ||
401 | |||
402 | /*-------------------------------------------------------------------------*/ | ||
403 | |||
404 | static void | 299 | static void |
405 | done(struct omap_ep *ep, struct omap_req *req, int status) | 300 | done(struct omap_ep *ep, struct omap_req *req, int status) |
406 | { | 301 | { |
@@ -1271,9 +1166,6 @@ static struct usb_ep_ops omap_ep_ops = { | |||
1271 | .alloc_request = omap_alloc_request, | 1166 | .alloc_request = omap_alloc_request, |
1272 | .free_request = omap_free_request, | 1167 | .free_request = omap_free_request, |
1273 | 1168 | ||
1274 | .alloc_buffer = omap_alloc_buffer, | ||
1275 | .free_buffer = omap_free_buffer, | ||
1276 | |||
1277 | .queue = omap_ep_queue, | 1169 | .queue = omap_ep_queue, |
1278 | .dequeue = omap_ep_dequeue, | 1170 | .dequeue = omap_ep_dequeue, |
1279 | 1171 | ||
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 84392e835d5f..63b9521c1322 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c | |||
@@ -24,9 +24,9 @@ | |||
24 | * | 24 | * |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #undef DEBUG | ||
28 | // #define VERBOSE DBG_VERBOSE | 27 | // #define VERBOSE DBG_VERBOSE |
29 | 28 | ||
29 | #include <linux/device.h> | ||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
32 | #include <linux/ioport.h> | 32 | #include <linux/ioport.h> |
@@ -46,19 +46,17 @@ | |||
46 | 46 | ||
47 | #include <asm/byteorder.h> | 47 | #include <asm/byteorder.h> |
48 | #include <asm/dma.h> | 48 | #include <asm/dma.h> |
49 | #include <asm/gpio.h> | ||
49 | #include <asm/io.h> | 50 | #include <asm/io.h> |
50 | #include <asm/system.h> | 51 | #include <asm/system.h> |
51 | #include <asm/mach-types.h> | 52 | #include <asm/mach-types.h> |
52 | #include <asm/unaligned.h> | 53 | #include <asm/unaligned.h> |
53 | #include <asm/hardware.h> | 54 | #include <asm/hardware.h> |
54 | #ifdef CONFIG_ARCH_PXA | ||
55 | #include <asm/arch/pxa-regs.h> | ||
56 | #endif | ||
57 | 55 | ||
58 | #include <linux/usb/ch9.h> | 56 | #include <linux/usb/ch9.h> |
59 | #include <linux/usb_gadget.h> | 57 | #include <linux/usb_gadget.h> |
60 | 58 | ||
61 | #include <asm/arch/udc.h> | 59 | #include <asm/mach/udc_pxa2xx.h> |
62 | 60 | ||
63 | 61 | ||
64 | /* | 62 | /* |
@@ -76,9 +74,17 @@ | |||
76 | * it constrains the sorts of USB configuration change events that work. | 74 | * it constrains the sorts of USB configuration change events that work. |
77 | * The errata for these chips are misleading; some "fixed" bugs from | 75 | * The errata for these chips are misleading; some "fixed" bugs from |
78 | * pxa250 a0/a1 b0/b1/b2 sure act like they're still there. | 76 | * pxa250 a0/a1 b0/b1/b2 sure act like they're still there. |
77 | * | ||
78 | * Note that the UDC hardware supports DMA (except on IXP) but that's | ||
79 | * not used here. IN-DMA (to host) is simple enough, when the data is | ||
80 | * suitably aligned (16 bytes) ... the network stack doesn't do that, | ||
81 | * other software can. OUT-DMA is buggy in most chip versions, as well | ||
82 | * as poorly designed (data toggle not automatic). So this driver won't | ||
83 | * bother using DMA. (Mostly-working IN-DMA support was available in | ||
84 | * kernels before 2.6.23, but was never enabled or well tested.) | ||
79 | */ | 85 | */ |
80 | 86 | ||
81 | #define DRIVER_VERSION "4-May-2005" | 87 | #define DRIVER_VERSION "30-June-2007" |
82 | #define DRIVER_DESC "PXA 25x USB Device Controller driver" | 88 | #define DRIVER_DESC "PXA 25x USB Device Controller driver" |
83 | 89 | ||
84 | 90 | ||
@@ -87,12 +93,9 @@ static const char driver_name [] = "pxa2xx_udc"; | |||
87 | static const char ep0name [] = "ep0"; | 93 | static const char ep0name [] = "ep0"; |
88 | 94 | ||
89 | 95 | ||
90 | // #define USE_DMA | ||
91 | // #define USE_OUT_DMA | ||
92 | // #define DISABLE_TEST_MODE | 96 | // #define DISABLE_TEST_MODE |
93 | 97 | ||
94 | #ifdef CONFIG_ARCH_IXP4XX | 98 | #ifdef CONFIG_ARCH_IXP4XX |
95 | #undef USE_DMA | ||
96 | 99 | ||
97 | /* cpu-specific register addresses are compiled in to this code */ | 100 | /* cpu-specific register addresses are compiled in to this code */ |
98 | #ifdef CONFIG_ARCH_PXA | 101 | #ifdef CONFIG_ARCH_PXA |
@@ -104,25 +107,6 @@ static const char ep0name [] = "ep0"; | |||
104 | #include "pxa2xx_udc.h" | 107 | #include "pxa2xx_udc.h" |
105 | 108 | ||
106 | 109 | ||
107 | #ifdef USE_DMA | ||
108 | static int use_dma = 1; | ||
109 | module_param(use_dma, bool, 0); | ||
110 | MODULE_PARM_DESC (use_dma, "true to use dma"); | ||
111 | |||
112 | static void dma_nodesc_handler (int dmach, void *_ep); | ||
113 | static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req); | ||
114 | |||
115 | #ifdef USE_OUT_DMA | ||
116 | #define DMASTR " (dma support)" | ||
117 | #else | ||
118 | #define DMASTR " (dma in)" | ||
119 | #endif | ||
120 | |||
121 | #else /* !USE_DMA */ | ||
122 | #define DMASTR " (pio only)" | ||
123 | #undef USE_OUT_DMA | ||
124 | #endif | ||
125 | |||
126 | #ifdef CONFIG_USB_PXA2XX_SMALL | 110 | #ifdef CONFIG_USB_PXA2XX_SMALL |
127 | #define SIZE_STR " (small)" | 111 | #define SIZE_STR " (small)" |
128 | #else | 112 | #else |
@@ -155,7 +139,7 @@ static int is_vbus_present(void) | |||
155 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | 139 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; |
156 | 140 | ||
157 | if (mach->gpio_vbus) | 141 | if (mach->gpio_vbus) |
158 | return udc_gpio_get(mach->gpio_vbus); | 142 | return gpio_get_value(mach->gpio_vbus); |
159 | if (mach->udc_is_connected) | 143 | if (mach->udc_is_connected) |
160 | return mach->udc_is_connected(); | 144 | return mach->udc_is_connected(); |
161 | return 1; | 145 | return 1; |
@@ -167,7 +151,7 @@ static void pullup_off(void) | |||
167 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | 151 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; |
168 | 152 | ||
169 | if (mach->gpio_pullup) | 153 | if (mach->gpio_pullup) |
170 | udc_gpio_set(mach->gpio_pullup, 0); | 154 | gpio_set_value(mach->gpio_pullup, 0); |
171 | else if (mach->udc_command) | 155 | else if (mach->udc_command) |
172 | mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); | 156 | mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); |
173 | } | 157 | } |
@@ -177,7 +161,7 @@ static void pullup_on(void) | |||
177 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; | 161 | struct pxa2xx_udc_mach_info *mach = the_controller->mach; |
178 | 162 | ||
179 | if (mach->gpio_pullup) | 163 | if (mach->gpio_pullup) |
180 | udc_gpio_set(mach->gpio_pullup, 1); | 164 | gpio_set_value(mach->gpio_pullup, 1); |
181 | else if (mach->udc_command) | 165 | else if (mach->udc_command) |
182 | mach->udc_command(PXA2XX_UDC_CMD_CONNECT); | 166 | mach->udc_command(PXA2XX_UDC_CMD_CONNECT); |
183 | } | 167 | } |
@@ -281,9 +265,8 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep, | |||
281 | } | 265 | } |
282 | 266 | ||
283 | ep->desc = desc; | 267 | ep->desc = desc; |
284 | ep->dma = -1; | ||
285 | ep->stopped = 0; | 268 | ep->stopped = 0; |
286 | ep->pio_irqs = ep->dma_irqs = 0; | 269 | ep->pio_irqs = 0; |
287 | ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize); | 270 | ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize); |
288 | 271 | ||
289 | /* flush fifo (mostly for OUT buffers) */ | 272 | /* flush fifo (mostly for OUT buffers) */ |
@@ -291,30 +274,6 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep, | |||
291 | 274 | ||
292 | /* ... reset halt state too, if we could ... */ | 275 | /* ... reset halt state too, if we could ... */ |
293 | 276 | ||
294 | #ifdef USE_DMA | ||
295 | /* for (some) bulk and ISO endpoints, try to get a DMA channel and | ||
296 | * bind it to the endpoint. otherwise use PIO. | ||
297 | */ | ||
298 | switch (ep->bmAttributes) { | ||
299 | case USB_ENDPOINT_XFER_ISOC: | ||
300 | if (le16_to_cpu(desc->wMaxPacketSize) % 32) | ||
301 | break; | ||
302 | // fall through | ||
303 | case USB_ENDPOINT_XFER_BULK: | ||
304 | if (!use_dma || !ep->reg_drcmr) | ||
305 | break; | ||
306 | ep->dma = pxa_request_dma ((char *)_ep->name, | ||
307 | (le16_to_cpu (desc->wMaxPacketSize) > 64) | ||
308 | ? DMA_PRIO_MEDIUM /* some iso */ | ||
309 | : DMA_PRIO_LOW, | ||
310 | dma_nodesc_handler, ep); | ||
311 | if (ep->dma >= 0) { | ||
312 | *ep->reg_drcmr = DRCMR_MAPVLD | ep->dma; | ||
313 | DMSG("%s using dma%d\n", _ep->name, ep->dma); | ||
314 | } | ||
315 | } | ||
316 | #endif | ||
317 | |||
318 | DBG(DBG_VERBOSE, "enabled %s\n", _ep->name); | 277 | DBG(DBG_VERBOSE, "enabled %s\n", _ep->name); |
319 | return 0; | 278 | return 0; |
320 | } | 279 | } |
@@ -334,14 +293,6 @@ static int pxa2xx_ep_disable (struct usb_ep *_ep) | |||
334 | 293 | ||
335 | nuke (ep, -ESHUTDOWN); | 294 | nuke (ep, -ESHUTDOWN); |
336 | 295 | ||
337 | #ifdef USE_DMA | ||
338 | if (ep->dma >= 0) { | ||
339 | *ep->reg_drcmr = 0; | ||
340 | pxa_free_dma (ep->dma); | ||
341 | ep->dma = -1; | ||
342 | } | ||
343 | #endif | ||
344 | |||
345 | /* flush fifo (mostly for IN buffers) */ | 296 | /* flush fifo (mostly for IN buffers) */ |
346 | pxa2xx_ep_fifo_flush (_ep); | 297 | pxa2xx_ep_fifo_flush (_ep); |
347 | 298 | ||
@@ -390,35 +341,6 @@ pxa2xx_ep_free_request (struct usb_ep *_ep, struct usb_request *_req) | |||
390 | kfree(req); | 341 | kfree(req); |
391 | } | 342 | } |
392 | 343 | ||
393 | |||
394 | /* PXA cache needs flushing with DMA I/O (it's dma-incoherent), but there's | ||
395 | * no device-affinity and the heap works perfectly well for i/o buffers. | ||
396 | * It wastes much less memory than dma_alloc_coherent() would, and even | ||
397 | * prevents cacheline (32 bytes wide) sharing problems. | ||
398 | */ | ||
399 | static void * | ||
400 | pxa2xx_ep_alloc_buffer(struct usb_ep *_ep, unsigned bytes, | ||
401 | dma_addr_t *dma, gfp_t gfp_flags) | ||
402 | { | ||
403 | char *retval; | ||
404 | |||
405 | retval = kmalloc (bytes, gfp_flags & ~(__GFP_DMA|__GFP_HIGHMEM)); | ||
406 | if (retval) | ||
407 | #ifdef USE_DMA | ||
408 | *dma = virt_to_bus (retval); | ||
409 | #else | ||
410 | *dma = (dma_addr_t)~0; | ||
411 | #endif | ||
412 | return retval; | ||
413 | } | ||
414 | |||
415 | static void | ||
416 | pxa2xx_ep_free_buffer(struct usb_ep *_ep, void *buf, dma_addr_t dma, | ||
417 | unsigned bytes) | ||
418 | { | ||
419 | kfree (buf); | ||
420 | } | ||
421 | |||
422 | /*-------------------------------------------------------------------------*/ | 344 | /*-------------------------------------------------------------------------*/ |
423 | 345 | ||
424 | /* | 346 | /* |
@@ -518,18 +440,8 @@ write_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) | |||
518 | /* requests complete when all IN data is in the FIFO */ | 440 | /* requests complete when all IN data is in the FIFO */ |
519 | if (is_last) { | 441 | if (is_last) { |
520 | done (ep, req, 0); | 442 | done (ep, req, 0); |
521 | if (list_empty(&ep->queue) || unlikely(ep->dma >= 0)) { | 443 | if (list_empty(&ep->queue)) |
522 | pio_irq_disable (ep->bEndpointAddress); | 444 | pio_irq_disable (ep->bEndpointAddress); |
523 | #ifdef USE_DMA | ||
524 | /* unaligned data and zlps couldn't use dma */ | ||
525 | if (unlikely(!list_empty(&ep->queue))) { | ||
526 | req = list_entry(ep->queue.next, | ||
527 | struct pxa2xx_request, queue); | ||
528 | kick_dma(ep,req); | ||
529 | return 0; | ||
530 | } | ||
531 | #endif | ||
532 | } | ||
533 | return 1; | 445 | return 1; |
534 | } | 446 | } |
535 | 447 | ||
@@ -728,182 +640,6 @@ read_ep0_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req) | |||
728 | return 0; | 640 | return 0; |
729 | } | 641 | } |
730 | 642 | ||
731 | #ifdef USE_DMA | ||
732 | |||
733 | #define MAX_IN_DMA ((DCMD_LENGTH + 1) - BULK_FIFO_SIZE) | ||
734 | |||
735 | static void | ||
736 | start_dma_nodesc(struct pxa2xx_ep *ep, struct pxa2xx_request *req, int is_in) | ||
737 | { | ||
738 | u32 dcmd = req->req.length; | ||
739 | u32 buf = req->req.dma; | ||
740 | u32 fifo = io_v2p ((u32)ep->reg_uddr); | ||
741 | |||
742 | /* caller guarantees there's a packet or more remaining | ||
743 | * - IN may end with a short packet (TSP set separately), | ||
744 | * - OUT is always full length | ||
745 | */ | ||
746 | buf += req->req.actual; | ||
747 | dcmd -= req->req.actual; | ||
748 | ep->dma_fixup = 0; | ||
749 | |||
750 | /* no-descriptor mode can be simple for bulk-in, iso-in, iso-out */ | ||
751 | DCSR(ep->dma) = DCSR_NODESC; | ||
752 | if (is_in) { | ||
753 | DSADR(ep->dma) = buf; | ||
754 | DTADR(ep->dma) = fifo; | ||
755 | if (dcmd > MAX_IN_DMA) | ||
756 | dcmd = MAX_IN_DMA; | ||
757 | else | ||
758 | ep->dma_fixup = (dcmd % ep->ep.maxpacket) != 0; | ||
759 | dcmd |= DCMD_BURST32 | DCMD_WIDTH1 | ||
760 | | DCMD_FLOWTRG | DCMD_INCSRCADDR; | ||
761 | } else { | ||
762 | #ifdef USE_OUT_DMA | ||
763 | DSADR(ep->dma) = fifo; | ||
764 | DTADR(ep->dma) = buf; | ||
765 | if (ep->bmAttributes != USB_ENDPOINT_XFER_ISOC) | ||
766 | dcmd = ep->ep.maxpacket; | ||
767 | dcmd |= DCMD_BURST32 | DCMD_WIDTH1 | ||
768 | | DCMD_FLOWSRC | DCMD_INCTRGADDR; | ||
769 | #endif | ||
770 | } | ||
771 | DCMD(ep->dma) = dcmd; | ||
772 | DCSR(ep->dma) = DCSR_RUN | DCSR_NODESC | ||
773 | | (unlikely(is_in) | ||
774 | ? DCSR_STOPIRQEN /* use dma_nodesc_handler() */ | ||
775 | : 0); /* use handle_ep() */ | ||
776 | } | ||
777 | |||
778 | static void kick_dma(struct pxa2xx_ep *ep, struct pxa2xx_request *req) | ||
779 | { | ||
780 | int is_in = ep->bEndpointAddress & USB_DIR_IN; | ||
781 | |||
782 | if (is_in) { | ||
783 | /* unaligned tx buffers and zlps only work with PIO */ | ||
784 | if ((req->req.dma & 0x0f) != 0 | ||
785 | || unlikely((req->req.length - req->req.actual) | ||
786 | == 0)) { | ||
787 | pio_irq_enable(ep->bEndpointAddress); | ||
788 | if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0) | ||
789 | (void) write_fifo(ep, req); | ||
790 | } else { | ||
791 | start_dma_nodesc(ep, req, USB_DIR_IN); | ||
792 | } | ||
793 | } else { | ||
794 | if ((req->req.length - req->req.actual) < ep->ep.maxpacket) { | ||
795 | DMSG("%s short dma read...\n", ep->ep.name); | ||
796 | /* we're always set up for pio out */ | ||
797 | read_fifo (ep, req); | ||
798 | } else { | ||
799 | *ep->reg_udccs = UDCCS_BO_DME | ||
800 | | (*ep->reg_udccs & UDCCS_BO_FST); | ||
801 | start_dma_nodesc(ep, req, USB_DIR_OUT); | ||
802 | } | ||
803 | } | ||
804 | } | ||
805 | |||
806 | static void cancel_dma(struct pxa2xx_ep *ep) | ||
807 | { | ||
808 | struct pxa2xx_request *req; | ||
809 | u32 tmp; | ||
810 | |||
811 | if (DCSR(ep->dma) == 0 || list_empty(&ep->queue)) | ||
812 | return; | ||
813 | |||
814 | DCSR(ep->dma) = 0; | ||
815 | while ((DCSR(ep->dma) & DCSR_STOPSTATE) == 0) | ||
816 | cpu_relax(); | ||
817 | |||
818 | req = list_entry(ep->queue.next, struct pxa2xx_request, queue); | ||
819 | tmp = DCMD(ep->dma) & DCMD_LENGTH; | ||
820 | req->req.actual = req->req.length - (tmp & DCMD_LENGTH); | ||
821 | |||
822 | /* the last tx packet may be incomplete, so flush the fifo. | ||
823 | * FIXME correct req.actual if we can | ||
824 | */ | ||
825 | if (ep->bEndpointAddress & USB_DIR_IN) | ||
826 | *ep->reg_udccs = UDCCS_BI_FTF; | ||
827 | } | ||
828 | |||
829 | /* dma channel stopped ... normal tx end (IN), or on error (IN/OUT) */ | ||
830 | static void dma_nodesc_handler(int dmach, void *_ep) | ||
831 | { | ||
832 | struct pxa2xx_ep *ep = _ep; | ||
833 | struct pxa2xx_request *req; | ||
834 | u32 tmp, completed; | ||
835 | |||
836 | local_irq_disable(); | ||
837 | |||
838 | req = list_entry(ep->queue.next, struct pxa2xx_request, queue); | ||
839 | |||
840 | ep->dma_irqs++; | ||
841 | ep->dev->stats.irqs++; | ||
842 | HEX_DISPLAY(ep->dev->stats.irqs); | ||
843 | |||
844 | /* ack/clear */ | ||
845 | tmp = DCSR(ep->dma); | ||
846 | DCSR(ep->dma) = tmp; | ||
847 | if ((tmp & DCSR_STOPSTATE) == 0 | ||
848 | || (DDADR(ep->dma) & DDADR_STOP) != 0) { | ||
849 | DBG(DBG_VERBOSE, "%s, dcsr %08x ddadr %08x\n", | ||
850 | ep->ep.name, DCSR(ep->dma), DDADR(ep->dma)); | ||
851 | goto done; | ||
852 | } | ||
853 | DCSR(ep->dma) = 0; /* clear DCSR_STOPSTATE */ | ||
854 | |||
855 | /* update transfer status */ | ||
856 | completed = tmp & DCSR_BUSERR; | ||
857 | if (ep->bEndpointAddress & USB_DIR_IN) | ||
858 | tmp = DSADR(ep->dma); | ||
859 | else | ||
860 | tmp = DTADR(ep->dma); | ||
861 | req->req.actual = tmp - req->req.dma; | ||
862 | |||
863 | /* FIXME seems we sometimes see partial transfers... */ | ||
864 | |||
865 | if (unlikely(completed != 0)) | ||
866 | req->req.status = -EIO; | ||
867 | else if (req->req.actual) { | ||
868 | /* these registers have zeroes in low bits; they miscount | ||
869 | * some (end-of-transfer) short packets: tx 14 as tx 12 | ||
870 | */ | ||
871 | if (ep->dma_fixup) | ||
872 | req->req.actual = min(req->req.actual + 3, | ||
873 | req->req.length); | ||
874 | |||
875 | tmp = (req->req.length - req->req.actual); | ||
876 | completed = (tmp == 0); | ||
877 | if (completed && (ep->bEndpointAddress & USB_DIR_IN)) { | ||
878 | |||
879 | /* maybe validate final short packet ... */ | ||
880 | if ((req->req.actual % ep->ep.maxpacket) != 0) | ||
881 | *ep->reg_udccs = UDCCS_BI_TSP/*|UDCCS_BI_TPC*/; | ||
882 | |||
883 | /* ... or zlp, using pio fallback */ | ||
884 | else if (ep->bmAttributes == USB_ENDPOINT_XFER_BULK | ||
885 | && req->req.zero) { | ||
886 | DMSG("%s zlp terminate ...\n", ep->ep.name); | ||
887 | completed = 0; | ||
888 | } | ||
889 | } | ||
890 | } | ||
891 | |||
892 | if (likely(completed)) { | ||
893 | done(ep, req, 0); | ||
894 | |||
895 | /* maybe re-activate after completion */ | ||
896 | if (ep->stopped || list_empty(&ep->queue)) | ||
897 | goto done; | ||
898 | req = list_entry(ep->queue.next, struct pxa2xx_request, queue); | ||
899 | } | ||
900 | kick_dma(ep, req); | ||
901 | done: | ||
902 | local_irq_enable(); | ||
903 | } | ||
904 | |||
905 | #endif | ||
906 | |||
907 | /*-------------------------------------------------------------------------*/ | 643 | /*-------------------------------------------------------------------------*/ |
908 | 644 | ||
909 | static int | 645 | static int |
@@ -942,19 +678,8 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) | |||
942 | (ep->desc->wMaxPacketSize))) | 678 | (ep->desc->wMaxPacketSize))) |
943 | return -EMSGSIZE; | 679 | return -EMSGSIZE; |
944 | 680 | ||
945 | #ifdef USE_DMA | ||
946 | // FIXME caller may already have done the dma mapping | ||
947 | if (ep->dma >= 0) { | ||
948 | _req->dma = dma_map_single(dev->dev, | ||
949 | _req->buf, _req->length, | ||
950 | ((ep->bEndpointAddress & USB_DIR_IN) != 0) | ||
951 | ? DMA_TO_DEVICE | ||
952 | : DMA_FROM_DEVICE); | ||
953 | } | ||
954 | #endif | ||
955 | |||
956 | DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n", | 681 | DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n", |
957 | _ep->name, _req, _req->length, _req->buf); | 682 | _ep->name, _req, _req->length, _req->buf); |
958 | 683 | ||
959 | local_irq_save(flags); | 684 | local_irq_save(flags); |
960 | 685 | ||
@@ -1002,11 +727,6 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) | |||
1002 | local_irq_restore (flags); | 727 | local_irq_restore (flags); |
1003 | return -EL2HLT; | 728 | return -EL2HLT; |
1004 | } | 729 | } |
1005 | #ifdef USE_DMA | ||
1006 | /* either start dma or prime pio pump */ | ||
1007 | } else if (ep->dma >= 0) { | ||
1008 | kick_dma(ep, req); | ||
1009 | #endif | ||
1010 | /* can the FIFO can satisfy the request immediately? */ | 730 | /* can the FIFO can satisfy the request immediately? */ |
1011 | } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) { | 731 | } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0) { |
1012 | if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0 | 732 | if ((*ep->reg_udccs & UDCCS_BI_TFS) != 0 |
@@ -1017,7 +737,7 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) | |||
1017 | req = NULL; | 737 | req = NULL; |
1018 | } | 738 | } |
1019 | 739 | ||
1020 | if (likely (req && ep->desc) && ep->dma < 0) | 740 | if (likely (req && ep->desc)) |
1021 | pio_irq_enable(ep->bEndpointAddress); | 741 | pio_irq_enable(ep->bEndpointAddress); |
1022 | } | 742 | } |
1023 | 743 | ||
@@ -1038,10 +758,6 @@ static void nuke(struct pxa2xx_ep *ep, int status) | |||
1038 | struct pxa2xx_request *req; | 758 | struct pxa2xx_request *req; |
1039 | 759 | ||
1040 | /* called with irqs blocked */ | 760 | /* called with irqs blocked */ |
1041 | #ifdef USE_DMA | ||
1042 | if (ep->dma >= 0 && !ep->stopped) | ||
1043 | cancel_dma(ep); | ||
1044 | #endif | ||
1045 | while (!list_empty(&ep->queue)) { | 761 | while (!list_empty(&ep->queue)) { |
1046 | req = list_entry(ep->queue.next, | 762 | req = list_entry(ep->queue.next, |
1047 | struct pxa2xx_request, | 763 | struct pxa2xx_request, |
@@ -1076,19 +792,7 @@ static int pxa2xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) | |||
1076 | return -EINVAL; | 792 | return -EINVAL; |
1077 | } | 793 | } |
1078 | 794 | ||
1079 | #ifdef USE_DMA | 795 | done(ep, req, -ECONNRESET); |
1080 | if (ep->dma >= 0 && ep->queue.next == &req->queue && !ep->stopped) { | ||
1081 | cancel_dma(ep); | ||
1082 | done(ep, req, -ECONNRESET); | ||
1083 | /* restart i/o */ | ||
1084 | if (!list_empty(&ep->queue)) { | ||
1085 | req = list_entry(ep->queue.next, | ||
1086 | struct pxa2xx_request, queue); | ||
1087 | kick_dma(ep, req); | ||
1088 | } | ||
1089 | } else | ||
1090 | #endif | ||
1091 | done(ep, req, -ECONNRESET); | ||
1092 | 796 | ||
1093 | local_irq_restore(flags); | 797 | local_irq_restore(flags); |
1094 | return 0; | 798 | return 0; |
@@ -1203,9 +907,6 @@ static struct usb_ep_ops pxa2xx_ep_ops = { | |||
1203 | .alloc_request = pxa2xx_ep_alloc_request, | 907 | .alloc_request = pxa2xx_ep_alloc_request, |
1204 | .free_request = pxa2xx_ep_free_request, | 908 | .free_request = pxa2xx_ep_free_request, |
1205 | 909 | ||
1206 | .alloc_buffer = pxa2xx_ep_alloc_buffer, | ||
1207 | .free_buffer = pxa2xx_ep_free_buffer, | ||
1208 | |||
1209 | .queue = pxa2xx_ep_queue, | 910 | .queue = pxa2xx_ep_queue, |
1210 | .dequeue = pxa2xx_ep_dequeue, | 911 | .dequeue = pxa2xx_ep_dequeue, |
1211 | 912 | ||
@@ -1325,7 +1026,7 @@ udc_proc_read(char *page, char **start, off_t off, int count, | |||
1325 | /* basic device status */ | 1026 | /* basic device status */ |
1326 | t = scnprintf(next, size, DRIVER_DESC "\n" | 1027 | t = scnprintf(next, size, DRIVER_DESC "\n" |
1327 | "%s version: %s\nGadget driver: %s\nHost %s\n\n", | 1028 | "%s version: %s\nGadget driver: %s\nHost %s\n\n", |
1328 | driver_name, DRIVER_VERSION SIZE_STR DMASTR, | 1029 | driver_name, DRIVER_VERSION SIZE_STR "(pio)", |
1329 | dev->driver ? dev->driver->driver.name : "(none)", | 1030 | dev->driver ? dev->driver->driver.name : "(none)", |
1330 | is_vbus_present() ? "full speed" : "disconnected"); | 1031 | is_vbus_present() ? "full speed" : "disconnected"); |
1331 | size -= t; | 1032 | size -= t; |
@@ -1390,7 +1091,6 @@ udc_proc_read(char *page, char **start, off_t off, int count, | |||
1390 | for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) { | 1091 | for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) { |
1391 | struct pxa2xx_ep *ep = &dev->ep [i]; | 1092 | struct pxa2xx_ep *ep = &dev->ep [i]; |
1392 | struct pxa2xx_request *req; | 1093 | struct pxa2xx_request *req; |
1393 | int t; | ||
1394 | 1094 | ||
1395 | if (i != 0) { | 1095 | if (i != 0) { |
1396 | const struct usb_endpoint_descriptor *d; | 1096 | const struct usb_endpoint_descriptor *d; |
@@ -1400,10 +1100,9 @@ udc_proc_read(char *page, char **start, off_t off, int count, | |||
1400 | continue; | 1100 | continue; |
1401 | tmp = *dev->ep [i].reg_udccs; | 1101 | tmp = *dev->ep [i].reg_udccs; |
1402 | t = scnprintf(next, size, | 1102 | t = scnprintf(next, size, |
1403 | "%s max %d %s udccs %02x irqs %lu/%lu\n", | 1103 | "%s max %d %s udccs %02x irqs %lu\n", |
1404 | ep->ep.name, le16_to_cpu (d->wMaxPacketSize), | 1104 | ep->ep.name, le16_to_cpu (d->wMaxPacketSize), |
1405 | (ep->dma >= 0) ? "dma" : "pio", tmp, | 1105 | "pio", tmp, ep->pio_irqs); |
1406 | ep->pio_irqs, ep->dma_irqs); | ||
1407 | /* TODO translate all five groups of udccs bits! */ | 1106 | /* TODO translate all five groups of udccs bits! */ |
1408 | 1107 | ||
1409 | } else /* ep0 should only have one transfer queued */ | 1108 | } else /* ep0 should only have one transfer queued */ |
@@ -1423,19 +1122,7 @@ udc_proc_read(char *page, char **start, off_t off, int count, | |||
1423 | continue; | 1122 | continue; |
1424 | } | 1123 | } |
1425 | list_for_each_entry(req, &ep->queue, queue) { | 1124 | list_for_each_entry(req, &ep->queue, queue) { |
1426 | #ifdef USE_DMA | 1125 | t = scnprintf(next, size, |
1427 | if (ep->dma >= 0 && req->queue.prev == &ep->queue) | ||
1428 | t = scnprintf(next, size, | ||
1429 | "\treq %p len %d/%d " | ||
1430 | "buf %p (dma%d dcmd %08x)\n", | ||
1431 | &req->req, req->req.actual, | ||
1432 | req->req.length, req->req.buf, | ||
1433 | ep->dma, DCMD(ep->dma) | ||
1434 | // low 13 bits == bytes-to-go | ||
1435 | ); | ||
1436 | else | ||
1437 | #endif | ||
1438 | t = scnprintf(next, size, | ||
1439 | "\treq %p len %d/%d buf %p\n", | 1126 | "\treq %p len %d/%d buf %p\n", |
1440 | &req->req, req->req.actual, | 1127 | &req->req, req->req.actual, |
1441 | req->req.length, req->req.buf); | 1128 | req->req.length, req->req.buf); |
@@ -1488,7 +1175,6 @@ static void udc_disable(struct pxa2xx_udc *dev) | |||
1488 | 1175 | ||
1489 | ep0_idle (dev); | 1176 | ep0_idle (dev); |
1490 | dev->gadget.speed = USB_SPEED_UNKNOWN; | 1177 | dev->gadget.speed = USB_SPEED_UNKNOWN; |
1491 | LED_CONNECTED_OFF; | ||
1492 | } | 1178 | } |
1493 | 1179 | ||
1494 | 1180 | ||
@@ -1514,7 +1200,7 @@ static void udc_reinit(struct pxa2xx_udc *dev) | |||
1514 | ep->desc = NULL; | 1200 | ep->desc = NULL; |
1515 | ep->stopped = 0; | 1201 | ep->stopped = 0; |
1516 | INIT_LIST_HEAD (&ep->queue); | 1202 | INIT_LIST_HEAD (&ep->queue); |
1517 | ep->pio_irqs = ep->dma_irqs = 0; | 1203 | ep->pio_irqs = 0; |
1518 | } | 1204 | } |
1519 | 1205 | ||
1520 | /* the rest was statically initialized, and is read-only */ | 1206 | /* the rest was statically initialized, and is read-only */ |
@@ -1666,7 +1352,6 @@ stop_activity(struct pxa2xx_udc *dev, struct usb_gadget_driver *driver) | |||
1666 | del_timer_sync(&dev->timer); | 1352 | del_timer_sync(&dev->timer); |
1667 | 1353 | ||
1668 | /* report disconnect; the driver is already quiesced */ | 1354 | /* report disconnect; the driver is already quiesced */ |
1669 | LED_CONNECTED_OFF; | ||
1670 | if (driver) | 1355 | if (driver) |
1671 | driver->disconnect(&dev->gadget); | 1356 | driver->disconnect(&dev->gadget); |
1672 | 1357 | ||
@@ -1715,16 +1400,13 @@ lubbock_vbus_irq(int irq, void *_dev) | |||
1715 | int vbus; | 1400 | int vbus; |
1716 | 1401 | ||
1717 | dev->stats.irqs++; | 1402 | dev->stats.irqs++; |
1718 | HEX_DISPLAY(dev->stats.irqs); | ||
1719 | switch (irq) { | 1403 | switch (irq) { |
1720 | case LUBBOCK_USB_IRQ: | 1404 | case LUBBOCK_USB_IRQ: |
1721 | LED_CONNECTED_ON; | ||
1722 | vbus = 1; | 1405 | vbus = 1; |
1723 | disable_irq(LUBBOCK_USB_IRQ); | 1406 | disable_irq(LUBBOCK_USB_IRQ); |
1724 | enable_irq(LUBBOCK_USB_DISC_IRQ); | 1407 | enable_irq(LUBBOCK_USB_DISC_IRQ); |
1725 | break; | 1408 | break; |
1726 | case LUBBOCK_USB_DISC_IRQ: | 1409 | case LUBBOCK_USB_DISC_IRQ: |
1727 | LED_CONNECTED_OFF; | ||
1728 | vbus = 0; | 1410 | vbus = 0; |
1729 | disable_irq(LUBBOCK_USB_DISC_IRQ); | 1411 | disable_irq(LUBBOCK_USB_DISC_IRQ); |
1730 | enable_irq(LUBBOCK_USB_IRQ); | 1412 | enable_irq(LUBBOCK_USB_IRQ); |
@@ -1742,7 +1424,7 @@ lubbock_vbus_irq(int irq, void *_dev) | |||
1742 | static irqreturn_t udc_vbus_irq(int irq, void *_dev) | 1424 | static irqreturn_t udc_vbus_irq(int irq, void *_dev) |
1743 | { | 1425 | { |
1744 | struct pxa2xx_udc *dev = _dev; | 1426 | struct pxa2xx_udc *dev = _dev; |
1745 | int vbus = udc_gpio_get(dev->mach->gpio_vbus); | 1427 | int vbus = gpio_get_value(dev->mach->gpio_vbus); |
1746 | 1428 | ||
1747 | pxa2xx_udc_vbus_session(&dev->gadget, vbus); | 1429 | pxa2xx_udc_vbus_session(&dev->gadget, vbus); |
1748 | return IRQ_HANDLED; | 1430 | return IRQ_HANDLED; |
@@ -2040,18 +1722,6 @@ static void handle_ep(struct pxa2xx_ep *ep) | |||
2040 | 1722 | ||
2041 | /* fifos can hold packets, ready for reading... */ | 1723 | /* fifos can hold packets, ready for reading... */ |
2042 | if (likely(req)) { | 1724 | if (likely(req)) { |
2043 | #ifdef USE_OUT_DMA | ||
2044 | // TODO didn't yet debug out-dma. this approach assumes | ||
2045 | // the worst about short packets and RPC; it might be better. | ||
2046 | |||
2047 | if (likely(ep->dma >= 0)) { | ||
2048 | if (!(udccs & UDCCS_BO_RSP)) { | ||
2049 | *ep->reg_udccs = UDCCS_BO_RPC; | ||
2050 | ep->dma_irqs++; | ||
2051 | return; | ||
2052 | } | ||
2053 | } | ||
2054 | #endif | ||
2055 | completed = read_fifo(ep, req); | 1725 | completed = read_fifo(ep, req); |
2056 | } else | 1726 | } else |
2057 | pio_irq_disable (ep->bEndpointAddress); | 1727 | pio_irq_disable (ep->bEndpointAddress); |
@@ -2074,7 +1744,6 @@ pxa2xx_udc_irq(int irq, void *_dev) | |||
2074 | int handled; | 1744 | int handled; |
2075 | 1745 | ||
2076 | dev->stats.irqs++; | 1746 | dev->stats.irqs++; |
2077 | HEX_DISPLAY(dev->stats.irqs); | ||
2078 | do { | 1747 | do { |
2079 | u32 udccr = UDCCR; | 1748 | u32 udccr = UDCCR; |
2080 | 1749 | ||
@@ -2125,7 +1794,6 @@ pxa2xx_udc_irq(int irq, void *_dev) | |||
2125 | } else { | 1794 | } else { |
2126 | DBG(DBG_VERBOSE, "USB reset end\n"); | 1795 | DBG(DBG_VERBOSE, "USB reset end\n"); |
2127 | dev->gadget.speed = USB_SPEED_FULL; | 1796 | dev->gadget.speed = USB_SPEED_FULL; |
2128 | LED_CONNECTED_ON; | ||
2129 | memset(&dev->stats, 0, sizeof dev->stats); | 1797 | memset(&dev->stats, 0, sizeof dev->stats); |
2130 | /* driver and endpoints are still reset */ | 1798 | /* driver and endpoints are still reset */ |
2131 | } | 1799 | } |
@@ -2217,7 +1885,6 @@ static struct pxa2xx_udc memory = { | |||
2217 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 1885 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
2218 | .reg_udccs = &UDCCS1, | 1886 | .reg_udccs = &UDCCS1, |
2219 | .reg_uddr = &UDDR1, | 1887 | .reg_uddr = &UDDR1, |
2220 | drcmr (25) | ||
2221 | }, | 1888 | }, |
2222 | .ep[2] = { | 1889 | .ep[2] = { |
2223 | .ep = { | 1890 | .ep = { |
@@ -2232,7 +1899,6 @@ static struct pxa2xx_udc memory = { | |||
2232 | .reg_udccs = &UDCCS2, | 1899 | .reg_udccs = &UDCCS2, |
2233 | .reg_ubcr = &UBCR2, | 1900 | .reg_ubcr = &UBCR2, |
2234 | .reg_uddr = &UDDR2, | 1901 | .reg_uddr = &UDDR2, |
2235 | drcmr (26) | ||
2236 | }, | 1902 | }, |
2237 | #ifndef CONFIG_USB_PXA2XX_SMALL | 1903 | #ifndef CONFIG_USB_PXA2XX_SMALL |
2238 | .ep[3] = { | 1904 | .ep[3] = { |
@@ -2247,7 +1913,6 @@ static struct pxa2xx_udc memory = { | |||
2247 | .bmAttributes = USB_ENDPOINT_XFER_ISOC, | 1913 | .bmAttributes = USB_ENDPOINT_XFER_ISOC, |
2248 | .reg_udccs = &UDCCS3, | 1914 | .reg_udccs = &UDCCS3, |
2249 | .reg_uddr = &UDDR3, | 1915 | .reg_uddr = &UDDR3, |
2250 | drcmr (27) | ||
2251 | }, | 1916 | }, |
2252 | .ep[4] = { | 1917 | .ep[4] = { |
2253 | .ep = { | 1918 | .ep = { |
@@ -2262,7 +1927,6 @@ static struct pxa2xx_udc memory = { | |||
2262 | .reg_udccs = &UDCCS4, | 1927 | .reg_udccs = &UDCCS4, |
2263 | .reg_ubcr = &UBCR4, | 1928 | .reg_ubcr = &UBCR4, |
2264 | .reg_uddr = &UDDR4, | 1929 | .reg_uddr = &UDDR4, |
2265 | drcmr (28) | ||
2266 | }, | 1930 | }, |
2267 | .ep[5] = { | 1931 | .ep[5] = { |
2268 | .ep = { | 1932 | .ep = { |
@@ -2291,7 +1955,6 @@ static struct pxa2xx_udc memory = { | |||
2291 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 1955 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
2292 | .reg_udccs = &UDCCS6, | 1956 | .reg_udccs = &UDCCS6, |
2293 | .reg_uddr = &UDDR6, | 1957 | .reg_uddr = &UDDR6, |
2294 | drcmr (30) | ||
2295 | }, | 1958 | }, |
2296 | .ep[7] = { | 1959 | .ep[7] = { |
2297 | .ep = { | 1960 | .ep = { |
@@ -2306,7 +1969,6 @@ static struct pxa2xx_udc memory = { | |||
2306 | .reg_udccs = &UDCCS7, | 1969 | .reg_udccs = &UDCCS7, |
2307 | .reg_ubcr = &UBCR7, | 1970 | .reg_ubcr = &UBCR7, |
2308 | .reg_uddr = &UDDR7, | 1971 | .reg_uddr = &UDDR7, |
2309 | drcmr (31) | ||
2310 | }, | 1972 | }, |
2311 | .ep[8] = { | 1973 | .ep[8] = { |
2312 | .ep = { | 1974 | .ep = { |
@@ -2320,7 +1982,6 @@ static struct pxa2xx_udc memory = { | |||
2320 | .bmAttributes = USB_ENDPOINT_XFER_ISOC, | 1982 | .bmAttributes = USB_ENDPOINT_XFER_ISOC, |
2321 | .reg_udccs = &UDCCS8, | 1983 | .reg_udccs = &UDCCS8, |
2322 | .reg_uddr = &UDDR8, | 1984 | .reg_uddr = &UDDR8, |
2323 | drcmr (32) | ||
2324 | }, | 1985 | }, |
2325 | .ep[9] = { | 1986 | .ep[9] = { |
2326 | .ep = { | 1987 | .ep = { |
@@ -2335,7 +1996,6 @@ static struct pxa2xx_udc memory = { | |||
2335 | .reg_udccs = &UDCCS9, | 1996 | .reg_udccs = &UDCCS9, |
2336 | .reg_ubcr = &UBCR9, | 1997 | .reg_ubcr = &UBCR9, |
2337 | .reg_uddr = &UDDR9, | 1998 | .reg_uddr = &UDDR9, |
2338 | drcmr (33) | ||
2339 | }, | 1999 | }, |
2340 | .ep[10] = { | 2000 | .ep[10] = { |
2341 | .ep = { | 2001 | .ep = { |
@@ -2364,7 +2024,6 @@ static struct pxa2xx_udc memory = { | |||
2364 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | 2024 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
2365 | .reg_udccs = &UDCCS11, | 2025 | .reg_udccs = &UDCCS11, |
2366 | .reg_uddr = &UDDR11, | 2026 | .reg_uddr = &UDDR11, |
2367 | drcmr (35) | ||
2368 | }, | 2027 | }, |
2369 | .ep[12] = { | 2028 | .ep[12] = { |
2370 | .ep = { | 2029 | .ep = { |
@@ -2379,7 +2038,6 @@ static struct pxa2xx_udc memory = { | |||
2379 | .reg_udccs = &UDCCS12, | 2038 | .reg_udccs = &UDCCS12, |
2380 | .reg_ubcr = &UBCR12, | 2039 | .reg_ubcr = &UBCR12, |
2381 | .reg_uddr = &UDDR12, | 2040 | .reg_uddr = &UDDR12, |
2382 | drcmr (36) | ||
2383 | }, | 2041 | }, |
2384 | .ep[13] = { | 2042 | .ep[13] = { |
2385 | .ep = { | 2043 | .ep = { |
@@ -2393,7 +2051,6 @@ static struct pxa2xx_udc memory = { | |||
2393 | .bmAttributes = USB_ENDPOINT_XFER_ISOC, | 2051 | .bmAttributes = USB_ENDPOINT_XFER_ISOC, |
2394 | .reg_udccs = &UDCCS13, | 2052 | .reg_udccs = &UDCCS13, |
2395 | .reg_uddr = &UDDR13, | 2053 | .reg_uddr = &UDDR13, |
2396 | drcmr (37) | ||
2397 | }, | 2054 | }, |
2398 | .ep[14] = { | 2055 | .ep[14] = { |
2399 | .ep = { | 2056 | .ep = { |
@@ -2408,7 +2065,6 @@ static struct pxa2xx_udc memory = { | |||
2408 | .reg_udccs = &UDCCS14, | 2065 | .reg_udccs = &UDCCS14, |
2409 | .reg_ubcr = &UBCR14, | 2066 | .reg_ubcr = &UBCR14, |
2410 | .reg_uddr = &UDDR14, | 2067 | .reg_uddr = &UDDR14, |
2411 | drcmr (38) | ||
2412 | }, | 2068 | }, |
2413 | .ep[15] = { | 2069 | .ep[15] = { |
2414 | .ep = { | 2070 | .ep = { |
@@ -2466,7 +2122,7 @@ static struct pxa2xx_udc memory = { | |||
2466 | static int __init pxa2xx_udc_probe(struct platform_device *pdev) | 2122 | static int __init pxa2xx_udc_probe(struct platform_device *pdev) |
2467 | { | 2123 | { |
2468 | struct pxa2xx_udc *dev = &memory; | 2124 | struct pxa2xx_udc *dev = &memory; |
2469 | int retval, out_dma = 1, vbus_irq, irq; | 2125 | int retval, vbus_irq, irq; |
2470 | u32 chiprev; | 2126 | u32 chiprev; |
2471 | 2127 | ||
2472 | /* insist on Intel/ARM/XScale */ | 2128 | /* insist on Intel/ARM/XScale */ |
@@ -2489,7 +2145,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) | |||
2489 | case PXA250_B2: case PXA210_B2: | 2145 | case PXA250_B2: case PXA210_B2: |
2490 | case PXA250_B1: case PXA210_B1: | 2146 | case PXA250_B1: case PXA210_B1: |
2491 | case PXA250_B0: case PXA210_B0: | 2147 | case PXA250_B0: case PXA210_B0: |
2492 | out_dma = 0; | 2148 | /* OUT-DMA is broken ... */ |
2493 | /* fall through */ | 2149 | /* fall through */ |
2494 | case PXA250_C0: case PXA210_C0: | 2150 | case PXA250_C0: case PXA210_C0: |
2495 | break; | 2151 | break; |
@@ -2498,11 +2154,9 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) | |||
2498 | case IXP425_B0: | 2154 | case IXP425_B0: |
2499 | case IXP465_AD: | 2155 | case IXP465_AD: |
2500 | dev->has_cfr = 1; | 2156 | dev->has_cfr = 1; |
2501 | out_dma = 0; | ||
2502 | break; | 2157 | break; |
2503 | #endif | 2158 | #endif |
2504 | default: | 2159 | default: |
2505 | out_dma = 0; | ||
2506 | printk(KERN_ERR "%s: unrecognized processor: %08x\n", | 2160 | printk(KERN_ERR "%s: unrecognized processor: %08x\n", |
2507 | driver_name, chiprev); | 2161 | driver_name, chiprev); |
2508 | /* iop3xx, ixp4xx, ... */ | 2162 | /* iop3xx, ixp4xx, ... */ |
@@ -2513,36 +2167,41 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) | |||
2513 | if (irq < 0) | 2167 | if (irq < 0) |
2514 | return -ENODEV; | 2168 | return -ENODEV; |
2515 | 2169 | ||
2516 | pr_debug("%s: IRQ %d%s%s%s\n", driver_name, irq, | 2170 | pr_debug("%s: IRQ %d%s%s\n", driver_name, irq, |
2517 | dev->has_cfr ? "" : " (!cfr)", | 2171 | dev->has_cfr ? "" : " (!cfr)", |
2518 | out_dma ? "" : " (broken dma-out)", | 2172 | SIZE_STR "(pio)" |
2519 | SIZE_STR DMASTR | ||
2520 | ); | 2173 | ); |
2521 | 2174 | ||
2522 | #ifdef USE_DMA | ||
2523 | #ifndef USE_OUT_DMA | ||
2524 | out_dma = 0; | ||
2525 | #endif | ||
2526 | /* pxa 250 erratum 130 prevents using OUT dma (fixed C0) */ | ||
2527 | if (!out_dma) { | ||
2528 | DMSG("disabled OUT dma\n"); | ||
2529 | dev->ep[ 2].reg_drcmr = dev->ep[ 4].reg_drcmr = 0; | ||
2530 | dev->ep[ 7].reg_drcmr = dev->ep[ 9].reg_drcmr = 0; | ||
2531 | dev->ep[12].reg_drcmr = dev->ep[14].reg_drcmr = 0; | ||
2532 | } | ||
2533 | #endif | ||
2534 | |||
2535 | /* other non-static parts of init */ | 2175 | /* other non-static parts of init */ |
2536 | dev->dev = &pdev->dev; | 2176 | dev->dev = &pdev->dev; |
2537 | dev->mach = pdev->dev.platform_data; | 2177 | dev->mach = pdev->dev.platform_data; |
2178 | |||
2538 | if (dev->mach->gpio_vbus) { | 2179 | if (dev->mach->gpio_vbus) { |
2539 | udc_gpio_init_vbus(dev->mach->gpio_vbus); | 2180 | if ((retval = gpio_request(dev->mach->gpio_vbus, |
2540 | vbus_irq = udc_gpio_to_irq(dev->mach->gpio_vbus); | 2181 | "pxa2xx_udc GPIO VBUS"))) { |
2182 | dev_dbg(&pdev->dev, | ||
2183 | "can't get vbus gpio %d, err: %d\n", | ||
2184 | dev->mach->gpio_vbus, retval); | ||
2185 | return -EBUSY; | ||
2186 | } | ||
2187 | gpio_direction_input(dev->mach->gpio_vbus); | ||
2188 | vbus_irq = gpio_to_irq(dev->mach->gpio_vbus); | ||
2541 | set_irq_type(vbus_irq, IRQT_BOTHEDGE); | 2189 | set_irq_type(vbus_irq, IRQT_BOTHEDGE); |
2542 | } else | 2190 | } else |
2543 | vbus_irq = 0; | 2191 | vbus_irq = 0; |
2544 | if (dev->mach->gpio_pullup) | 2192 | |
2545 | udc_gpio_init_pullup(dev->mach->gpio_pullup); | 2193 | if (dev->mach->gpio_pullup) { |
2194 | if ((retval = gpio_request(dev->mach->gpio_pullup, | ||
2195 | "pca2xx_udc GPIO PULLUP"))) { | ||
2196 | dev_dbg(&pdev->dev, | ||
2197 | "can't get pullup gpio %d, err: %d\n", | ||
2198 | dev->mach->gpio_pullup, retval); | ||
2199 | if (dev->mach->gpio_vbus) | ||
2200 | gpio_free(dev->mach->gpio_vbus); | ||
2201 | return -EBUSY; | ||
2202 | } | ||
2203 | gpio_direction_output(dev->mach->gpio_pullup, 0); | ||
2204 | } | ||
2546 | 2205 | ||
2547 | init_timer(&dev->timer); | 2206 | init_timer(&dev->timer); |
2548 | dev->timer.function = udc_watchdog; | 2207 | dev->timer.function = udc_watchdog; |
@@ -2566,6 +2225,10 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) | |||
2566 | if (retval != 0) { | 2225 | if (retval != 0) { |
2567 | printk(KERN_ERR "%s: can't get irq %d, err %d\n", | 2226 | printk(KERN_ERR "%s: can't get irq %d, err %d\n", |
2568 | driver_name, irq, retval); | 2227 | driver_name, irq, retval); |
2228 | if (dev->mach->gpio_pullup) | ||
2229 | gpio_free(dev->mach->gpio_pullup); | ||
2230 | if (dev->mach->gpio_vbus) | ||
2231 | gpio_free(dev->mach->gpio_vbus); | ||
2569 | return -EBUSY; | 2232 | return -EBUSY; |
2570 | } | 2233 | } |
2571 | dev->got_irq = 1; | 2234 | dev->got_irq = 1; |
@@ -2581,6 +2244,10 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) | |||
2581 | driver_name, LUBBOCK_USB_DISC_IRQ, retval); | 2244 | driver_name, LUBBOCK_USB_DISC_IRQ, retval); |
2582 | lubbock_fail0: | 2245 | lubbock_fail0: |
2583 | free_irq(irq, dev); | 2246 | free_irq(irq, dev); |
2247 | if (dev->mach->gpio_pullup) | ||
2248 | gpio_free(dev->mach->gpio_pullup); | ||
2249 | if (dev->mach->gpio_vbus) | ||
2250 | gpio_free(dev->mach->gpio_vbus); | ||
2584 | return -EBUSY; | 2251 | return -EBUSY; |
2585 | } | 2252 | } |
2586 | retval = request_irq(LUBBOCK_USB_IRQ, | 2253 | retval = request_irq(LUBBOCK_USB_IRQ, |
@@ -2593,11 +2260,6 @@ lubbock_fail0: | |||
2593 | free_irq(LUBBOCK_USB_DISC_IRQ, dev); | 2260 | free_irq(LUBBOCK_USB_DISC_IRQ, dev); |
2594 | goto lubbock_fail0; | 2261 | goto lubbock_fail0; |
2595 | } | 2262 | } |
2596 | #ifdef DEBUG | ||
2597 | /* with U-Boot (but not BLOB), hex is off by default */ | ||
2598 | HEX_DISPLAY(dev->stats.irqs); | ||
2599 | LUB_DISC_BLNK_LED &= 0xff; | ||
2600 | #endif | ||
2601 | } else | 2263 | } else |
2602 | #endif | 2264 | #endif |
2603 | if (vbus_irq) { | 2265 | if (vbus_irq) { |
@@ -2608,6 +2270,10 @@ lubbock_fail0: | |||
2608 | printk(KERN_ERR "%s: can't get irq %i, err %d\n", | 2270 | printk(KERN_ERR "%s: can't get irq %i, err %d\n", |
2609 | driver_name, vbus_irq, retval); | 2271 | driver_name, vbus_irq, retval); |
2610 | free_irq(irq, dev); | 2272 | free_irq(irq, dev); |
2273 | if (dev->mach->gpio_pullup) | ||
2274 | gpio_free(dev->mach->gpio_pullup); | ||
2275 | if (dev->mach->gpio_vbus) | ||
2276 | gpio_free(dev->mach->gpio_vbus); | ||
2611 | return -EBUSY; | 2277 | return -EBUSY; |
2612 | } | 2278 | } |
2613 | } | 2279 | } |
@@ -2641,8 +2307,13 @@ static int __exit pxa2xx_udc_remove(struct platform_device *pdev) | |||
2641 | free_irq(LUBBOCK_USB_IRQ, dev); | 2307 | free_irq(LUBBOCK_USB_IRQ, dev); |
2642 | } | 2308 | } |
2643 | #endif | 2309 | #endif |
2644 | if (dev->mach->gpio_vbus) | 2310 | if (dev->mach->gpio_vbus) { |
2645 | free_irq(IRQ_GPIO(dev->mach->gpio_vbus), dev); | 2311 | free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev); |
2312 | gpio_free(dev->mach->gpio_vbus); | ||
2313 | } | ||
2314 | if (dev->mach->gpio_pullup) | ||
2315 | gpio_free(dev->mach->gpio_pullup); | ||
2316 | |||
2646 | platform_set_drvdata(pdev, NULL); | 2317 | platform_set_drvdata(pdev, NULL); |
2647 | the_controller = NULL; | 2318 | the_controller = NULL; |
2648 | return 0; | 2319 | return 0; |
diff --git a/drivers/usb/gadget/pxa2xx_udc.h b/drivers/usb/gadget/pxa2xx_udc.h index 773e549aff3f..0e5d0e6fb0e2 100644 --- a/drivers/usb/gadget/pxa2xx_udc.h +++ b/drivers/usb/gadget/pxa2xx_udc.h | |||
@@ -54,8 +54,6 @@ struct pxa2xx_ep { | |||
54 | const struct usb_endpoint_descriptor *desc; | 54 | const struct usb_endpoint_descriptor *desc; |
55 | struct list_head queue; | 55 | struct list_head queue; |
56 | unsigned long pio_irqs; | 56 | unsigned long pio_irqs; |
57 | unsigned long dma_irqs; | ||
58 | short dma; | ||
59 | 57 | ||
60 | unsigned short fifo_size; | 58 | unsigned short fifo_size; |
61 | u8 bEndpointAddress; | 59 | u8 bEndpointAddress; |
@@ -63,7 +61,7 @@ struct pxa2xx_ep { | |||
63 | 61 | ||
64 | unsigned stopped : 1; | 62 | unsigned stopped : 1; |
65 | unsigned dma_fixup : 1; | 63 | unsigned dma_fixup : 1; |
66 | 64 | ||
67 | /* UDCCS = UDC Control/Status for this EP | 65 | /* UDCCS = UDC Control/Status for this EP |
68 | * UBCR = UDC Byte Count Remaining (contents of OUT fifo) | 66 | * UBCR = UDC Byte Count Remaining (contents of OUT fifo) |
69 | * UDDR = UDC Endpoint Data Register (the fifo) | 67 | * UDDR = UDC Endpoint Data Register (the fifo) |
@@ -72,12 +70,6 @@ struct pxa2xx_ep { | |||
72 | volatile u32 *reg_udccs; | 70 | volatile u32 *reg_udccs; |
73 | volatile u32 *reg_ubcr; | 71 | volatile u32 *reg_ubcr; |
74 | volatile u32 *reg_uddr; | 72 | volatile u32 *reg_uddr; |
75 | #ifdef USE_DMA | ||
76 | volatile u32 *reg_drcmr; | ||
77 | #define drcmr(n) .reg_drcmr = & DRCMR ## n , | ||
78 | #else | ||
79 | #define drcmr(n) | ||
80 | #endif | ||
81 | }; | 73 | }; |
82 | 74 | ||
83 | struct pxa2xx_request { | 75 | struct pxa2xx_request { |
@@ -85,7 +77,7 @@ struct pxa2xx_request { | |||
85 | struct list_head queue; | 77 | struct list_head queue; |
86 | }; | 78 | }; |
87 | 79 | ||
88 | enum ep0_state { | 80 | enum ep0_state { |
89 | EP0_IDLE, | 81 | EP0_IDLE, |
90 | EP0_IN_DATA_PHASE, | 82 | EP0_IN_DATA_PHASE, |
91 | EP0_OUT_DATA_PHASE, | 83 | EP0_OUT_DATA_PHASE, |
@@ -108,7 +100,6 @@ struct udc_stats { | |||
108 | 100 | ||
109 | #ifdef CONFIG_USB_PXA2XX_SMALL | 101 | #ifdef CONFIG_USB_PXA2XX_SMALL |
110 | /* when memory's tight, SMALL config saves code+data. */ | 102 | /* when memory's tight, SMALL config saves code+data. */ |
111 | #undef USE_DMA | ||
112 | #define PXA_UDC_NUM_ENDPOINTS 3 | 103 | #define PXA_UDC_NUM_ENDPOINTS 3 |
113 | #endif | 104 | #endif |
114 | 105 | ||
@@ -144,37 +135,8 @@ struct pxa2xx_udc { | |||
144 | #ifdef CONFIG_ARCH_LUBBOCK | 135 | #ifdef CONFIG_ARCH_LUBBOCK |
145 | #include <asm/arch/lubbock.h> | 136 | #include <asm/arch/lubbock.h> |
146 | /* lubbock can also report usb connect/disconnect irqs */ | 137 | /* lubbock can also report usb connect/disconnect irqs */ |
147 | |||
148 | #ifdef DEBUG | ||
149 | #define HEX_DISPLAY(n) if (machine_is_lubbock()) { LUB_HEXLED = (n); } | ||
150 | #endif | 138 | #endif |
151 | 139 | ||
152 | #endif | ||
153 | |||
154 | /*-------------------------------------------------------------------------*/ | ||
155 | |||
156 | /* LEDs are only for debug */ | ||
157 | #ifndef HEX_DISPLAY | ||
158 | #define HEX_DISPLAY(n) do {} while(0) | ||
159 | #endif | ||
160 | |||
161 | #ifdef DEBUG | ||
162 | #include <asm/leds.h> | ||
163 | |||
164 | #define LED_CONNECTED_ON leds_event(led_green_on) | ||
165 | #define LED_CONNECTED_OFF do { \ | ||
166 | leds_event(led_green_off); \ | ||
167 | HEX_DISPLAY(0); \ | ||
168 | } while(0) | ||
169 | #endif | ||
170 | |||
171 | #ifndef LED_CONNECTED_ON | ||
172 | #define LED_CONNECTED_ON do {} while(0) | ||
173 | #define LED_CONNECTED_OFF do {} while(0) | ||
174 | #endif | ||
175 | |||
176 | /*-------------------------------------------------------------------------*/ | ||
177 | |||
178 | static struct pxa2xx_udc *the_controller; | 140 | static struct pxa2xx_udc *the_controller; |
179 | 141 | ||
180 | /*-------------------------------------------------------------------------*/ | 142 | /*-------------------------------------------------------------------------*/ |
@@ -204,7 +166,7 @@ static const char *state_name[] = { | |||
204 | # define UDC_DEBUG DBG_NORMAL | 166 | # define UDC_DEBUG DBG_NORMAL |
205 | #endif | 167 | #endif |
206 | 168 | ||
207 | static void __attribute__ ((__unused__)) | 169 | static void __maybe_unused |
208 | dump_udccr(const char *label) | 170 | dump_udccr(const char *label) |
209 | { | 171 | { |
210 | u32 udccr = UDCCR; | 172 | u32 udccr = UDCCR; |
@@ -220,7 +182,7 @@ dump_udccr(const char *label) | |||
220 | (udccr & UDCCR_UDE) ? " ude" : ""); | 182 | (udccr & UDCCR_UDE) ? " ude" : ""); |
221 | } | 183 | } |
222 | 184 | ||
223 | static void __attribute__ ((__unused__)) | 185 | static void __maybe_unused |
224 | dump_udccs0(const char *label) | 186 | dump_udccs0(const char *label) |
225 | { | 187 | { |
226 | u32 udccs0 = UDCCS0; | 188 | u32 udccs0 = UDCCS0; |
@@ -237,7 +199,7 @@ dump_udccs0(const char *label) | |||
237 | (udccs0 & UDCCS0_OPR) ? " opr" : ""); | 199 | (udccs0 & UDCCS0_OPR) ? " opr" : ""); |
238 | } | 200 | } |
239 | 201 | ||
240 | static void __attribute__ ((__unused__)) | 202 | static void __maybe_unused |
241 | dump_state(struct pxa2xx_udc *dev) | 203 | dump_state(struct pxa2xx_udc *dev) |
242 | { | 204 | { |
243 | u32 tmp; | 205 | u32 tmp; |
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 708657c89132..db1b2bfcee4e 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c | |||
@@ -53,7 +53,7 @@ | |||
53 | */ | 53 | */ |
54 | 54 | ||
55 | #if 0 | 55 | #if 0 |
56 | #define DEBUG(str,args...) do { \ | 56 | #define DBG(str,args...) do { \ |
57 | if (rndis_debug) \ | 57 | if (rndis_debug) \ |
58 | printk(KERN_DEBUG str , ## args ); \ | 58 | printk(KERN_DEBUG str , ## args ); \ |
59 | } while (0) | 59 | } while (0) |
@@ -65,7 +65,7 @@ MODULE_PARM_DESC (rndis_debug, "enable debugging"); | |||
65 | #else | 65 | #else |
66 | 66 | ||
67 | #define rndis_debug 0 | 67 | #define rndis_debug 0 |
68 | #define DEBUG(str,args...) do{}while(0) | 68 | #define DBG(str,args...) do{}while(0) |
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | #define RNDIS_MAX_CONFIGS 1 | 71 | #define RNDIS_MAX_CONFIGS 1 |
@@ -183,9 +183,9 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
183 | if (!resp) return -ENOMEM; | 183 | if (!resp) return -ENOMEM; |
184 | 184 | ||
185 | if (buf_len && rndis_debug > 1) { | 185 | if (buf_len && rndis_debug > 1) { |
186 | DEBUG("query OID %08x value, len %d:\n", OID, buf_len); | 186 | DBG("query OID %08x value, len %d:\n", OID, buf_len); |
187 | for (i = 0; i < buf_len; i += 16) { | 187 | for (i = 0; i < buf_len; i += 16) { |
188 | DEBUG ("%03d: %08x %08x %08x %08x\n", i, | 188 | DBG("%03d: %08x %08x %08x %08x\n", i, |
189 | le32_to_cpu(get_unaligned((__le32 *) | 189 | le32_to_cpu(get_unaligned((__le32 *) |
190 | &buf[i])), | 190 | &buf[i])), |
191 | le32_to_cpu(get_unaligned((__le32 *) | 191 | le32_to_cpu(get_unaligned((__le32 *) |
@@ -207,7 +207,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
207 | 207 | ||
208 | /* mandatory */ | 208 | /* mandatory */ |
209 | case OID_GEN_SUPPORTED_LIST: | 209 | case OID_GEN_SUPPORTED_LIST: |
210 | DEBUG ("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__); | 210 | DBG("%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__); |
211 | length = sizeof (oid_supported_list); | 211 | length = sizeof (oid_supported_list); |
212 | count = length / sizeof (u32); | 212 | count = length / sizeof (u32); |
213 | for (i = 0; i < count; i++) | 213 | for (i = 0; i < count; i++) |
@@ -217,7 +217,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
217 | 217 | ||
218 | /* mandatory */ | 218 | /* mandatory */ |
219 | case OID_GEN_HARDWARE_STATUS: | 219 | case OID_GEN_HARDWARE_STATUS: |
220 | DEBUG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); | 220 | DBG("%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__); |
221 | /* Bogus question! | 221 | /* Bogus question! |
222 | * Hardware must be ready to receive high level protocols. | 222 | * Hardware must be ready to receive high level protocols. |
223 | * BTW: | 223 | * BTW: |
@@ -230,14 +230,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
230 | 230 | ||
231 | /* mandatory */ | 231 | /* mandatory */ |
232 | case OID_GEN_MEDIA_SUPPORTED: | 232 | case OID_GEN_MEDIA_SUPPORTED: |
233 | DEBUG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); | 233 | DBG("%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__); |
234 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); | 234 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); |
235 | retval = 0; | 235 | retval = 0; |
236 | break; | 236 | break; |
237 | 237 | ||
238 | /* mandatory */ | 238 | /* mandatory */ |
239 | case OID_GEN_MEDIA_IN_USE: | 239 | case OID_GEN_MEDIA_IN_USE: |
240 | DEBUG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); | 240 | DBG("%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__); |
241 | /* one medium, one transport... (maybe you do it better) */ | 241 | /* one medium, one transport... (maybe you do it better) */ |
242 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); | 242 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr].medium); |
243 | retval = 0; | 243 | retval = 0; |
@@ -245,7 +245,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
245 | 245 | ||
246 | /* mandatory */ | 246 | /* mandatory */ |
247 | case OID_GEN_MAXIMUM_FRAME_SIZE: | 247 | case OID_GEN_MAXIMUM_FRAME_SIZE: |
248 | DEBUG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); | 248 | DBG("%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__); |
249 | if (rndis_per_dev_params [configNr].dev) { | 249 | if (rndis_per_dev_params [configNr].dev) { |
250 | *outbuf = cpu_to_le32 ( | 250 | *outbuf = cpu_to_le32 ( |
251 | rndis_per_dev_params [configNr].dev->mtu); | 251 | rndis_per_dev_params [configNr].dev->mtu); |
@@ -256,7 +256,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
256 | /* mandatory */ | 256 | /* mandatory */ |
257 | case OID_GEN_LINK_SPEED: | 257 | case OID_GEN_LINK_SPEED: |
258 | if (rndis_debug > 1) | 258 | if (rndis_debug > 1) |
259 | DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__); | 259 | DBG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__); |
260 | if (rndis_per_dev_params [configNr].media_state | 260 | if (rndis_per_dev_params [configNr].media_state |
261 | == NDIS_MEDIA_STATE_DISCONNECTED) | 261 | == NDIS_MEDIA_STATE_DISCONNECTED) |
262 | *outbuf = __constant_cpu_to_le32 (0); | 262 | *outbuf = __constant_cpu_to_le32 (0); |
@@ -268,7 +268,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
268 | 268 | ||
269 | /* mandatory */ | 269 | /* mandatory */ |
270 | case OID_GEN_TRANSMIT_BLOCK_SIZE: | 270 | case OID_GEN_TRANSMIT_BLOCK_SIZE: |
271 | DEBUG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__); | 271 | DBG("%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__); |
272 | if (rndis_per_dev_params [configNr].dev) { | 272 | if (rndis_per_dev_params [configNr].dev) { |
273 | *outbuf = cpu_to_le32 ( | 273 | *outbuf = cpu_to_le32 ( |
274 | rndis_per_dev_params [configNr].dev->mtu); | 274 | rndis_per_dev_params [configNr].dev->mtu); |
@@ -278,7 +278,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
278 | 278 | ||
279 | /* mandatory */ | 279 | /* mandatory */ |
280 | case OID_GEN_RECEIVE_BLOCK_SIZE: | 280 | case OID_GEN_RECEIVE_BLOCK_SIZE: |
281 | DEBUG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); | 281 | DBG("%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__); |
282 | if (rndis_per_dev_params [configNr].dev) { | 282 | if (rndis_per_dev_params [configNr].dev) { |
283 | *outbuf = cpu_to_le32 ( | 283 | *outbuf = cpu_to_le32 ( |
284 | rndis_per_dev_params [configNr].dev->mtu); | 284 | rndis_per_dev_params [configNr].dev->mtu); |
@@ -288,7 +288,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
288 | 288 | ||
289 | /* mandatory */ | 289 | /* mandatory */ |
290 | case OID_GEN_VENDOR_ID: | 290 | case OID_GEN_VENDOR_ID: |
291 | DEBUG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); | 291 | DBG("%s: OID_GEN_VENDOR_ID\n", __FUNCTION__); |
292 | *outbuf = cpu_to_le32 ( | 292 | *outbuf = cpu_to_le32 ( |
293 | rndis_per_dev_params [configNr].vendorID); | 293 | rndis_per_dev_params [configNr].vendorID); |
294 | retval = 0; | 294 | retval = 0; |
@@ -296,7 +296,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
296 | 296 | ||
297 | /* mandatory */ | 297 | /* mandatory */ |
298 | case OID_GEN_VENDOR_DESCRIPTION: | 298 | case OID_GEN_VENDOR_DESCRIPTION: |
299 | DEBUG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); | 299 | DBG("%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__); |
300 | length = strlen (rndis_per_dev_params [configNr].vendorDescr); | 300 | length = strlen (rndis_per_dev_params [configNr].vendorDescr); |
301 | memcpy (outbuf, | 301 | memcpy (outbuf, |
302 | rndis_per_dev_params [configNr].vendorDescr, length); | 302 | rndis_per_dev_params [configNr].vendorDescr, length); |
@@ -304,7 +304,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
304 | break; | 304 | break; |
305 | 305 | ||
306 | case OID_GEN_VENDOR_DRIVER_VERSION: | 306 | case OID_GEN_VENDOR_DRIVER_VERSION: |
307 | DEBUG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); | 307 | DBG("%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__); |
308 | /* Created as LE */ | 308 | /* Created as LE */ |
309 | *outbuf = rndis_driver_version; | 309 | *outbuf = rndis_driver_version; |
310 | retval = 0; | 310 | retval = 0; |
@@ -312,14 +312,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
312 | 312 | ||
313 | /* mandatory */ | 313 | /* mandatory */ |
314 | case OID_GEN_CURRENT_PACKET_FILTER: | 314 | case OID_GEN_CURRENT_PACKET_FILTER: |
315 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__); | 315 | DBG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__); |
316 | *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter); | 316 | *outbuf = cpu_to_le32 (*rndis_per_dev_params[configNr].filter); |
317 | retval = 0; | 317 | retval = 0; |
318 | break; | 318 | break; |
319 | 319 | ||
320 | /* mandatory */ | 320 | /* mandatory */ |
321 | case OID_GEN_MAXIMUM_TOTAL_SIZE: | 321 | case OID_GEN_MAXIMUM_TOTAL_SIZE: |
322 | DEBUG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__); | 322 | DBG("%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__); |
323 | *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE); | 323 | *outbuf = __constant_cpu_to_le32(RNDIS_MAX_TOTAL_SIZE); |
324 | retval = 0; | 324 | retval = 0; |
325 | break; | 325 | break; |
@@ -327,14 +327,14 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
327 | /* mandatory */ | 327 | /* mandatory */ |
328 | case OID_GEN_MEDIA_CONNECT_STATUS: | 328 | case OID_GEN_MEDIA_CONNECT_STATUS: |
329 | if (rndis_debug > 1) | 329 | if (rndis_debug > 1) |
330 | DEBUG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__); | 330 | DBG("%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__); |
331 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 331 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
332 | .media_state); | 332 | .media_state); |
333 | retval = 0; | 333 | retval = 0; |
334 | break; | 334 | break; |
335 | 335 | ||
336 | case OID_GEN_PHYSICAL_MEDIUM: | 336 | case OID_GEN_PHYSICAL_MEDIUM: |
337 | DEBUG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); | 337 | DBG("%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__); |
338 | *outbuf = __constant_cpu_to_le32 (0); | 338 | *outbuf = __constant_cpu_to_le32 (0); |
339 | retval = 0; | 339 | retval = 0; |
340 | break; | 340 | break; |
@@ -344,7 +344,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
344 | * versions emit undefined RNDIS messages. DOCUMENT ALL THESE! | 344 | * versions emit undefined RNDIS messages. DOCUMENT ALL THESE! |
345 | */ | 345 | */ |
346 | case OID_GEN_MAC_OPTIONS: /* from WinME */ | 346 | case OID_GEN_MAC_OPTIONS: /* from WinME */ |
347 | DEBUG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); | 347 | DBG("%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__); |
348 | *outbuf = __constant_cpu_to_le32( | 348 | *outbuf = __constant_cpu_to_le32( |
349 | NDIS_MAC_OPTION_RECEIVE_SERIALIZED | 349 | NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
350 | | NDIS_MAC_OPTION_FULL_DUPLEX); | 350 | | NDIS_MAC_OPTION_FULL_DUPLEX); |
@@ -356,7 +356,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
356 | /* mandatory */ | 356 | /* mandatory */ |
357 | case OID_GEN_XMIT_OK: | 357 | case OID_GEN_XMIT_OK: |
358 | if (rndis_debug > 1) | 358 | if (rndis_debug > 1) |
359 | DEBUG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); | 359 | DBG("%s: OID_GEN_XMIT_OK\n", __FUNCTION__); |
360 | if (rndis_per_dev_params [configNr].stats) { | 360 | if (rndis_per_dev_params [configNr].stats) { |
361 | *outbuf = cpu_to_le32 ( | 361 | *outbuf = cpu_to_le32 ( |
362 | rndis_per_dev_params [configNr].stats->tx_packets - | 362 | rndis_per_dev_params [configNr].stats->tx_packets - |
@@ -369,7 +369,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
369 | /* mandatory */ | 369 | /* mandatory */ |
370 | case OID_GEN_RCV_OK: | 370 | case OID_GEN_RCV_OK: |
371 | if (rndis_debug > 1) | 371 | if (rndis_debug > 1) |
372 | DEBUG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); | 372 | DBG("%s: OID_GEN_RCV_OK\n", __FUNCTION__); |
373 | if (rndis_per_dev_params [configNr].stats) { | 373 | if (rndis_per_dev_params [configNr].stats) { |
374 | *outbuf = cpu_to_le32 ( | 374 | *outbuf = cpu_to_le32 ( |
375 | rndis_per_dev_params [configNr].stats->rx_packets - | 375 | rndis_per_dev_params [configNr].stats->rx_packets - |
@@ -382,7 +382,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
382 | /* mandatory */ | 382 | /* mandatory */ |
383 | case OID_GEN_XMIT_ERROR: | 383 | case OID_GEN_XMIT_ERROR: |
384 | if (rndis_debug > 1) | 384 | if (rndis_debug > 1) |
385 | DEBUG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__); | 385 | DBG("%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__); |
386 | if (rndis_per_dev_params [configNr].stats) { | 386 | if (rndis_per_dev_params [configNr].stats) { |
387 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 387 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
388 | .stats->tx_errors); | 388 | .stats->tx_errors); |
@@ -393,7 +393,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
393 | /* mandatory */ | 393 | /* mandatory */ |
394 | case OID_GEN_RCV_ERROR: | 394 | case OID_GEN_RCV_ERROR: |
395 | if (rndis_debug > 1) | 395 | if (rndis_debug > 1) |
396 | DEBUG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__); | 396 | DBG("%s: OID_GEN_RCV_ERROR\n", __FUNCTION__); |
397 | if (rndis_per_dev_params [configNr].stats) { | 397 | if (rndis_per_dev_params [configNr].stats) { |
398 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 398 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
399 | .stats->rx_errors); | 399 | .stats->rx_errors); |
@@ -403,7 +403,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
403 | 403 | ||
404 | /* mandatory */ | 404 | /* mandatory */ |
405 | case OID_GEN_RCV_NO_BUFFER: | 405 | case OID_GEN_RCV_NO_BUFFER: |
406 | DEBUG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); | 406 | DBG("%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__); |
407 | if (rndis_per_dev_params [configNr].stats) { | 407 | if (rndis_per_dev_params [configNr].stats) { |
408 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 408 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
409 | .stats->rx_dropped); | 409 | .stats->rx_dropped); |
@@ -413,7 +413,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
413 | 413 | ||
414 | #ifdef RNDIS_OPTIONAL_STATS | 414 | #ifdef RNDIS_OPTIONAL_STATS |
415 | case OID_GEN_DIRECTED_BYTES_XMIT: | 415 | case OID_GEN_DIRECTED_BYTES_XMIT: |
416 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__); | 416 | DBG("%s: OID_GEN_DIRECTED_BYTES_XMIT\n", __FUNCTION__); |
417 | /* | 417 | /* |
418 | * Aunt Tilly's size of shoes | 418 | * Aunt Tilly's size of shoes |
419 | * minus antarctica count of penguins | 419 | * minus antarctica count of penguins |
@@ -433,7 +433,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
433 | break; | 433 | break; |
434 | 434 | ||
435 | case OID_GEN_DIRECTED_FRAMES_XMIT: | 435 | case OID_GEN_DIRECTED_FRAMES_XMIT: |
436 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); | 436 | DBG("%s: OID_GEN_DIRECTED_FRAMES_XMIT\n", __FUNCTION__); |
437 | /* dito */ | 437 | /* dito */ |
438 | if (rndis_per_dev_params [configNr].stats) { | 438 | if (rndis_per_dev_params [configNr].stats) { |
439 | *outbuf = cpu_to_le32 ( | 439 | *outbuf = cpu_to_le32 ( |
@@ -449,7 +449,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
449 | break; | 449 | break; |
450 | 450 | ||
451 | case OID_GEN_MULTICAST_BYTES_XMIT: | 451 | case OID_GEN_MULTICAST_BYTES_XMIT: |
452 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); | 452 | DBG("%s: OID_GEN_MULTICAST_BYTES_XMIT\n", __FUNCTION__); |
453 | if (rndis_per_dev_params [configNr].stats) { | 453 | if (rndis_per_dev_params [configNr].stats) { |
454 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 454 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
455 | .stats->multicast*1234); | 455 | .stats->multicast*1234); |
@@ -458,7 +458,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
458 | break; | 458 | break; |
459 | 459 | ||
460 | case OID_GEN_MULTICAST_FRAMES_XMIT: | 460 | case OID_GEN_MULTICAST_FRAMES_XMIT: |
461 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); | 461 | DBG("%s: OID_GEN_MULTICAST_FRAMES_XMIT\n", __FUNCTION__); |
462 | if (rndis_per_dev_params [configNr].stats) { | 462 | if (rndis_per_dev_params [configNr].stats) { |
463 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 463 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
464 | .stats->multicast); | 464 | .stats->multicast); |
@@ -467,7 +467,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
467 | break; | 467 | break; |
468 | 468 | ||
469 | case OID_GEN_BROADCAST_BYTES_XMIT: | 469 | case OID_GEN_BROADCAST_BYTES_XMIT: |
470 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); | 470 | DBG("%s: OID_GEN_BROADCAST_BYTES_XMIT\n", __FUNCTION__); |
471 | if (rndis_per_dev_params [configNr].stats) { | 471 | if (rndis_per_dev_params [configNr].stats) { |
472 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 472 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
473 | .stats->tx_packets/42*255); | 473 | .stats->tx_packets/42*255); |
@@ -476,7 +476,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
476 | break; | 476 | break; |
477 | 477 | ||
478 | case OID_GEN_BROADCAST_FRAMES_XMIT: | 478 | case OID_GEN_BROADCAST_FRAMES_XMIT: |
479 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); | 479 | DBG("%s: OID_GEN_BROADCAST_FRAMES_XMIT\n", __FUNCTION__); |
480 | if (rndis_per_dev_params [configNr].stats) { | 480 | if (rndis_per_dev_params [configNr].stats) { |
481 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 481 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
482 | .stats->tx_packets/42); | 482 | .stats->tx_packets/42); |
@@ -485,19 +485,19 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
485 | break; | 485 | break; |
486 | 486 | ||
487 | case OID_GEN_DIRECTED_BYTES_RCV: | 487 | case OID_GEN_DIRECTED_BYTES_RCV: |
488 | DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); | 488 | DBG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); |
489 | *outbuf = __constant_cpu_to_le32 (0); | 489 | *outbuf = __constant_cpu_to_le32 (0); |
490 | retval = 0; | 490 | retval = 0; |
491 | break; | 491 | break; |
492 | 492 | ||
493 | case OID_GEN_DIRECTED_FRAMES_RCV: | 493 | case OID_GEN_DIRECTED_FRAMES_RCV: |
494 | DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); | 494 | DBG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); |
495 | *outbuf = __constant_cpu_to_le32 (0); | 495 | *outbuf = __constant_cpu_to_le32 (0); |
496 | retval = 0; | 496 | retval = 0; |
497 | break; | 497 | break; |
498 | 498 | ||
499 | case OID_GEN_MULTICAST_BYTES_RCV: | 499 | case OID_GEN_MULTICAST_BYTES_RCV: |
500 | DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); | 500 | DBG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); |
501 | if (rndis_per_dev_params [configNr].stats) { | 501 | if (rndis_per_dev_params [configNr].stats) { |
502 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 502 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
503 | .stats->multicast * 1111); | 503 | .stats->multicast * 1111); |
@@ -506,7 +506,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
506 | break; | 506 | break; |
507 | 507 | ||
508 | case OID_GEN_MULTICAST_FRAMES_RCV: | 508 | case OID_GEN_MULTICAST_FRAMES_RCV: |
509 | DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); | 509 | DBG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); |
510 | if (rndis_per_dev_params [configNr].stats) { | 510 | if (rndis_per_dev_params [configNr].stats) { |
511 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 511 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
512 | .stats->multicast); | 512 | .stats->multicast); |
@@ -515,7 +515,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
515 | break; | 515 | break; |
516 | 516 | ||
517 | case OID_GEN_BROADCAST_BYTES_RCV: | 517 | case OID_GEN_BROADCAST_BYTES_RCV: |
518 | DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); | 518 | DBG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); |
519 | if (rndis_per_dev_params [configNr].stats) { | 519 | if (rndis_per_dev_params [configNr].stats) { |
520 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 520 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
521 | .stats->rx_packets/42*255); | 521 | .stats->rx_packets/42*255); |
@@ -524,7 +524,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
524 | break; | 524 | break; |
525 | 525 | ||
526 | case OID_GEN_BROADCAST_FRAMES_RCV: | 526 | case OID_GEN_BROADCAST_FRAMES_RCV: |
527 | DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); | 527 | DBG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); |
528 | if (rndis_per_dev_params [configNr].stats) { | 528 | if (rndis_per_dev_params [configNr].stats) { |
529 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 529 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
530 | .stats->rx_packets/42); | 530 | .stats->rx_packets/42); |
@@ -533,7 +533,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
533 | break; | 533 | break; |
534 | 534 | ||
535 | case OID_GEN_RCV_CRC_ERROR: | 535 | case OID_GEN_RCV_CRC_ERROR: |
536 | DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); | 536 | DBG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); |
537 | if (rndis_per_dev_params [configNr].stats) { | 537 | if (rndis_per_dev_params [configNr].stats) { |
538 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 538 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
539 | .stats->rx_crc_errors); | 539 | .stats->rx_crc_errors); |
@@ -542,7 +542,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
542 | break; | 542 | break; |
543 | 543 | ||
544 | case OID_GEN_TRANSMIT_QUEUE_LENGTH: | 544 | case OID_GEN_TRANSMIT_QUEUE_LENGTH: |
545 | DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); | 545 | DBG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); |
546 | *outbuf = __constant_cpu_to_le32 (0); | 546 | *outbuf = __constant_cpu_to_le32 (0); |
547 | retval = 0; | 547 | retval = 0; |
548 | break; | 548 | break; |
@@ -552,7 +552,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
552 | 552 | ||
553 | /* mandatory */ | 553 | /* mandatory */ |
554 | case OID_802_3_PERMANENT_ADDRESS: | 554 | case OID_802_3_PERMANENT_ADDRESS: |
555 | DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__); | 555 | DBG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__); |
556 | if (rndis_per_dev_params [configNr].dev) { | 556 | if (rndis_per_dev_params [configNr].dev) { |
557 | length = ETH_ALEN; | 557 | length = ETH_ALEN; |
558 | memcpy (outbuf, | 558 | memcpy (outbuf, |
@@ -564,7 +564,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
564 | 564 | ||
565 | /* mandatory */ | 565 | /* mandatory */ |
566 | case OID_802_3_CURRENT_ADDRESS: | 566 | case OID_802_3_CURRENT_ADDRESS: |
567 | DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); | 567 | DBG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); |
568 | if (rndis_per_dev_params [configNr].dev) { | 568 | if (rndis_per_dev_params [configNr].dev) { |
569 | length = ETH_ALEN; | 569 | length = ETH_ALEN; |
570 | memcpy (outbuf, | 570 | memcpy (outbuf, |
@@ -576,7 +576,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
576 | 576 | ||
577 | /* mandatory */ | 577 | /* mandatory */ |
578 | case OID_802_3_MULTICAST_LIST: | 578 | case OID_802_3_MULTICAST_LIST: |
579 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); | 579 | DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); |
580 | /* Multicast base address only */ | 580 | /* Multicast base address only */ |
581 | *outbuf = __constant_cpu_to_le32 (0xE0000000); | 581 | *outbuf = __constant_cpu_to_le32 (0xE0000000); |
582 | retval = 0; | 582 | retval = 0; |
@@ -584,21 +584,21 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
584 | 584 | ||
585 | /* mandatory */ | 585 | /* mandatory */ |
586 | case OID_802_3_MAXIMUM_LIST_SIZE: | 586 | case OID_802_3_MAXIMUM_LIST_SIZE: |
587 | DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); | 587 | DBG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); |
588 | /* Multicast base address only */ | 588 | /* Multicast base address only */ |
589 | *outbuf = __constant_cpu_to_le32 (1); | 589 | *outbuf = __constant_cpu_to_le32 (1); |
590 | retval = 0; | 590 | retval = 0; |
591 | break; | 591 | break; |
592 | 592 | ||
593 | case OID_802_3_MAC_OPTIONS: | 593 | case OID_802_3_MAC_OPTIONS: |
594 | DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__); | 594 | DBG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__); |
595 | break; | 595 | break; |
596 | 596 | ||
597 | /* ieee802.3 statistics OIDs (table 4-4) */ | 597 | /* ieee802.3 statistics OIDs (table 4-4) */ |
598 | 598 | ||
599 | /* mandatory */ | 599 | /* mandatory */ |
600 | case OID_802_3_RCV_ERROR_ALIGNMENT: | 600 | case OID_802_3_RCV_ERROR_ALIGNMENT: |
601 | DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__); | 601 | DBG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__); |
602 | if (rndis_per_dev_params [configNr].stats) { | 602 | if (rndis_per_dev_params [configNr].stats) { |
603 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] | 603 | *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] |
604 | .stats->rx_frame_errors); | 604 | .stats->rx_frame_errors); |
@@ -608,51 +608,51 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
608 | 608 | ||
609 | /* mandatory */ | 609 | /* mandatory */ |
610 | case OID_802_3_XMIT_ONE_COLLISION: | 610 | case OID_802_3_XMIT_ONE_COLLISION: |
611 | DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); | 611 | DBG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); |
612 | *outbuf = __constant_cpu_to_le32 (0); | 612 | *outbuf = __constant_cpu_to_le32 (0); |
613 | retval = 0; | 613 | retval = 0; |
614 | break; | 614 | break; |
615 | 615 | ||
616 | /* mandatory */ | 616 | /* mandatory */ |
617 | case OID_802_3_XMIT_MORE_COLLISIONS: | 617 | case OID_802_3_XMIT_MORE_COLLISIONS: |
618 | DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); | 618 | DBG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); |
619 | *outbuf = __constant_cpu_to_le32 (0); | 619 | *outbuf = __constant_cpu_to_le32 (0); |
620 | retval = 0; | 620 | retval = 0; |
621 | break; | 621 | break; |
622 | 622 | ||
623 | #ifdef RNDIS_OPTIONAL_STATS | 623 | #ifdef RNDIS_OPTIONAL_STATS |
624 | case OID_802_3_XMIT_DEFERRED: | 624 | case OID_802_3_XMIT_DEFERRED: |
625 | DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__); | 625 | DBG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__); |
626 | /* TODO */ | 626 | /* TODO */ |
627 | break; | 627 | break; |
628 | 628 | ||
629 | case OID_802_3_XMIT_MAX_COLLISIONS: | 629 | case OID_802_3_XMIT_MAX_COLLISIONS: |
630 | DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__); | 630 | DBG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__); |
631 | /* TODO */ | 631 | /* TODO */ |
632 | break; | 632 | break; |
633 | 633 | ||
634 | case OID_802_3_RCV_OVERRUN: | 634 | case OID_802_3_RCV_OVERRUN: |
635 | DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__); | 635 | DBG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__); |
636 | /* TODO */ | 636 | /* TODO */ |
637 | break; | 637 | break; |
638 | 638 | ||
639 | case OID_802_3_XMIT_UNDERRUN: | 639 | case OID_802_3_XMIT_UNDERRUN: |
640 | DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__); | 640 | DBG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__); |
641 | /* TODO */ | 641 | /* TODO */ |
642 | break; | 642 | break; |
643 | 643 | ||
644 | case OID_802_3_XMIT_HEARTBEAT_FAILURE: | 644 | case OID_802_3_XMIT_HEARTBEAT_FAILURE: |
645 | DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__); | 645 | DBG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__); |
646 | /* TODO */ | 646 | /* TODO */ |
647 | break; | 647 | break; |
648 | 648 | ||
649 | case OID_802_3_XMIT_TIMES_CRS_LOST: | 649 | case OID_802_3_XMIT_TIMES_CRS_LOST: |
650 | DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__); | 650 | DBG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__); |
651 | /* TODO */ | 651 | /* TODO */ |
652 | break; | 652 | break; |
653 | 653 | ||
654 | case OID_802_3_XMIT_LATE_COLLISIONS: | 654 | case OID_802_3_XMIT_LATE_COLLISIONS: |
655 | DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__); | 655 | DBG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__); |
656 | /* TODO */ | 656 | /* TODO */ |
657 | break; | 657 | break; |
658 | #endif /* RNDIS_OPTIONAL_STATS */ | 658 | #endif /* RNDIS_OPTIONAL_STATS */ |
@@ -660,7 +660,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
660 | #ifdef RNDIS_PM | 660 | #ifdef RNDIS_PM |
661 | /* power management OIDs (table 4-5) */ | 661 | /* power management OIDs (table 4-5) */ |
662 | case OID_PNP_CAPABILITIES: | 662 | case OID_PNP_CAPABILITIES: |
663 | DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__); | 663 | DBG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__); |
664 | 664 | ||
665 | /* for now, no wakeup capabilities */ | 665 | /* for now, no wakeup capabilities */ |
666 | length = sizeof (struct NDIS_PNP_CAPABILITIES); | 666 | length = sizeof (struct NDIS_PNP_CAPABILITIES); |
@@ -668,7 +668,7 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len, | |||
668 | retval = 0; | 668 | retval = 0; |
669 | break; | 669 | break; |
670 | case OID_PNP_QUERY_POWER: | 670 | case OID_PNP_QUERY_POWER: |
671 | DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__, | 671 | DBG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__, |
672 | le32_to_cpu(get_unaligned((__le32 *)buf)) - 1); | 672 | le32_to_cpu(get_unaligned((__le32 *)buf)) - 1); |
673 | /* only suspend is a real power state, and | 673 | /* only suspend is a real power state, and |
674 | * it can't be entered by OID_PNP_SET_POWER... | 674 | * it can't be entered by OID_PNP_SET_POWER... |
@@ -705,9 +705,9 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, | |||
705 | return -ENOMEM; | 705 | return -ENOMEM; |
706 | 706 | ||
707 | if (buf_len && rndis_debug > 1) { | 707 | if (buf_len && rndis_debug > 1) { |
708 | DEBUG("set OID %08x value, len %d:\n", OID, buf_len); | 708 | DBG("set OID %08x value, len %d:\n", OID, buf_len); |
709 | for (i = 0; i < buf_len; i += 16) { | 709 | for (i = 0; i < buf_len; i += 16) { |
710 | DEBUG ("%03d: %08x %08x %08x %08x\n", i, | 710 | DBG("%03d: %08x %08x %08x %08x\n", i, |
711 | le32_to_cpu(get_unaligned((__le32 *) | 711 | le32_to_cpu(get_unaligned((__le32 *) |
712 | &buf[i])), | 712 | &buf[i])), |
713 | le32_to_cpu(get_unaligned((__le32 *) | 713 | le32_to_cpu(get_unaligned((__le32 *) |
@@ -731,7 +731,7 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, | |||
731 | */ | 731 | */ |
732 | *params->filter = (u16) le32_to_cpu(get_unaligned( | 732 | *params->filter = (u16) le32_to_cpu(get_unaligned( |
733 | (__le32 *)buf)); | 733 | (__le32 *)buf)); |
734 | DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", | 734 | DBG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", |
735 | __FUNCTION__, *params->filter); | 735 | __FUNCTION__, *params->filter); |
736 | 736 | ||
737 | /* this call has a significant side effect: it's | 737 | /* this call has a significant side effect: it's |
@@ -756,7 +756,7 @@ update_linkstate: | |||
756 | 756 | ||
757 | case OID_802_3_MULTICAST_LIST: | 757 | case OID_802_3_MULTICAST_LIST: |
758 | /* I think we can ignore this */ | 758 | /* I think we can ignore this */ |
759 | DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); | 759 | DBG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); |
760 | retval = 0; | 760 | retval = 0; |
761 | break; | 761 | break; |
762 | #if 0 | 762 | #if 0 |
@@ -764,7 +764,7 @@ update_linkstate: | |||
764 | { | 764 | { |
765 | struct rndis_config_parameter *param; | 765 | struct rndis_config_parameter *param; |
766 | param = (struct rndis_config_parameter *) buf; | 766 | param = (struct rndis_config_parameter *) buf; |
767 | DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n", | 767 | DBG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n", |
768 | __FUNCTION__, | 768 | __FUNCTION__, |
769 | min(cpu_to_le32(param->ParameterNameLength),80), | 769 | min(cpu_to_le32(param->ParameterNameLength),80), |
770 | buf + param->ParameterNameOffset); | 770 | buf + param->ParameterNameOffset); |
@@ -781,7 +781,7 @@ update_linkstate: | |||
781 | * FIXME ... then things go batty; Windows wedges itself. | 781 | * FIXME ... then things go batty; Windows wedges itself. |
782 | */ | 782 | */ |
783 | i = le32_to_cpu(get_unaligned((__le32 *)buf)); | 783 | i = le32_to_cpu(get_unaligned((__le32 *)buf)); |
784 | DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1); | 784 | DBG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1); |
785 | switch (i) { | 785 | switch (i) { |
786 | case NdisDeviceStateD0: | 786 | case NdisDeviceStateD0: |
787 | *params->filter = params->saved_filter; | 787 | *params->filter = params->saved_filter; |
@@ -858,7 +858,7 @@ static int rndis_query_response (int configNr, rndis_query_msg_type *buf) | |||
858 | rndis_query_cmplt_type *resp; | 858 | rndis_query_cmplt_type *resp; |
859 | rndis_resp_t *r; | 859 | rndis_resp_t *r; |
860 | 860 | ||
861 | // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID)); | 861 | // DBG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID)); |
862 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; | 862 | if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; |
863 | 863 | ||
864 | /* | 864 | /* |
@@ -911,15 +911,15 @@ static int rndis_set_response (int configNr, rndis_set_msg_type *buf) | |||
911 | BufOffset = le32_to_cpu (buf->InformationBufferOffset); | 911 | BufOffset = le32_to_cpu (buf->InformationBufferOffset); |
912 | 912 | ||
913 | #ifdef VERBOSE | 913 | #ifdef VERBOSE |
914 | DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength); | 914 | DBG("%s: Length: %d\n", __FUNCTION__, BufLength); |
915 | DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset); | 915 | DBG("%s: Offset: %d\n", __FUNCTION__, BufOffset); |
916 | DEBUG("%s: InfoBuffer: ", __FUNCTION__); | 916 | DBG("%s: InfoBuffer: ", __FUNCTION__); |
917 | 917 | ||
918 | for (i = 0; i < BufLength; i++) { | 918 | for (i = 0; i < BufLength; i++) { |
919 | DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); | 919 | DBG("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); |
920 | } | 920 | } |
921 | 921 | ||
922 | DEBUG ("\n"); | 922 | DBG("\n"); |
923 | #endif | 923 | #endif |
924 | 924 | ||
925 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); | 925 | resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); |
@@ -1082,14 +1082,14 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1082 | /* For USB: responses may take up to 10 seconds */ | 1082 | /* For USB: responses may take up to 10 seconds */ |
1083 | switch (MsgType) { | 1083 | switch (MsgType) { |
1084 | case REMOTE_NDIS_INITIALIZE_MSG: | 1084 | case REMOTE_NDIS_INITIALIZE_MSG: |
1085 | DEBUG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", | 1085 | DBG("%s: REMOTE_NDIS_INITIALIZE_MSG\n", |
1086 | __FUNCTION__ ); | 1086 | __FUNCTION__ ); |
1087 | params->state = RNDIS_INITIALIZED; | 1087 | params->state = RNDIS_INITIALIZED; |
1088 | return rndis_init_response (configNr, | 1088 | return rndis_init_response (configNr, |
1089 | (rndis_init_msg_type *) buf); | 1089 | (rndis_init_msg_type *) buf); |
1090 | 1090 | ||
1091 | case REMOTE_NDIS_HALT_MSG: | 1091 | case REMOTE_NDIS_HALT_MSG: |
1092 | DEBUG("%s: REMOTE_NDIS_HALT_MSG\n", | 1092 | DBG("%s: REMOTE_NDIS_HALT_MSG\n", |
1093 | __FUNCTION__ ); | 1093 | __FUNCTION__ ); |
1094 | params->state = RNDIS_UNINITIALIZED; | 1094 | params->state = RNDIS_UNINITIALIZED; |
1095 | if (params->dev) { | 1095 | if (params->dev) { |
@@ -1107,7 +1107,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1107 | (rndis_set_msg_type *) buf); | 1107 | (rndis_set_msg_type *) buf); |
1108 | 1108 | ||
1109 | case REMOTE_NDIS_RESET_MSG: | 1109 | case REMOTE_NDIS_RESET_MSG: |
1110 | DEBUG("%s: REMOTE_NDIS_RESET_MSG\n", | 1110 | DBG("%s: REMOTE_NDIS_RESET_MSG\n", |
1111 | __FUNCTION__ ); | 1111 | __FUNCTION__ ); |
1112 | return rndis_reset_response (configNr, | 1112 | return rndis_reset_response (configNr, |
1113 | (rndis_reset_msg_type *) buf); | 1113 | (rndis_reset_msg_type *) buf); |
@@ -1115,7 +1115,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1115 | case REMOTE_NDIS_KEEPALIVE_MSG: | 1115 | case REMOTE_NDIS_KEEPALIVE_MSG: |
1116 | /* For USB: host does this every 5 seconds */ | 1116 | /* For USB: host does this every 5 seconds */ |
1117 | if (rndis_debug > 1) | 1117 | if (rndis_debug > 1) |
1118 | DEBUG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", | 1118 | DBG("%s: REMOTE_NDIS_KEEPALIVE_MSG\n", |
1119 | __FUNCTION__ ); | 1119 | __FUNCTION__ ); |
1120 | return rndis_keepalive_response (configNr, | 1120 | return rndis_keepalive_response (configNr, |
1121 | (rndis_keepalive_msg_type *) | 1121 | (rndis_keepalive_msg_type *) |
@@ -1132,7 +1132,7 @@ int rndis_msg_parser (u8 configNr, u8 *buf) | |||
1132 | { | 1132 | { |
1133 | unsigned i; | 1133 | unsigned i; |
1134 | for (i = 0; i < MsgLength; i += 16) { | 1134 | for (i = 0; i < MsgLength; i += 16) { |
1135 | DEBUG ("%03d: " | 1135 | DBG("%03d: " |
1136 | " %02x %02x %02x %02x" | 1136 | " %02x %02x %02x %02x" |
1137 | " %02x %02x %02x %02x" | 1137 | " %02x %02x %02x %02x" |
1138 | " %02x %02x %02x %02x" | 1138 | " %02x %02x %02x %02x" |
@@ -1163,18 +1163,18 @@ int rndis_register (int (* rndis_control_ack) (struct net_device *)) | |||
1163 | if (!rndis_per_dev_params [i].used) { | 1163 | if (!rndis_per_dev_params [i].used) { |
1164 | rndis_per_dev_params [i].used = 1; | 1164 | rndis_per_dev_params [i].used = 1; |
1165 | rndis_per_dev_params [i].ack = rndis_control_ack; | 1165 | rndis_per_dev_params [i].ack = rndis_control_ack; |
1166 | DEBUG("%s: configNr = %d\n", __FUNCTION__, i); | 1166 | DBG("%s: configNr = %d\n", __FUNCTION__, i); |
1167 | return i; | 1167 | return i; |
1168 | } | 1168 | } |
1169 | } | 1169 | } |
1170 | DEBUG("failed\n"); | 1170 | DBG("failed\n"); |
1171 | 1171 | ||
1172 | return -1; | 1172 | return -1; |
1173 | } | 1173 | } |
1174 | 1174 | ||
1175 | void rndis_deregister (int configNr) | 1175 | void rndis_deregister (int configNr) |
1176 | { | 1176 | { |
1177 | DEBUG("%s: \n", __FUNCTION__ ); | 1177 | DBG("%s: \n", __FUNCTION__ ); |
1178 | 1178 | ||
1179 | if (configNr >= RNDIS_MAX_CONFIGS) return; | 1179 | if (configNr >= RNDIS_MAX_CONFIGS) return; |
1180 | rndis_per_dev_params [configNr].used = 0; | 1180 | rndis_per_dev_params [configNr].used = 0; |
@@ -1186,7 +1186,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev, | |||
1186 | struct net_device_stats *stats, | 1186 | struct net_device_stats *stats, |
1187 | u16 *cdc_filter) | 1187 | u16 *cdc_filter) |
1188 | { | 1188 | { |
1189 | DEBUG("%s:\n", __FUNCTION__ ); | 1189 | DBG("%s:\n", __FUNCTION__ ); |
1190 | if (!dev || !stats) return -1; | 1190 | if (!dev || !stats) return -1; |
1191 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; | 1191 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; |
1192 | 1192 | ||
@@ -1199,7 +1199,7 @@ int rndis_set_param_dev (u8 configNr, struct net_device *dev, | |||
1199 | 1199 | ||
1200 | int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) | 1200 | int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) |
1201 | { | 1201 | { |
1202 | DEBUG("%s:\n", __FUNCTION__ ); | 1202 | DBG("%s:\n", __FUNCTION__ ); |
1203 | if (!vendorDescr) return -1; | 1203 | if (!vendorDescr) return -1; |
1204 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; | 1204 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; |
1205 | 1205 | ||
@@ -1211,7 +1211,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr) | |||
1211 | 1211 | ||
1212 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) | 1212 | int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed) |
1213 | { | 1213 | { |
1214 | DEBUG("%s: %u %u\n", __FUNCTION__, medium, speed); | 1214 | DBG("%s: %u %u\n", __FUNCTION__, medium, speed); |
1215 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; | 1215 | if (configNr >= RNDIS_MAX_CONFIGS) return -1; |
1216 | 1216 | ||
1217 | rndis_per_dev_params [configNr].medium = medium; | 1217 | rndis_per_dev_params [configNr].medium = medium; |
@@ -1390,7 +1390,7 @@ static int rndis_proc_write (struct file *file, const char __user *buffer, | |||
1390 | break; | 1390 | break; |
1391 | default: | 1391 | default: |
1392 | if (fl_speed) p->speed = speed; | 1392 | if (fl_speed) p->speed = speed; |
1393 | else DEBUG ("%c is not valid\n", c); | 1393 | else DBG("%c is not valid\n", c); |
1394 | break; | 1394 | break; |
1395 | } | 1395 | } |
1396 | 1396 | ||
@@ -1419,12 +1419,12 @@ int __devinit rndis_init (void) | |||
1419 | if (!(rndis_connect_state [i] | 1419 | if (!(rndis_connect_state [i] |
1420 | = create_proc_entry (name, 0660, NULL))) | 1420 | = create_proc_entry (name, 0660, NULL))) |
1421 | { | 1421 | { |
1422 | DEBUG ("%s :remove entries", __FUNCTION__); | 1422 | DBG("%s :remove entries", __FUNCTION__); |
1423 | while (i) { | 1423 | while (i) { |
1424 | sprintf (name, NAME_TEMPLATE, --i); | 1424 | sprintf (name, NAME_TEMPLATE, --i); |
1425 | remove_proc_entry (name, NULL); | 1425 | remove_proc_entry (name, NULL); |
1426 | } | 1426 | } |
1427 | DEBUG ("\n"); | 1427 | DBG("\n"); |
1428 | return -EIO; | 1428 | return -EIO; |
1429 | } | 1429 | } |
1430 | 1430 | ||
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c new file mode 100644 index 000000000000..0be80c635c48 --- /dev/null +++ b/drivers/usb/gadget/s3c2410_udc.c | |||
@@ -0,0 +1,2045 @@ | |||
1 | /* | ||
2 | * linux/drivers/usb/gadget/s3c2410_udc.c | ||
3 | * | ||
4 | * Samsung S3C24xx series on-chip full speed USB device controllers | ||
5 | * | ||
6 | * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard | ||
7 | * Additional cleanups by Ben Dooks <ben-linux@fluff.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/module.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/ioport.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/smp_lock.h> | ||
32 | #include <linux/errno.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <linux/timer.h> | ||
35 | #include <linux/list.h> | ||
36 | #include <linux/interrupt.h> | ||
37 | #include <linux/platform_device.h> | ||
38 | #include <linux/version.h> | ||
39 | #include <linux/clk.h> | ||
40 | |||
41 | #include <linux/debugfs.h> | ||
42 | #include <linux/seq_file.h> | ||
43 | |||
44 | #include <linux/usb.h> | ||
45 | #include <linux/usb_gadget.h> | ||
46 | |||
47 | #include <asm/byteorder.h> | ||
48 | #include <asm/io.h> | ||
49 | #include <asm/irq.h> | ||
50 | #include <asm/system.h> | ||
51 | #include <asm/unaligned.h> | ||
52 | #include <asm/arch/irqs.h> | ||
53 | |||
54 | #include <asm/arch/hardware.h> | ||
55 | #include <asm/arch/regs-clock.h> | ||
56 | #include <asm/arch/regs-gpio.h> | ||
57 | #include <asm/arch/regs-udc.h> | ||
58 | #include <asm/arch/udc.h> | ||
59 | |||
60 | #include <asm/mach-types.h> | ||
61 | |||
62 | #include "s3c2410_udc.h" | ||
63 | |||
64 | #define DRIVER_DESC "S3C2410 USB Device Controller Gadget" | ||
65 | #define DRIVER_VERSION "29 Apr 2007" | ||
66 | #define DRIVER_AUTHOR "Herbert Pötzl <herbert@13thfloor.at>, " \ | ||
67 | "Arnaud Patard <arnaud.patard@rtp-net.org>" | ||
68 | |||
69 | static const char gadget_name[] = "s3c2410_udc"; | ||
70 | static const char driver_desc[] = DRIVER_DESC; | ||
71 | |||
72 | static struct s3c2410_udc *the_controller; | ||
73 | static struct clk *udc_clock; | ||
74 | static struct clk *usb_bus_clock; | ||
75 | static void __iomem *base_addr; | ||
76 | static u64 rsrc_start; | ||
77 | static u64 rsrc_len; | ||
78 | static struct dentry *s3c2410_udc_debugfs_root; | ||
79 | |||
80 | static inline u32 udc_read(u32 reg) | ||
81 | { | ||
82 | return readb(base_addr + reg); | ||
83 | } | ||
84 | |||
85 | static inline void udc_write(u32 value, u32 reg) | ||
86 | { | ||
87 | writeb(value, base_addr + reg); | ||
88 | } | ||
89 | |||
90 | static inline void udc_writeb(void __iomem *base, u32 value, u32 reg) | ||
91 | { | ||
92 | writeb(value, base + reg); | ||
93 | } | ||
94 | |||
95 | static struct s3c2410_udc_mach_info *udc_info; | ||
96 | |||
97 | /*************************** DEBUG FUNCTION ***************************/ | ||
98 | #define DEBUG_NORMAL 1 | ||
99 | #define DEBUG_VERBOSE 2 | ||
100 | |||
101 | #ifdef CONFIG_USB_S3C2410_DEBUG | ||
102 | #define USB_S3C2410_DEBUG_LEVEL 0 | ||
103 | |||
104 | static uint32_t s3c2410_ticks = 0; | ||
105 | |||
106 | static int dprintk(int level, const char *fmt, ...) | ||
107 | { | ||
108 | static char printk_buf[1024]; | ||
109 | static long prevticks; | ||
110 | static int invocation; | ||
111 | va_list args; | ||
112 | int len; | ||
113 | |||
114 | if (level > USB_S3C2410_DEBUG_LEVEL) | ||
115 | return 0; | ||
116 | |||
117 | if (s3c2410_ticks != prevticks) { | ||
118 | prevticks = s3c2410_ticks; | ||
119 | invocation = 0; | ||
120 | } | ||
121 | |||
122 | len = scnprintf(printk_buf, | ||
123 | sizeof(printk_buf), "%1lu.%02d USB: ", | ||
124 | prevticks, invocation++); | ||
125 | |||
126 | va_start(args, fmt); | ||
127 | len = vscnprintf(printk_buf+len, | ||
128 | sizeof(printk_buf)-len, fmt, args); | ||
129 | va_end(args); | ||
130 | |||
131 | return printk(KERN_DEBUG "%s", printk_buf); | ||
132 | } | ||
133 | #else | ||
134 | static int dprintk(int level, const char *fmt, ...) | ||
135 | { | ||
136 | return 0; | ||
137 | } | ||
138 | #endif | ||
139 | static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p) | ||
140 | { | ||
141 | u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg; | ||
142 | u32 ep_int_en_reg, usb_int_en_reg, ep0_csr; | ||
143 | u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2; | ||
144 | u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2; | ||
145 | |||
146 | addr_reg = udc_read(S3C2410_UDC_FUNC_ADDR_REG); | ||
147 | pwr_reg = udc_read(S3C2410_UDC_PWR_REG); | ||
148 | ep_int_reg = udc_read(S3C2410_UDC_EP_INT_REG); | ||
149 | usb_int_reg = udc_read(S3C2410_UDC_USB_INT_REG); | ||
150 | ep_int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG); | ||
151 | usb_int_en_reg = udc_read(S3C2410_UDC_USB_INT_EN_REG); | ||
152 | udc_write(0, S3C2410_UDC_INDEX_REG); | ||
153 | ep0_csr = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
154 | udc_write(1, S3C2410_UDC_INDEX_REG); | ||
155 | ep1_i_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
156 | ep1_i_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG); | ||
157 | ep1_o_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
158 | ep1_o_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG); | ||
159 | udc_write(2, S3C2410_UDC_INDEX_REG); | ||
160 | ep2_i_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
161 | ep2_i_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG); | ||
162 | ep2_o_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
163 | ep2_o_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG); | ||
164 | |||
165 | seq_printf(m, "FUNC_ADDR_REG : 0x%04X\n" | ||
166 | "PWR_REG : 0x%04X\n" | ||
167 | "EP_INT_REG : 0x%04X\n" | ||
168 | "USB_INT_REG : 0x%04X\n" | ||
169 | "EP_INT_EN_REG : 0x%04X\n" | ||
170 | "USB_INT_EN_REG : 0x%04X\n" | ||
171 | "EP0_CSR : 0x%04X\n" | ||
172 | "EP1_I_CSR1 : 0x%04X\n" | ||
173 | "EP1_I_CSR2 : 0x%04X\n" | ||
174 | "EP1_O_CSR1 : 0x%04X\n" | ||
175 | "EP1_O_CSR2 : 0x%04X\n" | ||
176 | "EP2_I_CSR1 : 0x%04X\n" | ||
177 | "EP2_I_CSR2 : 0x%04X\n" | ||
178 | "EP2_O_CSR1 : 0x%04X\n" | ||
179 | "EP2_O_CSR2 : 0x%04X\n", | ||
180 | addr_reg,pwr_reg,ep_int_reg,usb_int_reg, | ||
181 | ep_int_en_reg, usb_int_en_reg, ep0_csr, | ||
182 | ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2, | ||
183 | ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2 | ||
184 | ); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int s3c2410_udc_debugfs_fops_open(struct inode *inode, | ||
190 | struct file *file) | ||
191 | { | ||
192 | return single_open(file, s3c2410_udc_debugfs_seq_show, NULL); | ||
193 | } | ||
194 | |||
195 | static const struct file_operations s3c2410_udc_debugfs_fops = { | ||
196 | .open = s3c2410_udc_debugfs_fops_open, | ||
197 | .read = seq_read, | ||
198 | .llseek = seq_lseek, | ||
199 | .release = single_release, | ||
200 | .owner = THIS_MODULE, | ||
201 | }; | ||
202 | |||
203 | /* io macros */ | ||
204 | |||
205 | static inline void s3c2410_udc_clear_ep0_opr(void __iomem *base) | ||
206 | { | ||
207 | udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
208 | udc_writeb(base, S3C2410_UDC_EP0_CSR_SOPKTRDY, | ||
209 | S3C2410_UDC_EP0_CSR_REG); | ||
210 | } | ||
211 | |||
212 | static inline void s3c2410_udc_clear_ep0_sst(void __iomem *base) | ||
213 | { | ||
214 | udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
215 | writeb(0x00, base + S3C2410_UDC_EP0_CSR_REG); | ||
216 | } | ||
217 | |||
218 | static inline void s3c2410_udc_clear_ep0_se(void __iomem *base) | ||
219 | { | ||
220 | udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
221 | udc_writeb(base, S3C2410_UDC_EP0_CSR_SSE, S3C2410_UDC_EP0_CSR_REG); | ||
222 | } | ||
223 | |||
224 | static inline void s3c2410_udc_set_ep0_ipr(void __iomem *base) | ||
225 | { | ||
226 | udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
227 | udc_writeb(base, S3C2410_UDC_EP0_CSR_IPKRDY, S3C2410_UDC_EP0_CSR_REG); | ||
228 | } | ||
229 | |||
230 | static inline void s3c2410_udc_set_ep0_de(void __iomem *base) | ||
231 | { | ||
232 | udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
233 | udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG); | ||
234 | } | ||
235 | |||
236 | inline void s3c2410_udc_set_ep0_ss(void __iomem *b) | ||
237 | { | ||
238 | udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
239 | udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG); | ||
240 | } | ||
241 | |||
242 | static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base) | ||
243 | { | ||
244 | udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
245 | |||
246 | udc_writeb(base,(S3C2410_UDC_EP0_CSR_SOPKTRDY | ||
247 | | S3C2410_UDC_EP0_CSR_DE), | ||
248 | S3C2410_UDC_EP0_CSR_REG); | ||
249 | } | ||
250 | |||
251 | static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base) | ||
252 | { | ||
253 | udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
254 | udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY | ||
255 | | S3C2410_UDC_EP0_CSR_SSE), | ||
256 | S3C2410_UDC_EP0_CSR_REG); | ||
257 | } | ||
258 | |||
259 | static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base) | ||
260 | { | ||
261 | udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
262 | udc_writeb(base, (S3C2410_UDC_EP0_CSR_IPKRDY | ||
263 | | S3C2410_UDC_EP0_CSR_DE), | ||
264 | S3C2410_UDC_EP0_CSR_REG); | ||
265 | } | ||
266 | |||
267 | /*------------------------- I/O ----------------------------------*/ | ||
268 | |||
269 | /* | ||
270 | * s3c2410_udc_done | ||
271 | */ | ||
272 | static void s3c2410_udc_done(struct s3c2410_ep *ep, | ||
273 | struct s3c2410_request *req, int status) | ||
274 | { | ||
275 | unsigned halted = ep->halted; | ||
276 | |||
277 | list_del_init(&req->queue); | ||
278 | |||
279 | if (likely (req->req.status == -EINPROGRESS)) | ||
280 | req->req.status = status; | ||
281 | else | ||
282 | status = req->req.status; | ||
283 | |||
284 | ep->halted = 1; | ||
285 | req->req.complete(&ep->ep, &req->req); | ||
286 | ep->halted = halted; | ||
287 | } | ||
288 | |||
289 | static void s3c2410_udc_nuke(struct s3c2410_udc *udc, | ||
290 | struct s3c2410_ep *ep, int status) | ||
291 | { | ||
292 | /* Sanity check */ | ||
293 | if (&ep->queue == NULL) | ||
294 | return; | ||
295 | |||
296 | while (!list_empty (&ep->queue)) { | ||
297 | struct s3c2410_request *req; | ||
298 | req = list_entry (ep->queue.next, struct s3c2410_request, | ||
299 | queue); | ||
300 | s3c2410_udc_done(ep, req, status); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev) | ||
305 | { | ||
306 | unsigned i; | ||
307 | |||
308 | /* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint | ||
309 | * fifos, and pending transactions mustn't be continued in any case. | ||
310 | */ | ||
311 | |||
312 | for (i = 1; i < S3C2410_ENDPOINTS; i++) | ||
313 | s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED); | ||
314 | } | ||
315 | |||
316 | static inline int s3c2410_udc_fifo_count_out(void) | ||
317 | { | ||
318 | int tmp; | ||
319 | |||
320 | tmp = udc_read(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8; | ||
321 | tmp |= udc_read(S3C2410_UDC_OUT_FIFO_CNT1_REG); | ||
322 | return tmp; | ||
323 | } | ||
324 | |||
325 | /* | ||
326 | * s3c2410_udc_write_packet | ||
327 | */ | ||
328 | static inline int s3c2410_udc_write_packet(int fifo, | ||
329 | struct s3c2410_request *req, | ||
330 | unsigned max) | ||
331 | { | ||
332 | unsigned len = min(req->req.length - req->req.actual, max); | ||
333 | u8 *buf = req->req.buf + req->req.actual; | ||
334 | |||
335 | prefetch(buf); | ||
336 | |||
337 | dprintk(DEBUG_VERBOSE, "%s %d %d %d %d\n", __func__, | ||
338 | req->req.actual, req->req.length, len, req->req.actual + len); | ||
339 | |||
340 | req->req.actual += len; | ||
341 | |||
342 | udelay(5); | ||
343 | writesb(base_addr + fifo, buf, len); | ||
344 | return len; | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * s3c2410_udc_write_fifo | ||
349 | * | ||
350 | * return: 0 = still running, 1 = completed, negative = errno | ||
351 | */ | ||
352 | static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep, | ||
353 | struct s3c2410_request *req) | ||
354 | { | ||
355 | unsigned count; | ||
356 | int is_last; | ||
357 | u32 idx; | ||
358 | int fifo_reg; | ||
359 | u32 ep_csr; | ||
360 | |||
361 | idx = ep->bEndpointAddress & 0x7F; | ||
362 | switch (idx) { | ||
363 | default: | ||
364 | idx = 0; | ||
365 | case 0: | ||
366 | fifo_reg = S3C2410_UDC_EP0_FIFO_REG; | ||
367 | break; | ||
368 | case 1: | ||
369 | fifo_reg = S3C2410_UDC_EP1_FIFO_REG; | ||
370 | break; | ||
371 | case 2: | ||
372 | fifo_reg = S3C2410_UDC_EP2_FIFO_REG; | ||
373 | break; | ||
374 | case 3: | ||
375 | fifo_reg = S3C2410_UDC_EP3_FIFO_REG; | ||
376 | break; | ||
377 | case 4: | ||
378 | fifo_reg = S3C2410_UDC_EP4_FIFO_REG; | ||
379 | break; | ||
380 | } | ||
381 | |||
382 | count = s3c2410_udc_write_packet(fifo_reg, req, ep->ep.maxpacket); | ||
383 | |||
384 | /* last packet is often short (sometimes a zlp) */ | ||
385 | if (count != ep->ep.maxpacket) | ||
386 | is_last = 1; | ||
387 | else if (req->req.length != req->req.actual || req->req.zero) | ||
388 | is_last = 0; | ||
389 | else | ||
390 | is_last = 2; | ||
391 | |||
392 | /* Only ep0 debug messages are interesting */ | ||
393 | if (idx == 0) | ||
394 | dprintk(DEBUG_NORMAL, | ||
395 | "Written ep%d %d.%d of %d b [last %d,z %d]\n", | ||
396 | idx, count, req->req.actual, req->req.length, | ||
397 | is_last, req->req.zero); | ||
398 | |||
399 | if (is_last) { | ||
400 | /* The order is important. It prevents sending 2 packets | ||
401 | * at the same time */ | ||
402 | |||
403 | if (idx == 0) { | ||
404 | /* Reset signal => no need to say 'data sent' */ | ||
405 | if (! (udc_read(S3C2410_UDC_USB_INT_REG) | ||
406 | & S3C2410_UDC_USBINT_RESET)) | ||
407 | s3c2410_udc_set_ep0_de_in(base_addr); | ||
408 | ep->dev->ep0state=EP0_IDLE; | ||
409 | } else { | ||
410 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
411 | ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
412 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
413 | udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY, | ||
414 | S3C2410_UDC_IN_CSR1_REG); | ||
415 | } | ||
416 | |||
417 | s3c2410_udc_done(ep, req, 0); | ||
418 | is_last = 1; | ||
419 | } else { | ||
420 | if (idx == 0) { | ||
421 | /* Reset signal => no need to say 'data sent' */ | ||
422 | if (! (udc_read(S3C2410_UDC_USB_INT_REG) | ||
423 | & S3C2410_UDC_USBINT_RESET)) | ||
424 | s3c2410_udc_set_ep0_ipr(base_addr); | ||
425 | } else { | ||
426 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
427 | ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
428 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
429 | udc_write(ep_csr | S3C2410_UDC_ICSR1_PKTRDY, | ||
430 | S3C2410_UDC_IN_CSR1_REG); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | return is_last; | ||
435 | } | ||
436 | |||
437 | static inline int s3c2410_udc_read_packet(int fifo, u8 *buf, | ||
438 | struct s3c2410_request *req, unsigned avail) | ||
439 | { | ||
440 | unsigned len; | ||
441 | |||
442 | len = min(req->req.length - req->req.actual, avail); | ||
443 | req->req.actual += len; | ||
444 | |||
445 | readsb(fifo + base_addr, buf, len); | ||
446 | return len; | ||
447 | } | ||
448 | |||
449 | /* | ||
450 | * return: 0 = still running, 1 = queue empty, negative = errno | ||
451 | */ | ||
452 | static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, | ||
453 | struct s3c2410_request *req) | ||
454 | { | ||
455 | u8 *buf; | ||
456 | u32 ep_csr; | ||
457 | unsigned bufferspace; | ||
458 | int is_last=1; | ||
459 | unsigned avail; | ||
460 | int fifo_count = 0; | ||
461 | u32 idx; | ||
462 | int fifo_reg; | ||
463 | |||
464 | idx = ep->bEndpointAddress & 0x7F; | ||
465 | |||
466 | switch (idx) { | ||
467 | default: | ||
468 | idx = 0; | ||
469 | case 0: | ||
470 | fifo_reg = S3C2410_UDC_EP0_FIFO_REG; | ||
471 | break; | ||
472 | case 1: | ||
473 | fifo_reg = S3C2410_UDC_EP1_FIFO_REG; | ||
474 | break; | ||
475 | case 2: | ||
476 | fifo_reg = S3C2410_UDC_EP2_FIFO_REG; | ||
477 | break; | ||
478 | case 3: | ||
479 | fifo_reg = S3C2410_UDC_EP3_FIFO_REG; | ||
480 | break; | ||
481 | case 4: | ||
482 | fifo_reg = S3C2410_UDC_EP4_FIFO_REG; | ||
483 | break; | ||
484 | } | ||
485 | |||
486 | if (!req->req.length) | ||
487 | return 1; | ||
488 | |||
489 | buf = req->req.buf + req->req.actual; | ||
490 | bufferspace = req->req.length - req->req.actual; | ||
491 | if (!bufferspace) { | ||
492 | dprintk(DEBUG_NORMAL, "%s: buffer full!\n", __func__); | ||
493 | return -1; | ||
494 | } | ||
495 | |||
496 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
497 | |||
498 | fifo_count = s3c2410_udc_fifo_count_out(); | ||
499 | dprintk(DEBUG_NORMAL, "%s fifo count : %d\n", __func__, fifo_count); | ||
500 | |||
501 | if (fifo_count > ep->ep.maxpacket) | ||
502 | avail = ep->ep.maxpacket; | ||
503 | else | ||
504 | avail = fifo_count; | ||
505 | |||
506 | fifo_count = s3c2410_udc_read_packet(fifo_reg, buf, req, avail); | ||
507 | |||
508 | /* checking this with ep0 is not accurate as we already | ||
509 | * read a control request | ||
510 | **/ | ||
511 | if (idx != 0 && fifo_count < ep->ep.maxpacket) { | ||
512 | is_last = 1; | ||
513 | /* overflowed this request? flush extra data */ | ||
514 | if (fifo_count != avail) | ||
515 | req->req.status = -EOVERFLOW; | ||
516 | } else { | ||
517 | is_last = (req->req.length <= req->req.actual) ? 1 : 0; | ||
518 | } | ||
519 | |||
520 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
521 | fifo_count = s3c2410_udc_fifo_count_out(); | ||
522 | |||
523 | /* Only ep0 debug messages are interesting */ | ||
524 | if (idx == 0) | ||
525 | dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n", | ||
526 | __func__, fifo_count,is_last); | ||
527 | |||
528 | if (is_last) { | ||
529 | if (idx == 0) { | ||
530 | s3c2410_udc_set_ep0_de_out(base_addr); | ||
531 | ep->dev->ep0state = EP0_IDLE; | ||
532 | } else { | ||
533 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
534 | ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG); | ||
535 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
536 | udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY, | ||
537 | S3C2410_UDC_OUT_CSR1_REG); | ||
538 | } | ||
539 | |||
540 | s3c2410_udc_done(ep, req, 0); | ||
541 | } else { | ||
542 | if (idx == 0) { | ||
543 | s3c2410_udc_clear_ep0_opr(base_addr); | ||
544 | } else { | ||
545 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
546 | ep_csr = udc_read(S3C2410_UDC_OUT_CSR1_REG); | ||
547 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
548 | udc_write(ep_csr & ~S3C2410_UDC_OCSR1_PKTRDY, | ||
549 | S3C2410_UDC_OUT_CSR1_REG); | ||
550 | } | ||
551 | } | ||
552 | |||
553 | return is_last; | ||
554 | } | ||
555 | |||
556 | static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq) | ||
557 | { | ||
558 | unsigned char *outbuf = (unsigned char*)crq; | ||
559 | int bytes_read = 0; | ||
560 | |||
561 | udc_write(0, S3C2410_UDC_INDEX_REG); | ||
562 | |||
563 | bytes_read = s3c2410_udc_fifo_count_out(); | ||
564 | |||
565 | dprintk(DEBUG_NORMAL, "%s: fifo_count=%d\n", __func__, bytes_read); | ||
566 | |||
567 | if (bytes_read > sizeof(struct usb_ctrlrequest)) | ||
568 | bytes_read = sizeof(struct usb_ctrlrequest); | ||
569 | |||
570 | readsb(S3C2410_UDC_EP0_FIFO_REG + base_addr, outbuf, bytes_read); | ||
571 | |||
572 | dprintk(DEBUG_VERBOSE, "%s: len=%d %02x:%02x {%x,%x,%x}\n", __func__, | ||
573 | bytes_read, crq->bRequest, crq->bRequestType, | ||
574 | crq->wValue, crq->wIndex, crq->wLength); | ||
575 | |||
576 | return bytes_read; | ||
577 | } | ||
578 | |||
579 | static int s3c2410_udc_get_status(struct s3c2410_udc *dev, | ||
580 | struct usb_ctrlrequest *crq) | ||
581 | { | ||
582 | u16 status = 0; | ||
583 | u8 ep_num = crq->wIndex & 0x7F; | ||
584 | u8 is_in = crq->wIndex & USB_DIR_IN; | ||
585 | |||
586 | switch (crq->bRequestType & USB_RECIP_MASK) { | ||
587 | case USB_RECIP_INTERFACE: | ||
588 | break; | ||
589 | |||
590 | case USB_RECIP_DEVICE: | ||
591 | status = dev->devstatus; | ||
592 | break; | ||
593 | |||
594 | case USB_RECIP_ENDPOINT: | ||
595 | if (ep_num > 4 || crq->wLength > 2) | ||
596 | return 1; | ||
597 | |||
598 | if (ep_num == 0) { | ||
599 | udc_write(0, S3C2410_UDC_INDEX_REG); | ||
600 | status = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
601 | status = status & S3C2410_UDC_EP0_CSR_SENDSTL; | ||
602 | } else { | ||
603 | udc_write(ep_num, S3C2410_UDC_INDEX_REG); | ||
604 | if (is_in) { | ||
605 | status = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
606 | status = status & S3C2410_UDC_ICSR1_SENDSTL; | ||
607 | } else { | ||
608 | status = udc_read(S3C2410_UDC_OUT_CSR1_REG); | ||
609 | status = status & S3C2410_UDC_OCSR1_SENDSTL; | ||
610 | } | ||
611 | } | ||
612 | |||
613 | status = status ? 1 : 0; | ||
614 | break; | ||
615 | |||
616 | default: | ||
617 | return 1; | ||
618 | } | ||
619 | |||
620 | /* Seems to be needed to get it working. ouch :( */ | ||
621 | udelay(5); | ||
622 | udc_write(status & 0xFF, S3C2410_UDC_EP0_FIFO_REG); | ||
623 | udc_write(status >> 8, S3C2410_UDC_EP0_FIFO_REG); | ||
624 | s3c2410_udc_set_ep0_de_in(base_addr); | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | /*------------------------- usb state machine -------------------------------*/ | ||
629 | static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value); | ||
630 | |||
631 | static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev, | ||
632 | struct s3c2410_ep *ep, | ||
633 | struct usb_ctrlrequest *crq, | ||
634 | u32 ep0csr) | ||
635 | { | ||
636 | int len, ret, tmp; | ||
637 | |||
638 | /* start control request? */ | ||
639 | if (!(ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY)) | ||
640 | return; | ||
641 | |||
642 | s3c2410_udc_nuke(dev, ep, -EPROTO); | ||
643 | |||
644 | len = s3c2410_udc_read_fifo_crq(crq); | ||
645 | if (len != sizeof(*crq)) { | ||
646 | dprintk(DEBUG_NORMAL, "setup begin: fifo READ ERROR" | ||
647 | " wanted %d bytes got %d. Stalling out...\n", | ||
648 | sizeof(*crq), len); | ||
649 | s3c2410_udc_set_ep0_ss(base_addr); | ||
650 | return; | ||
651 | } | ||
652 | |||
653 | dprintk(DEBUG_NORMAL, "bRequest = %d bRequestType %d wLength = %d\n", | ||
654 | crq->bRequest, crq->bRequestType, crq->wLength); | ||
655 | |||
656 | /* cope with automagic for some standard requests. */ | ||
657 | dev->req_std = (crq->bRequestType & USB_TYPE_MASK) | ||
658 | == USB_TYPE_STANDARD; | ||
659 | dev->req_config = 0; | ||
660 | dev->req_pending = 1; | ||
661 | |||
662 | switch (crq->bRequest) { | ||
663 | case USB_REQ_SET_CONFIGURATION: | ||
664 | dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ... \n"); | ||
665 | |||
666 | if (crq->bRequestType == USB_RECIP_DEVICE) { | ||
667 | dev->req_config = 1; | ||
668 | s3c2410_udc_set_ep0_de_out(base_addr); | ||
669 | } | ||
670 | break; | ||
671 | |||
672 | case USB_REQ_SET_INTERFACE: | ||
673 | dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ... \n"); | ||
674 | |||
675 | if (crq->bRequestType == USB_RECIP_INTERFACE) { | ||
676 | dev->req_config = 1; | ||
677 | s3c2410_udc_set_ep0_de_out(base_addr); | ||
678 | } | ||
679 | break; | ||
680 | |||
681 | case USB_REQ_SET_ADDRESS: | ||
682 | dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ... \n"); | ||
683 | |||
684 | if (crq->bRequestType == USB_RECIP_DEVICE) { | ||
685 | tmp = crq->wValue & 0x7F; | ||
686 | dev->address = tmp; | ||
687 | udc_write((tmp | S3C2410_UDC_FUNCADDR_UPDATE), | ||
688 | S3C2410_UDC_FUNC_ADDR_REG); | ||
689 | s3c2410_udc_set_ep0_de_out(base_addr); | ||
690 | return; | ||
691 | } | ||
692 | break; | ||
693 | |||
694 | case USB_REQ_GET_STATUS: | ||
695 | dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ... \n"); | ||
696 | s3c2410_udc_clear_ep0_opr(base_addr); | ||
697 | |||
698 | if (dev->req_std) { | ||
699 | if (!s3c2410_udc_get_status(dev, crq)) { | ||
700 | return; | ||
701 | } | ||
702 | } | ||
703 | break; | ||
704 | |||
705 | case USB_REQ_CLEAR_FEATURE: | ||
706 | s3c2410_udc_clear_ep0_opr(base_addr); | ||
707 | |||
708 | if (crq->bRequestType != USB_RECIP_ENDPOINT) | ||
709 | break; | ||
710 | |||
711 | if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0) | ||
712 | break; | ||
713 | |||
714 | s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 0); | ||
715 | s3c2410_udc_set_ep0_de_out(base_addr); | ||
716 | return; | ||
717 | |||
718 | case USB_REQ_SET_FEATURE: | ||
719 | s3c2410_udc_clear_ep0_opr(base_addr); | ||
720 | |||
721 | if (crq->bRequestType != USB_RECIP_ENDPOINT) | ||
722 | break; | ||
723 | |||
724 | if (crq->wValue != USB_ENDPOINT_HALT || crq->wLength != 0) | ||
725 | break; | ||
726 | |||
727 | s3c2410_udc_set_halt(&dev->ep[crq->wIndex & 0x7f].ep, 1); | ||
728 | s3c2410_udc_set_ep0_de_out(base_addr); | ||
729 | return; | ||
730 | |||
731 | default: | ||
732 | s3c2410_udc_clear_ep0_opr(base_addr); | ||
733 | break; | ||
734 | } | ||
735 | |||
736 | if (crq->bRequestType & USB_DIR_IN) | ||
737 | dev->ep0state = EP0_IN_DATA_PHASE; | ||
738 | else | ||
739 | dev->ep0state = EP0_OUT_DATA_PHASE; | ||
740 | |||
741 | ret = dev->driver->setup(&dev->gadget, crq); | ||
742 | if (ret < 0) { | ||
743 | if (dev->req_config) { | ||
744 | dprintk(DEBUG_NORMAL, "config change %02x fail %d?\n", | ||
745 | crq->bRequest, ret); | ||
746 | return; | ||
747 | } | ||
748 | |||
749 | if (ret == -EOPNOTSUPP) | ||
750 | dprintk(DEBUG_NORMAL, "Operation not supported\n"); | ||
751 | else | ||
752 | dprintk(DEBUG_NORMAL, | ||
753 | "dev->driver->setup failed. (%d)\n", ret); | ||
754 | |||
755 | udelay(5); | ||
756 | s3c2410_udc_set_ep0_ss(base_addr); | ||
757 | s3c2410_udc_set_ep0_de_out(base_addr); | ||
758 | dev->ep0state = EP0_IDLE; | ||
759 | /* deferred i/o == no response yet */ | ||
760 | } else if (dev->req_pending) { | ||
761 | dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n"); | ||
762 | dev->req_pending=0; | ||
763 | } | ||
764 | |||
765 | dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]); | ||
766 | } | ||
767 | |||
768 | static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev) | ||
769 | { | ||
770 | u32 ep0csr; | ||
771 | struct s3c2410_ep *ep = &dev->ep[0]; | ||
772 | struct s3c2410_request *req; | ||
773 | struct usb_ctrlrequest crq; | ||
774 | |||
775 | if (list_empty(&ep->queue)) | ||
776 | req = NULL; | ||
777 | else | ||
778 | req = list_entry(ep->queue.next, struct s3c2410_request, queue); | ||
779 | |||
780 | /* We make the assumption that S3C2410_UDC_IN_CSR1_REG equal to | ||
781 | * S3C2410_UDC_EP0_CSR_REG when index is zero */ | ||
782 | |||
783 | udc_write(0, S3C2410_UDC_INDEX_REG); | ||
784 | ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
785 | |||
786 | dprintk(DEBUG_NORMAL, "ep0csr %x ep0state %s\n", | ||
787 | ep0csr, ep0states[dev->ep0state]); | ||
788 | |||
789 | /* clear stall status */ | ||
790 | if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) { | ||
791 | s3c2410_udc_nuke(dev, ep, -EPIPE); | ||
792 | dprintk(DEBUG_NORMAL, "... clear SENT_STALL ...\n"); | ||
793 | s3c2410_udc_clear_ep0_sst(base_addr); | ||
794 | dev->ep0state = EP0_IDLE; | ||
795 | return; | ||
796 | } | ||
797 | |||
798 | /* clear setup end */ | ||
799 | if (ep0csr & S3C2410_UDC_EP0_CSR_SE) { | ||
800 | dprintk(DEBUG_NORMAL, "... serviced SETUP_END ...\n"); | ||
801 | s3c2410_udc_nuke(dev, ep, 0); | ||
802 | s3c2410_udc_clear_ep0_se(base_addr); | ||
803 | dev->ep0state = EP0_IDLE; | ||
804 | } | ||
805 | |||
806 | switch (dev->ep0state) { | ||
807 | case EP0_IDLE: | ||
808 | s3c2410_udc_handle_ep0_idle(dev, ep, &crq, ep0csr); | ||
809 | break; | ||
810 | |||
811 | case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */ | ||
812 | dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n"); | ||
813 | if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) { | ||
814 | s3c2410_udc_write_fifo(ep, req); | ||
815 | } | ||
816 | break; | ||
817 | |||
818 | case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */ | ||
819 | dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n"); | ||
820 | if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req ) { | ||
821 | s3c2410_udc_read_fifo(ep,req); | ||
822 | } | ||
823 | break; | ||
824 | |||
825 | case EP0_END_XFER: | ||
826 | dprintk(DEBUG_NORMAL, "EP0_END_XFER ... what now?\n"); | ||
827 | dev->ep0state = EP0_IDLE; | ||
828 | break; | ||
829 | |||
830 | case EP0_STALL: | ||
831 | dprintk(DEBUG_NORMAL, "EP0_STALL ... what now?\n"); | ||
832 | dev->ep0state = EP0_IDLE; | ||
833 | break; | ||
834 | } | ||
835 | } | ||
836 | |||
837 | /* | ||
838 | * handle_ep - Manage I/O endpoints | ||
839 | */ | ||
840 | |||
841 | static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep) | ||
842 | { | ||
843 | struct s3c2410_request *req; | ||
844 | int is_in = ep->bEndpointAddress & USB_DIR_IN; | ||
845 | u32 ep_csr1; | ||
846 | u32 idx; | ||
847 | |||
848 | if (likely (!list_empty(&ep->queue))) | ||
849 | req = list_entry(ep->queue.next, | ||
850 | struct s3c2410_request, queue); | ||
851 | else | ||
852 | req = NULL; | ||
853 | |||
854 | idx = ep->bEndpointAddress & 0x7F; | ||
855 | |||
856 | if (is_in) { | ||
857 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
858 | ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
859 | dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n", | ||
860 | idx, ep_csr1, req ? 1 : 0); | ||
861 | |||
862 | if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) { | ||
863 | dprintk(DEBUG_VERBOSE, "st\n"); | ||
864 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
865 | udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL, | ||
866 | S3C2410_UDC_IN_CSR1_REG); | ||
867 | return; | ||
868 | } | ||
869 | |||
870 | if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) { | ||
871 | s3c2410_udc_write_fifo(ep,req); | ||
872 | } | ||
873 | } else { | ||
874 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
875 | ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG); | ||
876 | dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1); | ||
877 | |||
878 | if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) { | ||
879 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
880 | udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL, | ||
881 | S3C2410_UDC_OUT_CSR1_REG); | ||
882 | return; | ||
883 | } | ||
884 | |||
885 | if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) { | ||
886 | s3c2410_udc_read_fifo(ep,req); | ||
887 | } | ||
888 | } | ||
889 | } | ||
890 | |||
891 | #include <asm/arch/regs-irq.h> | ||
892 | |||
893 | /* | ||
894 | * s3c2410_udc_irq - interrupt handler | ||
895 | */ | ||
896 | static irqreturn_t s3c2410_udc_irq(int irq, void *_dev) | ||
897 | { | ||
898 | struct s3c2410_udc *dev = _dev; | ||
899 | int usb_status; | ||
900 | int usbd_status; | ||
901 | int pwr_reg; | ||
902 | int ep0csr; | ||
903 | int i; | ||
904 | u32 idx; | ||
905 | unsigned long flags; | ||
906 | |||
907 | spin_lock_irqsave(&dev->lock, flags); | ||
908 | |||
909 | /* Driver connected ? */ | ||
910 | if (!dev->driver) { | ||
911 | /* Clear interrupts */ | ||
912 | udc_write(udc_read(S3C2410_UDC_USB_INT_REG), | ||
913 | S3C2410_UDC_USB_INT_REG); | ||
914 | udc_write(udc_read(S3C2410_UDC_EP_INT_REG), | ||
915 | S3C2410_UDC_EP_INT_REG); | ||
916 | } | ||
917 | |||
918 | /* Save index */ | ||
919 | idx = udc_read(S3C2410_UDC_INDEX_REG); | ||
920 | |||
921 | /* Read status registers */ | ||
922 | usb_status = udc_read(S3C2410_UDC_USB_INT_REG); | ||
923 | usbd_status = udc_read(S3C2410_UDC_EP_INT_REG); | ||
924 | pwr_reg = udc_read(S3C2410_UDC_PWR_REG); | ||
925 | |||
926 | udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); | ||
927 | ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
928 | |||
929 | dprintk(DEBUG_NORMAL, "usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n", | ||
930 | usb_status, usbd_status, pwr_reg, ep0csr); | ||
931 | |||
932 | /* | ||
933 | * Now, handle interrupts. There's two types : | ||
934 | * - Reset, Resume, Suspend coming -> usb_int_reg | ||
935 | * - EP -> ep_int_reg | ||
936 | */ | ||
937 | |||
938 | /* RESET */ | ||
939 | if (usb_status & S3C2410_UDC_USBINT_RESET) { | ||
940 | /* two kind of reset : | ||
941 | * - reset start -> pwr reg = 8 | ||
942 | * - reset end -> pwr reg = 0 | ||
943 | **/ | ||
944 | dprintk(DEBUG_NORMAL, "USB reset csr %x pwr %x\n", | ||
945 | ep0csr, pwr_reg); | ||
946 | |||
947 | dev->gadget.speed = USB_SPEED_UNKNOWN; | ||
948 | udc_write(0x00, S3C2410_UDC_INDEX_REG); | ||
949 | udc_write((dev->ep[0].ep.maxpacket & 0x7ff) >> 3, | ||
950 | S3C2410_UDC_MAXP_REG); | ||
951 | dev->address = 0; | ||
952 | |||
953 | dev->ep0state = EP0_IDLE; | ||
954 | dev->gadget.speed = USB_SPEED_FULL; | ||
955 | |||
956 | /* clear interrupt */ | ||
957 | udc_write(S3C2410_UDC_USBINT_RESET, | ||
958 | S3C2410_UDC_USB_INT_REG); | ||
959 | |||
960 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
961 | spin_unlock_irqrestore(&dev->lock, flags); | ||
962 | return IRQ_HANDLED; | ||
963 | } | ||
964 | |||
965 | /* RESUME */ | ||
966 | if (usb_status & S3C2410_UDC_USBINT_RESUME) { | ||
967 | dprintk(DEBUG_NORMAL, "USB resume\n"); | ||
968 | |||
969 | /* clear interrupt */ | ||
970 | udc_write(S3C2410_UDC_USBINT_RESUME, | ||
971 | S3C2410_UDC_USB_INT_REG); | ||
972 | |||
973 | if (dev->gadget.speed != USB_SPEED_UNKNOWN | ||
974 | && dev->driver | ||
975 | && dev->driver->resume) | ||
976 | dev->driver->resume(&dev->gadget); | ||
977 | } | ||
978 | |||
979 | /* SUSPEND */ | ||
980 | if (usb_status & S3C2410_UDC_USBINT_SUSPEND) { | ||
981 | dprintk(DEBUG_NORMAL, "USB suspend\n"); | ||
982 | |||
983 | /* clear interrupt */ | ||
984 | udc_write(S3C2410_UDC_USBINT_SUSPEND, | ||
985 | S3C2410_UDC_USB_INT_REG); | ||
986 | |||
987 | if (dev->gadget.speed != USB_SPEED_UNKNOWN | ||
988 | && dev->driver | ||
989 | && dev->driver->suspend) | ||
990 | dev->driver->suspend(&dev->gadget); | ||
991 | |||
992 | dev->ep0state = EP0_IDLE; | ||
993 | } | ||
994 | |||
995 | /* EP */ | ||
996 | /* control traffic */ | ||
997 | /* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready | ||
998 | * generate an interrupt | ||
999 | */ | ||
1000 | if (usbd_status & S3C2410_UDC_INT_EP0) { | ||
1001 | dprintk(DEBUG_VERBOSE, "USB ep0 irq\n"); | ||
1002 | /* Clear the interrupt bit by setting it to 1 */ | ||
1003 | udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG); | ||
1004 | s3c2410_udc_handle_ep0(dev); | ||
1005 | } | ||
1006 | |||
1007 | /* endpoint data transfers */ | ||
1008 | for (i = 1; i < S3C2410_ENDPOINTS; i++) { | ||
1009 | u32 tmp = 1 << i; | ||
1010 | if (usbd_status & tmp) { | ||
1011 | dprintk(DEBUG_VERBOSE, "USB ep%d irq\n", i); | ||
1012 | |||
1013 | /* Clear the interrupt bit by setting it to 1 */ | ||
1014 | udc_write(tmp, S3C2410_UDC_EP_INT_REG); | ||
1015 | s3c2410_udc_handle_ep(&dev->ep[i]); | ||
1016 | } | ||
1017 | } | ||
1018 | |||
1019 | dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", irq); | ||
1020 | |||
1021 | /* Restore old index */ | ||
1022 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
1023 | |||
1024 | spin_unlock_irqrestore(&dev->lock, flags); | ||
1025 | |||
1026 | return IRQ_HANDLED; | ||
1027 | } | ||
1028 | /*------------------------- s3c2410_ep_ops ----------------------------------*/ | ||
1029 | |||
1030 | static inline struct s3c2410_ep *to_s3c2410_ep(struct usb_ep *ep) | ||
1031 | { | ||
1032 | return container_of(ep, struct s3c2410_ep, ep); | ||
1033 | } | ||
1034 | |||
1035 | static inline struct s3c2410_udc *to_s3c2410_udc(struct usb_gadget *gadget) | ||
1036 | { | ||
1037 | return container_of(gadget, struct s3c2410_udc, gadget); | ||
1038 | } | ||
1039 | |||
1040 | static inline struct s3c2410_request *to_s3c2410_req(struct usb_request *req) | ||
1041 | { | ||
1042 | return container_of(req, struct s3c2410_request, req); | ||
1043 | } | ||
1044 | |||
1045 | /* | ||
1046 | * s3c2410_udc_ep_enable | ||
1047 | */ | ||
1048 | static int s3c2410_udc_ep_enable(struct usb_ep *_ep, | ||
1049 | const struct usb_endpoint_descriptor *desc) | ||
1050 | { | ||
1051 | struct s3c2410_udc *dev; | ||
1052 | struct s3c2410_ep *ep; | ||
1053 | u32 max, tmp; | ||
1054 | unsigned long flags; | ||
1055 | u32 csr1,csr2; | ||
1056 | u32 int_en_reg; | ||
1057 | |||
1058 | ep = to_s3c2410_ep(_ep); | ||
1059 | |||
1060 | if (!_ep || !desc || ep->desc | ||
1061 | || _ep->name == ep0name | ||
1062 | || desc->bDescriptorType != USB_DT_ENDPOINT) | ||
1063 | return -EINVAL; | ||
1064 | |||
1065 | dev = ep->dev; | ||
1066 | if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) | ||
1067 | return -ESHUTDOWN; | ||
1068 | |||
1069 | max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff; | ||
1070 | |||
1071 | local_irq_save (flags); | ||
1072 | _ep->maxpacket = max & 0x7ff; | ||
1073 | ep->desc = desc; | ||
1074 | ep->halted = 0; | ||
1075 | ep->bEndpointAddress = desc->bEndpointAddress; | ||
1076 | |||
1077 | /* set max packet */ | ||
1078 | udc_write(ep->num, S3C2410_UDC_INDEX_REG); | ||
1079 | udc_write(max >> 3, S3C2410_UDC_MAXP_REG); | ||
1080 | |||
1081 | /* set type, direction, address; reset fifo counters */ | ||
1082 | if (desc->bEndpointAddress & USB_DIR_IN) { | ||
1083 | csr1 = S3C2410_UDC_ICSR1_FFLUSH|S3C2410_UDC_ICSR1_CLRDT; | ||
1084 | csr2 = S3C2410_UDC_ICSR2_MODEIN|S3C2410_UDC_ICSR2_DMAIEN; | ||
1085 | |||
1086 | udc_write(ep->num, S3C2410_UDC_INDEX_REG); | ||
1087 | udc_write(csr1, S3C2410_UDC_IN_CSR1_REG); | ||
1088 | udc_write(ep->num, S3C2410_UDC_INDEX_REG); | ||
1089 | udc_write(csr2, S3C2410_UDC_IN_CSR2_REG); | ||
1090 | } else { | ||
1091 | /* don't flush in fifo or it will cause endpoint interrupt */ | ||
1092 | csr1 = S3C2410_UDC_ICSR1_CLRDT; | ||
1093 | csr2 = S3C2410_UDC_ICSR2_DMAIEN; | ||
1094 | |||
1095 | udc_write(ep->num, S3C2410_UDC_INDEX_REG); | ||
1096 | udc_write(csr1, S3C2410_UDC_IN_CSR1_REG); | ||
1097 | udc_write(ep->num, S3C2410_UDC_INDEX_REG); | ||
1098 | udc_write(csr2, S3C2410_UDC_IN_CSR2_REG); | ||
1099 | |||
1100 | csr1 = S3C2410_UDC_OCSR1_FFLUSH | S3C2410_UDC_OCSR1_CLRDT; | ||
1101 | csr2 = S3C2410_UDC_OCSR2_DMAIEN; | ||
1102 | |||
1103 | udc_write(ep->num, S3C2410_UDC_INDEX_REG); | ||
1104 | udc_write(csr1, S3C2410_UDC_OUT_CSR1_REG); | ||
1105 | udc_write(ep->num, S3C2410_UDC_INDEX_REG); | ||
1106 | udc_write(csr2, S3C2410_UDC_OUT_CSR2_REG); | ||
1107 | } | ||
1108 | |||
1109 | /* enable irqs */ | ||
1110 | int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG); | ||
1111 | udc_write(int_en_reg | (1 << ep->num), S3C2410_UDC_EP_INT_EN_REG); | ||
1112 | |||
1113 | /* print some debug message */ | ||
1114 | tmp = desc->bEndpointAddress; | ||
1115 | dprintk (DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n", | ||
1116 | _ep->name,ep->num, tmp, | ||
1117 | desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max); | ||
1118 | |||
1119 | local_irq_restore (flags); | ||
1120 | s3c2410_udc_set_halt(_ep, 0); | ||
1121 | |||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | /* | ||
1126 | * s3c2410_udc_ep_disable | ||
1127 | */ | ||
1128 | static int s3c2410_udc_ep_disable(struct usb_ep *_ep) | ||
1129 | { | ||
1130 | struct s3c2410_ep *ep = to_s3c2410_ep(_ep); | ||
1131 | unsigned long flags; | ||
1132 | u32 int_en_reg; | ||
1133 | |||
1134 | if (!_ep || !ep->desc) { | ||
1135 | dprintk(DEBUG_NORMAL, "%s not enabled\n", | ||
1136 | _ep ? ep->ep.name : NULL); | ||
1137 | return -EINVAL; | ||
1138 | } | ||
1139 | |||
1140 | local_irq_save(flags); | ||
1141 | |||
1142 | dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name); | ||
1143 | |||
1144 | ep->desc = NULL; | ||
1145 | ep->halted = 1; | ||
1146 | |||
1147 | s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN); | ||
1148 | |||
1149 | /* disable irqs */ | ||
1150 | int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG); | ||
1151 | udc_write(int_en_reg & ~(1<<ep->num), S3C2410_UDC_EP_INT_EN_REG); | ||
1152 | |||
1153 | local_irq_restore(flags); | ||
1154 | |||
1155 | dprintk(DEBUG_NORMAL, "%s disabled\n", _ep->name); | ||
1156 | |||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | /* | ||
1161 | * s3c2410_udc_alloc_request | ||
1162 | */ | ||
1163 | static struct usb_request * | ||
1164 | s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags) | ||
1165 | { | ||
1166 | struct s3c2410_request *req; | ||
1167 | |||
1168 | dprintk(DEBUG_VERBOSE,"%s(%p,%d)\n", __func__, _ep, mem_flags); | ||
1169 | |||
1170 | if (!_ep) | ||
1171 | return NULL; | ||
1172 | |||
1173 | req = kzalloc (sizeof(struct s3c2410_request), mem_flags); | ||
1174 | if (!req) | ||
1175 | return NULL; | ||
1176 | |||
1177 | INIT_LIST_HEAD (&req->queue); | ||
1178 | return &req->req; | ||
1179 | } | ||
1180 | |||
1181 | /* | ||
1182 | * s3c2410_udc_free_request | ||
1183 | */ | ||
1184 | static void | ||
1185 | s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req) | ||
1186 | { | ||
1187 | struct s3c2410_ep *ep = to_s3c2410_ep(_ep); | ||
1188 | struct s3c2410_request *req = to_s3c2410_req(_req); | ||
1189 | |||
1190 | dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req); | ||
1191 | |||
1192 | if (!ep || !_req || (!ep->desc && _ep->name != ep0name)) | ||
1193 | return; | ||
1194 | |||
1195 | WARN_ON (!list_empty (&req->queue)); | ||
1196 | kfree(req); | ||
1197 | } | ||
1198 | |||
1199 | /* | ||
1200 | * s3c2410_udc_queue | ||
1201 | */ | ||
1202 | static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, | ||
1203 | gfp_t gfp_flags) | ||
1204 | { | ||
1205 | struct s3c2410_request *req = to_s3c2410_req(_req); | ||
1206 | struct s3c2410_ep *ep = to_s3c2410_ep(_ep); | ||
1207 | struct s3c2410_udc *dev; | ||
1208 | u32 ep_csr = 0; | ||
1209 | int fifo_count = 0; | ||
1210 | unsigned long flags; | ||
1211 | |||
1212 | if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { | ||
1213 | dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__); | ||
1214 | return -EINVAL; | ||
1215 | } | ||
1216 | |||
1217 | dev = ep->dev; | ||
1218 | if (unlikely (!dev->driver | ||
1219 | || dev->gadget.speed == USB_SPEED_UNKNOWN)) { | ||
1220 | return -ESHUTDOWN; | ||
1221 | } | ||
1222 | |||
1223 | local_irq_save (flags); | ||
1224 | |||
1225 | if (unlikely(!_req || !_req->complete | ||
1226 | || !_req->buf || !list_empty(&req->queue))) { | ||
1227 | if (!_req) | ||
1228 | dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__); | ||
1229 | else { | ||
1230 | dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n", | ||
1231 | __func__, !_req->complete,!_req->buf, | ||
1232 | !list_empty(&req->queue)); | ||
1233 | } | ||
1234 | |||
1235 | local_irq_restore(flags); | ||
1236 | return -EINVAL; | ||
1237 | } | ||
1238 | |||
1239 | _req->status = -EINPROGRESS; | ||
1240 | _req->actual = 0; | ||
1241 | |||
1242 | dprintk(DEBUG_VERBOSE, "%s: ep%x len %d\n", | ||
1243 | __func__, ep->bEndpointAddress, _req->length); | ||
1244 | |||
1245 | if (ep->bEndpointAddress) { | ||
1246 | udc_write(ep->bEndpointAddress & 0x7F, S3C2410_UDC_INDEX_REG); | ||
1247 | |||
1248 | ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN) | ||
1249 | ? S3C2410_UDC_IN_CSR1_REG | ||
1250 | : S3C2410_UDC_OUT_CSR1_REG); | ||
1251 | fifo_count = s3c2410_udc_fifo_count_out(); | ||
1252 | } else { | ||
1253 | udc_write(0, S3C2410_UDC_INDEX_REG); | ||
1254 | ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG); | ||
1255 | fifo_count = s3c2410_udc_fifo_count_out(); | ||
1256 | } | ||
1257 | |||
1258 | /* kickstart this i/o queue? */ | ||
1259 | if (list_empty(&ep->queue) && !ep->halted) { | ||
1260 | if (ep->bEndpointAddress == 0 /* ep0 */) { | ||
1261 | switch (dev->ep0state) { | ||
1262 | case EP0_IN_DATA_PHASE: | ||
1263 | if (!(ep_csr&S3C2410_UDC_EP0_CSR_IPKRDY) | ||
1264 | && s3c2410_udc_write_fifo(ep, | ||
1265 | req)) { | ||
1266 | dev->ep0state = EP0_IDLE; | ||
1267 | req = NULL; | ||
1268 | } | ||
1269 | break; | ||
1270 | |||
1271 | case EP0_OUT_DATA_PHASE: | ||
1272 | if ((!_req->length) | ||
1273 | || ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY) | ||
1274 | && s3c2410_udc_read_fifo(ep, | ||
1275 | req))) { | ||
1276 | dev->ep0state = EP0_IDLE; | ||
1277 | req = NULL; | ||
1278 | } | ||
1279 | break; | ||
1280 | |||
1281 | default: | ||
1282 | local_irq_restore(flags); | ||
1283 | return -EL2HLT; | ||
1284 | } | ||
1285 | } else if ((ep->bEndpointAddress & USB_DIR_IN) != 0 | ||
1286 | && (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY)) | ||
1287 | && s3c2410_udc_write_fifo(ep, req)) { | ||
1288 | req = NULL; | ||
1289 | } else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY) | ||
1290 | && fifo_count | ||
1291 | && s3c2410_udc_read_fifo(ep, req)) { | ||
1292 | req = NULL; | ||
1293 | } | ||
1294 | } | ||
1295 | |||
1296 | /* pio or dma irq handler advances the queue. */ | ||
1297 | if (likely (req != 0)) | ||
1298 | list_add_tail(&req->queue, &ep->queue); | ||
1299 | |||
1300 | local_irq_restore(flags); | ||
1301 | |||
1302 | dprintk(DEBUG_VERBOSE, "%s ok\n", __func__); | ||
1303 | return 0; | ||
1304 | } | ||
1305 | |||
1306 | /* | ||
1307 | * s3c2410_udc_dequeue | ||
1308 | */ | ||
1309 | static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req) | ||
1310 | { | ||
1311 | struct s3c2410_ep *ep = to_s3c2410_ep(_ep); | ||
1312 | struct s3c2410_udc *udc; | ||
1313 | int retval = -EINVAL; | ||
1314 | unsigned long flags; | ||
1315 | struct s3c2410_request *req = NULL; | ||
1316 | |||
1317 | dprintk(DEBUG_VERBOSE, "%s(%p,%p)\n", __func__, _ep, _req); | ||
1318 | |||
1319 | if (!the_controller->driver) | ||
1320 | return -ESHUTDOWN; | ||
1321 | |||
1322 | if (!_ep || !_req) | ||
1323 | return retval; | ||
1324 | |||
1325 | udc = to_s3c2410_udc(ep->gadget); | ||
1326 | |||
1327 | local_irq_save (flags); | ||
1328 | |||
1329 | list_for_each_entry (req, &ep->queue, queue) { | ||
1330 | if (&req->req == _req) { | ||
1331 | list_del_init (&req->queue); | ||
1332 | _req->status = -ECONNRESET; | ||
1333 | retval = 0; | ||
1334 | break; | ||
1335 | } | ||
1336 | } | ||
1337 | |||
1338 | if (retval == 0) { | ||
1339 | dprintk(DEBUG_VERBOSE, | ||
1340 | "dequeued req %p from %s, len %d buf %p\n", | ||
1341 | req, _ep->name, _req->length, _req->buf); | ||
1342 | |||
1343 | s3c2410_udc_done(ep, req, -ECONNRESET); | ||
1344 | } | ||
1345 | |||
1346 | local_irq_restore (flags); | ||
1347 | return retval; | ||
1348 | } | ||
1349 | |||
1350 | /* | ||
1351 | * s3c2410_udc_set_halt | ||
1352 | */ | ||
1353 | static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value) | ||
1354 | { | ||
1355 | struct s3c2410_ep *ep = to_s3c2410_ep(_ep); | ||
1356 | u32 ep_csr = 0; | ||
1357 | unsigned long flags; | ||
1358 | u32 idx; | ||
1359 | |||
1360 | if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) { | ||
1361 | dprintk(DEBUG_NORMAL, "%s: inval 2\n", __func__); | ||
1362 | return -EINVAL; | ||
1363 | } | ||
1364 | |||
1365 | local_irq_save (flags); | ||
1366 | |||
1367 | idx = ep->bEndpointAddress & 0x7F; | ||
1368 | |||
1369 | if (idx == 0) { | ||
1370 | s3c2410_udc_set_ep0_ss(base_addr); | ||
1371 | s3c2410_udc_set_ep0_de_out(base_addr); | ||
1372 | } else { | ||
1373 | udc_write(idx, S3C2410_UDC_INDEX_REG); | ||
1374 | ep_csr = udc_read((ep->bEndpointAddress &USB_DIR_IN) | ||
1375 | ? S3C2410_UDC_IN_CSR1_REG | ||
1376 | : S3C2410_UDC_OUT_CSR1_REG); | ||
1377 | |||
1378 | if ((ep->bEndpointAddress & USB_DIR_IN) != 0) { | ||
1379 | if (value) | ||
1380 | udc_write(ep_csr | S3C2410_UDC_ICSR1_SENDSTL, | ||
1381 | S3C2410_UDC_IN_CSR1_REG); | ||
1382 | else { | ||
1383 | ep_csr &= ~S3C2410_UDC_ICSR1_SENDSTL; | ||
1384 | udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG); | ||
1385 | ep_csr |= S3C2410_UDC_ICSR1_CLRDT; | ||
1386 | udc_write(ep_csr, S3C2410_UDC_IN_CSR1_REG); | ||
1387 | } | ||
1388 | } else { | ||
1389 | if (value) | ||
1390 | udc_write(ep_csr | S3C2410_UDC_OCSR1_SENDSTL, | ||
1391 | S3C2410_UDC_OUT_CSR1_REG); | ||
1392 | else { | ||
1393 | ep_csr &= ~S3C2410_UDC_OCSR1_SENDSTL; | ||
1394 | udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG); | ||
1395 | ep_csr |= S3C2410_UDC_OCSR1_CLRDT; | ||
1396 | udc_write(ep_csr, S3C2410_UDC_OUT_CSR1_REG); | ||
1397 | } | ||
1398 | } | ||
1399 | } | ||
1400 | |||
1401 | ep->halted = value ? 1 : 0; | ||
1402 | local_irq_restore (flags); | ||
1403 | |||
1404 | return 0; | ||
1405 | } | ||
1406 | |||
1407 | static const struct usb_ep_ops s3c2410_ep_ops = { | ||
1408 | .enable = s3c2410_udc_ep_enable, | ||
1409 | .disable = s3c2410_udc_ep_disable, | ||
1410 | |||
1411 | .alloc_request = s3c2410_udc_alloc_request, | ||
1412 | .free_request = s3c2410_udc_free_request, | ||
1413 | |||
1414 | .queue = s3c2410_udc_queue, | ||
1415 | .dequeue = s3c2410_udc_dequeue, | ||
1416 | |||
1417 | .set_halt = s3c2410_udc_set_halt, | ||
1418 | }; | ||
1419 | |||
1420 | /*------------------------- usb_gadget_ops ----------------------------------*/ | ||
1421 | |||
1422 | /* | ||
1423 | * s3c2410_udc_get_frame | ||
1424 | */ | ||
1425 | static int s3c2410_udc_get_frame(struct usb_gadget *_gadget) | ||
1426 | { | ||
1427 | int tmp; | ||
1428 | |||
1429 | dprintk(DEBUG_VERBOSE, "%s()\n", __func__); | ||
1430 | |||
1431 | tmp = udc_read(S3C2410_UDC_FRAME_NUM2_REG) << 8; | ||
1432 | tmp |= udc_read(S3C2410_UDC_FRAME_NUM1_REG); | ||
1433 | return tmp; | ||
1434 | } | ||
1435 | |||
1436 | /* | ||
1437 | * s3c2410_udc_wakeup | ||
1438 | */ | ||
1439 | static int s3c2410_udc_wakeup(struct usb_gadget *_gadget) | ||
1440 | { | ||
1441 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); | ||
1442 | return 0; | ||
1443 | } | ||
1444 | |||
1445 | /* | ||
1446 | * s3c2410_udc_set_selfpowered | ||
1447 | */ | ||
1448 | static int s3c2410_udc_set_selfpowered(struct usb_gadget *gadget, int value) | ||
1449 | { | ||
1450 | struct s3c2410_udc *udc = to_s3c2410_udc(gadget); | ||
1451 | |||
1452 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); | ||
1453 | |||
1454 | if (value) | ||
1455 | udc->devstatus |= (1 << USB_DEVICE_SELF_POWERED); | ||
1456 | else | ||
1457 | udc->devstatus &= ~(1 << USB_DEVICE_SELF_POWERED); | ||
1458 | |||
1459 | return 0; | ||
1460 | } | ||
1461 | |||
1462 | static void s3c2410_udc_disable(struct s3c2410_udc *dev); | ||
1463 | static void s3c2410_udc_enable(struct s3c2410_udc *dev); | ||
1464 | |||
1465 | static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on) | ||
1466 | { | ||
1467 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); | ||
1468 | |||
1469 | if (udc_info && udc_info->udc_command) { | ||
1470 | if (is_on) | ||
1471 | s3c2410_udc_enable(udc); | ||
1472 | else { | ||
1473 | if (udc->gadget.speed != USB_SPEED_UNKNOWN) { | ||
1474 | if (udc->driver && udc->driver->disconnect) | ||
1475 | udc->driver->disconnect(&udc->gadget); | ||
1476 | |||
1477 | } | ||
1478 | s3c2410_udc_disable(udc); | ||
1479 | } | ||
1480 | } | ||
1481 | else | ||
1482 | return -EOPNOTSUPP; | ||
1483 | |||
1484 | return 0; | ||
1485 | } | ||
1486 | |||
1487 | static int s3c2410_udc_vbus_session(struct usb_gadget *gadget, int is_active) | ||
1488 | { | ||
1489 | struct s3c2410_udc *udc = to_s3c2410_udc(gadget); | ||
1490 | |||
1491 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); | ||
1492 | |||
1493 | udc->vbus = (is_active != 0); | ||
1494 | s3c2410_udc_set_pullup(udc, is_active); | ||
1495 | return 0; | ||
1496 | } | ||
1497 | |||
1498 | static int s3c2410_udc_pullup(struct usb_gadget *gadget, int is_on) | ||
1499 | { | ||
1500 | struct s3c2410_udc *udc = to_s3c2410_udc(gadget); | ||
1501 | |||
1502 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); | ||
1503 | |||
1504 | s3c2410_udc_set_pullup(udc, is_on ? 0 : 1); | ||
1505 | return 0; | ||
1506 | } | ||
1507 | |||
1508 | static irqreturn_t s3c2410_udc_vbus_irq(int irq, void *_dev) | ||
1509 | { | ||
1510 | struct s3c2410_udc *dev = _dev; | ||
1511 | unsigned int value; | ||
1512 | |||
1513 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); | ||
1514 | value = s3c2410_gpio_getpin(udc_info->vbus_pin); | ||
1515 | |||
1516 | if (udc_info->vbus_pin_inverted) | ||
1517 | value = !value; | ||
1518 | |||
1519 | if (value != dev->vbus) | ||
1520 | s3c2410_udc_vbus_session(&dev->gadget, value); | ||
1521 | |||
1522 | return IRQ_HANDLED; | ||
1523 | } | ||
1524 | |||
1525 | static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma) | ||
1526 | { | ||
1527 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); | ||
1528 | |||
1529 | if (udc_info && udc_info->vbus_draw) { | ||
1530 | udc_info->vbus_draw(ma); | ||
1531 | return 0; | ||
1532 | } | ||
1533 | |||
1534 | return -ENOTSUPP; | ||
1535 | } | ||
1536 | |||
1537 | static const struct usb_gadget_ops s3c2410_ops = { | ||
1538 | .get_frame = s3c2410_udc_get_frame, | ||
1539 | .wakeup = s3c2410_udc_wakeup, | ||
1540 | .set_selfpowered = s3c2410_udc_set_selfpowered, | ||
1541 | .pullup = s3c2410_udc_pullup, | ||
1542 | .vbus_session = s3c2410_udc_vbus_session, | ||
1543 | .vbus_draw = s3c2410_vbus_draw, | ||
1544 | }; | ||
1545 | |||
1546 | /*------------------------- gadget driver handling---------------------------*/ | ||
1547 | /* | ||
1548 | * s3c2410_udc_disable | ||
1549 | */ | ||
1550 | static void s3c2410_udc_disable(struct s3c2410_udc *dev) | ||
1551 | { | ||
1552 | dprintk(DEBUG_NORMAL, "%s()\n", __func__); | ||
1553 | |||
1554 | /* Disable all interrupts */ | ||
1555 | udc_write(0x00, S3C2410_UDC_USB_INT_EN_REG); | ||
1556 | udc_write(0x00, S3C2410_UDC_EP_INT_EN_REG); | ||
1557 | |||
1558 | /* Clear the interrupt registers */ | ||
1559 | udc_write(S3C2410_UDC_USBINT_RESET | ||
1560 | | S3C2410_UDC_USBINT_RESUME | ||
1561 | | S3C2410_UDC_USBINT_SUSPEND, | ||
1562 | S3C2410_UDC_USB_INT_REG); | ||
1563 | |||
1564 | udc_write(0x1F, S3C2410_UDC_EP_INT_REG); | ||
1565 | |||
1566 | /* Good bye, cruel world */ | ||
1567 | if (udc_info && udc_info->udc_command) | ||
1568 | udc_info->udc_command(S3C2410_UDC_P_DISABLE); | ||
1569 | |||
1570 | /* Set speed to unknown */ | ||
1571 | dev->gadget.speed = USB_SPEED_UNKNOWN; | ||
1572 | } | ||
1573 | |||
1574 | /* | ||
1575 | * s3c2410_udc_reinit | ||
1576 | */ | ||
1577 | static void s3c2410_udc_reinit(struct s3c2410_udc *dev) | ||
1578 | { | ||
1579 | u32 i; | ||
1580 | |||
1581 | /* device/ep0 records init */ | ||
1582 | INIT_LIST_HEAD (&dev->gadget.ep_list); | ||
1583 | INIT_LIST_HEAD (&dev->gadget.ep0->ep_list); | ||
1584 | dev->ep0state = EP0_IDLE; | ||
1585 | |||
1586 | for (i = 0; i < S3C2410_ENDPOINTS; i++) { | ||
1587 | struct s3c2410_ep *ep = &dev->ep[i]; | ||
1588 | |||
1589 | if (i != 0) | ||
1590 | list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); | ||
1591 | |||
1592 | ep->dev = dev; | ||
1593 | ep->desc = NULL; | ||
1594 | ep->halted = 0; | ||
1595 | INIT_LIST_HEAD (&ep->queue); | ||
1596 | } | ||
1597 | } | ||
1598 | |||
1599 | /* | ||
1600 | * s3c2410_udc_enable | ||
1601 | */ | ||
1602 | static void s3c2410_udc_enable(struct s3c2410_udc *dev) | ||
1603 | { | ||
1604 | int i; | ||
1605 | |||
1606 | dprintk(DEBUG_NORMAL, "s3c2410_udc_enable called\n"); | ||
1607 | |||
1608 | /* dev->gadget.speed = USB_SPEED_UNKNOWN; */ | ||
1609 | dev->gadget.speed = USB_SPEED_FULL; | ||
1610 | |||
1611 | /* Set MAXP for all endpoints */ | ||
1612 | for (i = 0; i < S3C2410_ENDPOINTS; i++) { | ||
1613 | udc_write(i, S3C2410_UDC_INDEX_REG); | ||
1614 | udc_write((dev->ep[i].ep.maxpacket & 0x7ff) >> 3, | ||
1615 | S3C2410_UDC_MAXP_REG); | ||
1616 | } | ||
1617 | |||
1618 | /* Set default power state */ | ||
1619 | udc_write(DEFAULT_POWER_STATE, S3C2410_UDC_PWR_REG); | ||
1620 | |||
1621 | /* Enable reset and suspend interrupt interrupts */ | ||
1622 | udc_write(S3C2410_UDC_USBINT_RESET | S3C2410_UDC_USBINT_SUSPEND, | ||
1623 | S3C2410_UDC_USB_INT_EN_REG); | ||
1624 | |||
1625 | /* Enable ep0 interrupt */ | ||
1626 | udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_EN_REG); | ||
1627 | |||
1628 | /* time to say "hello, world" */ | ||
1629 | if (udc_info && udc_info->udc_command) | ||
1630 | udc_info->udc_command(S3C2410_UDC_P_ENABLE); | ||
1631 | } | ||
1632 | |||
1633 | /* | ||
1634 | * usb_gadget_register_driver | ||
1635 | */ | ||
1636 | int usb_gadget_register_driver(struct usb_gadget_driver *driver) | ||
1637 | { | ||
1638 | struct s3c2410_udc *udc = the_controller; | ||
1639 | int retval; | ||
1640 | |||
1641 | dprintk(DEBUG_NORMAL, "usb_gadget_register_driver() '%s'\n", | ||
1642 | driver->driver.name); | ||
1643 | |||
1644 | /* Sanity checks */ | ||
1645 | if (!udc) | ||
1646 | return -ENODEV; | ||
1647 | |||
1648 | if (udc->driver) | ||
1649 | return -EBUSY; | ||
1650 | |||
1651 | if (!driver->bind || !driver->setup | ||
1652 | || driver->speed != USB_SPEED_FULL) { | ||
1653 | printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n", | ||
1654 | driver->bind, driver->setup, driver->speed); | ||
1655 | return -EINVAL; | ||
1656 | } | ||
1657 | #if defined(MODULE) | ||
1658 | if (!driver->unbind) { | ||
1659 | printk(KERN_ERR "Invalid driver: no unbind method\n"); | ||
1660 | return -EINVAL; | ||
1661 | } | ||
1662 | #endif | ||
1663 | |||
1664 | /* Hook the driver */ | ||
1665 | udc->driver = driver; | ||
1666 | udc->gadget.dev.driver = &driver->driver; | ||
1667 | |||
1668 | /* Bind the driver */ | ||
1669 | if ((retval = device_add(&udc->gadget.dev)) != 0) { | ||
1670 | printk(KERN_ERR "Error in device_add() : %d\n",retval); | ||
1671 | goto register_error; | ||
1672 | } | ||
1673 | |||
1674 | dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n", | ||
1675 | driver->driver.name); | ||
1676 | |||
1677 | if ((retval = driver->bind (&udc->gadget)) != 0) { | ||
1678 | device_del(&udc->gadget.dev); | ||
1679 | goto register_error; | ||
1680 | } | ||
1681 | |||
1682 | /* Enable udc */ | ||
1683 | s3c2410_udc_enable(udc); | ||
1684 | |||
1685 | return 0; | ||
1686 | |||
1687 | register_error: | ||
1688 | udc->driver = NULL; | ||
1689 | udc->gadget.dev.driver = NULL; | ||
1690 | return retval; | ||
1691 | } | ||
1692 | |||
1693 | /* | ||
1694 | * usb_gadget_unregister_driver | ||
1695 | */ | ||
1696 | int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) | ||
1697 | { | ||
1698 | struct s3c2410_udc *udc = the_controller; | ||
1699 | |||
1700 | if (!udc) | ||
1701 | return -ENODEV; | ||
1702 | |||
1703 | if (!driver || driver != udc->driver || !driver->unbind) | ||
1704 | return -EINVAL; | ||
1705 | |||
1706 | dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n", | ||
1707 | driver->driver.name); | ||
1708 | |||
1709 | if (driver->disconnect) | ||
1710 | driver->disconnect(&udc->gadget); | ||
1711 | |||
1712 | device_del(&udc->gadget.dev); | ||
1713 | udc->driver = NULL; | ||
1714 | |||
1715 | /* Disable udc */ | ||
1716 | s3c2410_udc_disable(udc); | ||
1717 | |||
1718 | return 0; | ||
1719 | } | ||
1720 | |||
1721 | /*---------------------------------------------------------------------------*/ | ||
1722 | static struct s3c2410_udc memory = { | ||
1723 | .gadget = { | ||
1724 | .ops = &s3c2410_ops, | ||
1725 | .ep0 = &memory.ep[0].ep, | ||
1726 | .name = gadget_name, | ||
1727 | .dev = { | ||
1728 | .bus_id = "gadget", | ||
1729 | }, | ||
1730 | }, | ||
1731 | |||
1732 | /* control endpoint */ | ||
1733 | .ep[0] = { | ||
1734 | .num = 0, | ||
1735 | .ep = { | ||
1736 | .name = ep0name, | ||
1737 | .ops = &s3c2410_ep_ops, | ||
1738 | .maxpacket = EP0_FIFO_SIZE, | ||
1739 | }, | ||
1740 | .dev = &memory, | ||
1741 | }, | ||
1742 | |||
1743 | /* first group of endpoints */ | ||
1744 | .ep[1] = { | ||
1745 | .num = 1, | ||
1746 | .ep = { | ||
1747 | .name = "ep1-bulk", | ||
1748 | .ops = &s3c2410_ep_ops, | ||
1749 | .maxpacket = EP_FIFO_SIZE, | ||
1750 | }, | ||
1751 | .dev = &memory, | ||
1752 | .fifo_size = EP_FIFO_SIZE, | ||
1753 | .bEndpointAddress = 1, | ||
1754 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
1755 | }, | ||
1756 | .ep[2] = { | ||
1757 | .num = 2, | ||
1758 | .ep = { | ||
1759 | .name = "ep2-bulk", | ||
1760 | .ops = &s3c2410_ep_ops, | ||
1761 | .maxpacket = EP_FIFO_SIZE, | ||
1762 | }, | ||
1763 | .dev = &memory, | ||
1764 | .fifo_size = EP_FIFO_SIZE, | ||
1765 | .bEndpointAddress = 2, | ||
1766 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
1767 | }, | ||
1768 | .ep[3] = { | ||
1769 | .num = 3, | ||
1770 | .ep = { | ||
1771 | .name = "ep3-bulk", | ||
1772 | .ops = &s3c2410_ep_ops, | ||
1773 | .maxpacket = EP_FIFO_SIZE, | ||
1774 | }, | ||
1775 | .dev = &memory, | ||
1776 | .fifo_size = EP_FIFO_SIZE, | ||
1777 | .bEndpointAddress = 3, | ||
1778 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
1779 | }, | ||
1780 | .ep[4] = { | ||
1781 | .num = 4, | ||
1782 | .ep = { | ||
1783 | .name = "ep4-bulk", | ||
1784 | .ops = &s3c2410_ep_ops, | ||
1785 | .maxpacket = EP_FIFO_SIZE, | ||
1786 | }, | ||
1787 | .dev = &memory, | ||
1788 | .fifo_size = EP_FIFO_SIZE, | ||
1789 | .bEndpointAddress = 4, | ||
1790 | .bmAttributes = USB_ENDPOINT_XFER_BULK, | ||
1791 | } | ||
1792 | |||
1793 | }; | ||
1794 | |||
1795 | /* | ||
1796 | * probe - binds to the platform device | ||
1797 | */ | ||
1798 | static int s3c2410_udc_probe(struct platform_device *pdev) | ||
1799 | { | ||
1800 | struct s3c2410_udc *udc = &memory; | ||
1801 | struct device *dev = &pdev->dev; | ||
1802 | int retval; | ||
1803 | unsigned int irq; | ||
1804 | |||
1805 | dev_dbg(dev, "%s()\n", __func__); | ||
1806 | |||
1807 | usb_bus_clock = clk_get(NULL, "usb-bus-gadget"); | ||
1808 | if (IS_ERR(usb_bus_clock)) { | ||
1809 | dev_err(dev, "failed to get usb bus clock source\n"); | ||
1810 | return PTR_ERR(usb_bus_clock); | ||
1811 | } | ||
1812 | |||
1813 | clk_enable(usb_bus_clock); | ||
1814 | |||
1815 | udc_clock = clk_get(NULL, "usb-device"); | ||
1816 | if (IS_ERR(udc_clock)) { | ||
1817 | dev_err(dev, "failed to get udc clock source\n"); | ||
1818 | return PTR_ERR(udc_clock); | ||
1819 | } | ||
1820 | |||
1821 | clk_enable(udc_clock); | ||
1822 | |||
1823 | mdelay(10); | ||
1824 | |||
1825 | dev_dbg(dev, "got and enabled clocks\n"); | ||
1826 | |||
1827 | if (strncmp(pdev->name, "s3c2440", 7) == 0) { | ||
1828 | dev_info(dev, "S3C2440: increasing FIFO to 128 bytes\n"); | ||
1829 | memory.ep[1].fifo_size = S3C2440_EP_FIFO_SIZE; | ||
1830 | memory.ep[2].fifo_size = S3C2440_EP_FIFO_SIZE; | ||
1831 | memory.ep[3].fifo_size = S3C2440_EP_FIFO_SIZE; | ||
1832 | memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE; | ||
1833 | } | ||
1834 | |||
1835 | spin_lock_init (&udc->lock); | ||
1836 | udc_info = pdev->dev.platform_data; | ||
1837 | |||
1838 | rsrc_start = S3C2410_PA_USBDEV; | ||
1839 | rsrc_len = S3C24XX_SZ_USBDEV; | ||
1840 | |||
1841 | if (!request_mem_region(rsrc_start, rsrc_len, gadget_name)) | ||
1842 | return -EBUSY; | ||
1843 | |||
1844 | base_addr = ioremap(rsrc_start, rsrc_len); | ||
1845 | if (!base_addr) { | ||
1846 | retval = -ENOMEM; | ||
1847 | goto err_mem; | ||
1848 | } | ||
1849 | |||
1850 | device_initialize(&udc->gadget.dev); | ||
1851 | udc->gadget.dev.parent = &pdev->dev; | ||
1852 | udc->gadget.dev.dma_mask = pdev->dev.dma_mask; | ||
1853 | |||
1854 | the_controller = udc; | ||
1855 | platform_set_drvdata(pdev, udc); | ||
1856 | |||
1857 | s3c2410_udc_disable(udc); | ||
1858 | s3c2410_udc_reinit(udc); | ||
1859 | |||
1860 | /* irq setup after old hardware state is cleaned up */ | ||
1861 | retval = request_irq(IRQ_USBD, s3c2410_udc_irq, | ||
1862 | IRQF_DISABLED, gadget_name, udc); | ||
1863 | |||
1864 | if (retval != 0) { | ||
1865 | dev_err(dev, "cannot get irq %i, err %d\n", IRQ_USBD, retval); | ||
1866 | retval = -EBUSY; | ||
1867 | goto err_map; | ||
1868 | } | ||
1869 | |||
1870 | dev_dbg(dev, "got irq %i\n", IRQ_USBD); | ||
1871 | |||
1872 | if (udc_info && udc_info->vbus_pin > 0) { | ||
1873 | irq = s3c2410_gpio_getirq(udc_info->vbus_pin); | ||
1874 | retval = request_irq(irq, s3c2410_udc_vbus_irq, | ||
1875 | IRQF_DISABLED | IRQF_TRIGGER_RISING | ||
1876 | | IRQF_TRIGGER_FALLING, | ||
1877 | gadget_name, udc); | ||
1878 | |||
1879 | if (retval != 0) { | ||
1880 | dev_err(dev, "can't get vbus irq %i, err %d\n", | ||
1881 | irq, retval); | ||
1882 | retval = -EBUSY; | ||
1883 | goto err_int; | ||
1884 | } | ||
1885 | |||
1886 | dev_dbg(dev, "got irq %i\n", irq); | ||
1887 | } else { | ||
1888 | udc->vbus = 1; | ||
1889 | } | ||
1890 | |||
1891 | if (s3c2410_udc_debugfs_root) { | ||
1892 | udc->regs_info = debugfs_create_file("registers", S_IRUGO, | ||
1893 | s3c2410_udc_debugfs_root, | ||
1894 | udc, &s3c2410_udc_debugfs_fops); | ||
1895 | if (IS_ERR(udc->regs_info)) { | ||
1896 | dev_warn(dev, "debugfs file creation failed %ld\n", | ||
1897 | PTR_ERR(udc->regs_info)); | ||
1898 | udc->regs_info = NULL; | ||
1899 | } | ||
1900 | } | ||
1901 | |||
1902 | dev_dbg(dev, "probe ok\n"); | ||
1903 | |||
1904 | return 0; | ||
1905 | |||
1906 | err_int: | ||
1907 | free_irq(IRQ_USBD, udc); | ||
1908 | err_map: | ||
1909 | iounmap(base_addr); | ||
1910 | err_mem: | ||
1911 | release_mem_region(rsrc_start, rsrc_len); | ||
1912 | |||
1913 | return retval; | ||
1914 | } | ||
1915 | |||
1916 | /* | ||
1917 | * s3c2410_udc_remove | ||
1918 | */ | ||
1919 | static int s3c2410_udc_remove(struct platform_device *pdev) | ||
1920 | { | ||
1921 | struct s3c2410_udc *udc = platform_get_drvdata(pdev); | ||
1922 | unsigned int irq; | ||
1923 | |||
1924 | dev_dbg(&pdev->dev, "%s()\n", __func__); | ||
1925 | if (udc->driver) | ||
1926 | return -EBUSY; | ||
1927 | |||
1928 | debugfs_remove(udc->regs_info); | ||
1929 | |||
1930 | if (udc_info && udc_info->vbus_pin > 0) { | ||
1931 | irq = s3c2410_gpio_getirq(udc_info->vbus_pin); | ||
1932 | free_irq(irq, udc); | ||
1933 | } | ||
1934 | |||
1935 | free_irq(IRQ_USBD, udc); | ||
1936 | |||
1937 | iounmap(base_addr); | ||
1938 | release_mem_region(rsrc_start, rsrc_len); | ||
1939 | |||
1940 | platform_set_drvdata(pdev, NULL); | ||
1941 | |||
1942 | if (!IS_ERR(udc_clock) && udc_clock != NULL) { | ||
1943 | clk_disable(udc_clock); | ||
1944 | clk_put(udc_clock); | ||
1945 | udc_clock = NULL; | ||
1946 | } | ||
1947 | |||
1948 | if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) { | ||
1949 | clk_disable(usb_bus_clock); | ||
1950 | clk_put(usb_bus_clock); | ||
1951 | usb_bus_clock = NULL; | ||
1952 | } | ||
1953 | |||
1954 | dev_dbg(&pdev->dev, "%s: remove ok\n", __func__); | ||
1955 | return 0; | ||
1956 | } | ||
1957 | |||
1958 | #ifdef CONFIG_PM | ||
1959 | static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message) | ||
1960 | { | ||
1961 | if (udc_info && udc_info->udc_command) | ||
1962 | udc_info->udc_command(S3C2410_UDC_P_DISABLE); | ||
1963 | |||
1964 | return 0; | ||
1965 | } | ||
1966 | |||
1967 | static int s3c2410_udc_resume(struct platform_device *pdev) | ||
1968 | { | ||
1969 | if (udc_info && udc_info->udc_command) | ||
1970 | udc_info->udc_command(S3C2410_UDC_P_ENABLE); | ||
1971 | |||
1972 | return 0; | ||
1973 | } | ||
1974 | #else | ||
1975 | #define s3c2410_udc_suspend NULL | ||
1976 | #define s3c2410_udc_resume NULL | ||
1977 | #endif | ||
1978 | |||
1979 | static struct platform_driver udc_driver_2410 = { | ||
1980 | .driver = { | ||
1981 | .name = "s3c2410-usbgadget", | ||
1982 | .owner = THIS_MODULE, | ||
1983 | }, | ||
1984 | .probe = s3c2410_udc_probe, | ||
1985 | .remove = s3c2410_udc_remove, | ||
1986 | .suspend = s3c2410_udc_suspend, | ||
1987 | .resume = s3c2410_udc_resume, | ||
1988 | }; | ||
1989 | |||
1990 | static struct platform_driver udc_driver_2440 = { | ||
1991 | .driver = { | ||
1992 | .name = "s3c2440-usbgadget", | ||
1993 | .owner = THIS_MODULE, | ||
1994 | }, | ||
1995 | .probe = s3c2410_udc_probe, | ||
1996 | .remove = s3c2410_udc_remove, | ||
1997 | .suspend = s3c2410_udc_suspend, | ||
1998 | .resume = s3c2410_udc_resume, | ||
1999 | }; | ||
2000 | |||
2001 | static int __init udc_init(void) | ||
2002 | { | ||
2003 | int retval; | ||
2004 | |||
2005 | dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION); | ||
2006 | |||
2007 | s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL); | ||
2008 | if (IS_ERR(s3c2410_udc_debugfs_root)) { | ||
2009 | printk(KERN_ERR "%s: debugfs dir creation failed %ld\n", | ||
2010 | gadget_name, PTR_ERR(s3c2410_udc_debugfs_root)); | ||
2011 | s3c2410_udc_debugfs_root = NULL; | ||
2012 | } | ||
2013 | |||
2014 | retval = platform_driver_register(&udc_driver_2410); | ||
2015 | if (retval) | ||
2016 | goto err; | ||
2017 | |||
2018 | retval = platform_driver_register(&udc_driver_2440); | ||
2019 | if (retval) | ||
2020 | goto err; | ||
2021 | |||
2022 | return 0; | ||
2023 | |||
2024 | err: | ||
2025 | debugfs_remove(s3c2410_udc_debugfs_root); | ||
2026 | return retval; | ||
2027 | } | ||
2028 | |||
2029 | static void __exit udc_exit(void) | ||
2030 | { | ||
2031 | platform_driver_unregister(&udc_driver_2410); | ||
2032 | platform_driver_unregister(&udc_driver_2440); | ||
2033 | debugfs_remove(s3c2410_udc_debugfs_root); | ||
2034 | } | ||
2035 | |||
2036 | EXPORT_SYMBOL(usb_gadget_unregister_driver); | ||
2037 | EXPORT_SYMBOL(usb_gadget_register_driver); | ||
2038 | |||
2039 | module_init(udc_init); | ||
2040 | module_exit(udc_exit); | ||
2041 | |||
2042 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
2043 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
2044 | MODULE_VERSION(DRIVER_VERSION); | ||
2045 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/gadget/s3c2410_udc.h b/drivers/usb/gadget/s3c2410_udc.h new file mode 100644 index 000000000000..9e0bece4f241 --- /dev/null +++ b/drivers/usb/gadget/s3c2410_udc.h | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * linux/drivers/usb/gadget/s3c2410_udc.h | ||
3 | * Samsung on-chip full speed USB device controllers | ||
4 | * | ||
5 | * Copyright (C) 2004-2007 Herbert Pötzl - Arnaud Patard | ||
6 | * Additional cleanups by Ben Dooks <ben-linux@fluff.org> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #ifndef _S3C2410_UDC_H | ||
25 | #define _S3C2410_UDC_H | ||
26 | |||
27 | struct s3c2410_ep { | ||
28 | struct list_head queue; | ||
29 | unsigned long last_io; /* jiffies timestamp */ | ||
30 | struct usb_gadget *gadget; | ||
31 | struct s3c2410_udc *dev; | ||
32 | const struct usb_endpoint_descriptor *desc; | ||
33 | struct usb_ep ep; | ||
34 | u8 num; | ||
35 | |||
36 | unsigned short fifo_size; | ||
37 | u8 bEndpointAddress; | ||
38 | u8 bmAttributes; | ||
39 | |||
40 | unsigned halted : 1; | ||
41 | unsigned already_seen : 1; | ||
42 | unsigned setup_stage : 1; | ||
43 | }; | ||
44 | |||
45 | |||
46 | /* Warning : ep0 has a fifo of 16 bytes */ | ||
47 | /* Don't try to set 32 or 64 */ | ||
48 | /* also testusb 14 fails wit 16 but is */ | ||
49 | /* fine with 8 */ | ||
50 | #define EP0_FIFO_SIZE 8 | ||
51 | #define EP_FIFO_SIZE 64 | ||
52 | #define DEFAULT_POWER_STATE 0x00 | ||
53 | |||
54 | #define S3C2440_EP_FIFO_SIZE 128 | ||
55 | |||
56 | static const char ep0name [] = "ep0"; | ||
57 | |||
58 | static const char *const ep_name[] = { | ||
59 | ep0name, /* everyone has ep0 */ | ||
60 | /* s3c2410 four bidirectional bulk endpoints */ | ||
61 | "ep1-bulk", "ep2-bulk", "ep3-bulk", "ep4-bulk", | ||
62 | }; | ||
63 | |||
64 | #define S3C2410_ENDPOINTS ARRAY_SIZE(ep_name) | ||
65 | |||
66 | struct s3c2410_request { | ||
67 | struct list_head queue; /* ep's requests */ | ||
68 | struct usb_request req; | ||
69 | }; | ||
70 | |||
71 | enum ep0_state { | ||
72 | EP0_IDLE, | ||
73 | EP0_IN_DATA_PHASE, | ||
74 | EP0_OUT_DATA_PHASE, | ||
75 | EP0_END_XFER, | ||
76 | EP0_STALL, | ||
77 | }; | ||
78 | |||
79 | static const char *ep0states[]= { | ||
80 | "EP0_IDLE", | ||
81 | "EP0_IN_DATA_PHASE", | ||
82 | "EP0_OUT_DATA_PHASE", | ||
83 | "EP0_END_XFER", | ||
84 | "EP0_STALL", | ||
85 | }; | ||
86 | |||
87 | struct s3c2410_udc { | ||
88 | spinlock_t lock; | ||
89 | |||
90 | struct s3c2410_ep ep[S3C2410_ENDPOINTS]; | ||
91 | int address; | ||
92 | struct usb_gadget gadget; | ||
93 | struct usb_gadget_driver *driver; | ||
94 | struct s3c2410_request fifo_req; | ||
95 | u8 fifo_buf[EP_FIFO_SIZE]; | ||
96 | u16 devstatus; | ||
97 | |||
98 | u32 port_status; | ||
99 | int ep0state; | ||
100 | |||
101 | unsigned got_irq : 1; | ||
102 | |||
103 | unsigned req_std : 1; | ||
104 | unsigned req_config : 1; | ||
105 | unsigned req_pending : 1; | ||
106 | u8 vbus; | ||
107 | struct dentry *regs_info; | ||
108 | }; | ||
109 | |||
110 | #endif | ||
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index f847c3414be3..dd33ff0ae4ce 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -2215,7 +2215,7 @@ static struct gs_buf *gs_buf_alloc(unsigned int size, gfp_t kmalloc_flags) | |||
2215 | * | 2215 | * |
2216 | * Free the buffer and all associated memory. | 2216 | * Free the buffer and all associated memory. |
2217 | */ | 2217 | */ |
2218 | void gs_buf_free(struct gs_buf *gb) | 2218 | static void gs_buf_free(struct gs_buf *gb) |
2219 | { | 2219 | { |
2220 | if (gb) { | 2220 | if (gb) { |
2221 | kfree(gb->buf_buf); | 2221 | kfree(gb->buf_buf); |
@@ -2228,7 +2228,7 @@ void gs_buf_free(struct gs_buf *gb) | |||
2228 | * | 2228 | * |
2229 | * Clear out all data in the circular buffer. | 2229 | * Clear out all data in the circular buffer. |
2230 | */ | 2230 | */ |
2231 | void gs_buf_clear(struct gs_buf *gb) | 2231 | static void gs_buf_clear(struct gs_buf *gb) |
2232 | { | 2232 | { |
2233 | if (gb != NULL) | 2233 | if (gb != NULL) |
2234 | gb->buf_get = gb->buf_put; | 2234 | gb->buf_get = gb->buf_put; |
@@ -2241,7 +2241,7 @@ void gs_buf_clear(struct gs_buf *gb) | |||
2241 | * Return the number of bytes of data available in the circular | 2241 | * Return the number of bytes of data available in the circular |
2242 | * buffer. | 2242 | * buffer. |
2243 | */ | 2243 | */ |
2244 | unsigned int gs_buf_data_avail(struct gs_buf *gb) | 2244 | static unsigned int gs_buf_data_avail(struct gs_buf *gb) |
2245 | { | 2245 | { |
2246 | if (gb != NULL) | 2246 | if (gb != NULL) |
2247 | return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size; | 2247 | return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size; |
@@ -2255,7 +2255,7 @@ unsigned int gs_buf_data_avail(struct gs_buf *gb) | |||
2255 | * Return the number of bytes of space available in the circular | 2255 | * Return the number of bytes of space available in the circular |
2256 | * buffer. | 2256 | * buffer. |
2257 | */ | 2257 | */ |
2258 | unsigned int gs_buf_space_avail(struct gs_buf *gb) | 2258 | static unsigned int gs_buf_space_avail(struct gs_buf *gb) |
2259 | { | 2259 | { |
2260 | if (gb != NULL) | 2260 | if (gb != NULL) |
2261 | return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size; | 2261 | return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size; |
@@ -2271,7 +2271,8 @@ unsigned int gs_buf_space_avail(struct gs_buf *gb) | |||
2271 | * | 2271 | * |
2272 | * Return the number of bytes copied. | 2272 | * Return the number of bytes copied. |
2273 | */ | 2273 | */ |
2274 | unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count) | 2274 | static unsigned int |
2275 | gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count) | ||
2275 | { | 2276 | { |
2276 | unsigned int len; | 2277 | unsigned int len; |
2277 | 2278 | ||
@@ -2309,7 +2310,8 @@ unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count) | |||
2309 | * | 2310 | * |
2310 | * Return the number of bytes copied. | 2311 | * Return the number of bytes copied. |
2311 | */ | 2312 | */ |
2312 | unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count) | 2313 | static unsigned int |
2314 | gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count) | ||
2313 | { | 2315 | { |
2314 | unsigned int len; | 2316 | unsigned int len; |
2315 | 2317 | ||
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 7078374d0b79..a2e6e3fc8c8d 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c | |||
@@ -481,8 +481,7 @@ alloc_ep_req (struct usb_ep *ep, unsigned length) | |||
481 | req = usb_ep_alloc_request (ep, GFP_ATOMIC); | 481 | req = usb_ep_alloc_request (ep, GFP_ATOMIC); |
482 | if (req) { | 482 | if (req) { |
483 | req->length = length; | 483 | req->length = length; |
484 | req->buf = usb_ep_alloc_buffer (ep, length, | 484 | req->buf = kmalloc(length, GFP_ATOMIC); |
485 | &req->dma, GFP_ATOMIC); | ||
486 | if (!req->buf) { | 485 | if (!req->buf) { |
487 | usb_ep_free_request (ep, req); | 486 | usb_ep_free_request (ep, req); |
488 | req = NULL; | 487 | req = NULL; |
@@ -493,8 +492,7 @@ alloc_ep_req (struct usb_ep *ep, unsigned length) | |||
493 | 492 | ||
494 | static void free_ep_req (struct usb_ep *ep, struct usb_request *req) | 493 | static void free_ep_req (struct usb_ep *ep, struct usb_request *req) |
495 | { | 494 | { |
496 | if (req->buf) | 495 | kfree(req->buf); |
497 | usb_ep_free_buffer (ep, req->buf, req->dma, req->length); | ||
498 | usb_ep_free_request (ep, req); | 496 | usb_ep_free_request (ep, req); |
499 | } | 497 | } |
500 | 498 | ||
@@ -1199,8 +1197,7 @@ autoconf_fail: | |||
1199 | dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL); | 1197 | dev->req = usb_ep_alloc_request (gadget->ep0, GFP_KERNEL); |
1200 | if (!dev->req) | 1198 | if (!dev->req) |
1201 | goto enomem; | 1199 | goto enomem; |
1202 | dev->req->buf = usb_ep_alloc_buffer (gadget->ep0, USB_BUFSIZ, | 1200 | dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); |
1203 | &dev->req->dma, GFP_KERNEL); | ||
1204 | if (!dev->req->buf) | 1201 | if (!dev->req->buf) |
1205 | goto enomem; | 1202 | goto enomem; |
1206 | 1203 | ||
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 62711870f8ee..2f529828c74d 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -69,8 +69,20 @@ config USB_EHCI_TT_NEWSCHED | |||
69 | 69 | ||
70 | config USB_EHCI_BIG_ENDIAN_MMIO | 70 | config USB_EHCI_BIG_ENDIAN_MMIO |
71 | bool | 71 | bool |
72 | depends on USB_EHCI_HCD | 72 | depends on USB_EHCI_HCD && (PPC_CELLEB || PPC_PS3 || 440EPX) |
73 | default n | 73 | default y |
74 | |||
75 | config USB_EHCI_BIG_ENDIAN_DESC | ||
76 | bool | ||
77 | depends on USB_EHCI_HCD && 440EPX | ||
78 | default y | ||
79 | |||
80 | config USB_EHCI_FSL | ||
81 | bool | ||
82 | select USB_EHCI_ROOT_HUB_TT | ||
83 | default y if MPC834x || PPC_MPC831x | ||
84 | ---help--- | ||
85 | Variation of ARC USB block used in some Freescale chips. | ||
74 | 86 | ||
75 | config USB_ISP116X_HCD | 87 | config USB_ISP116X_HCD |
76 | tristate "ISP116X HCD support" | 88 | tristate "ISP116X HCD support" |
@@ -224,3 +236,15 @@ config USB_SL811_CS | |||
224 | To compile this driver as a module, choose M here: the | 236 | To compile this driver as a module, choose M here: the |
225 | module will be called "sl811_cs". | 237 | module will be called "sl811_cs". |
226 | 238 | ||
239 | config USB_R8A66597_HCD | ||
240 | tristate "R8A66597 HCD suppoort" | ||
241 | depends on USB | ||
242 | help | ||
243 | The R8A66597 is a USB 2.0 host and peripheral controller. | ||
244 | |||
245 | Enable this option if your board has this chip, and you want | ||
246 | to use it as a host controller. If unsure, say N. | ||
247 | |||
248 | To compile this driver as a module, choose M here: the | ||
249 | module will be called r8a66597-hcd. | ||
250 | |||
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 2ff396bd180f..bb8e9d44f371 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -15,3 +15,5 @@ obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o | |||
15 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o | 15 | obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o |
16 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o | 16 | obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o |
17 | obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o | 17 | obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o |
18 | obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o | ||
19 | |||
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 43eddaecc3dd..c9cc4413198e 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c | |||
@@ -52,7 +52,7 @@ static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) | |||
52 | HCS_INDICATOR (params) ? " ind" : "", | 52 | HCS_INDICATOR (params) ? " ind" : "", |
53 | HCS_N_CC (params), | 53 | HCS_N_CC (params), |
54 | HCS_N_PCC (params), | 54 | HCS_N_PCC (params), |
55 | HCS_PORTROUTED (params) ? "" : " ordered", | 55 | HCS_PORTROUTED (params) ? "" : " ordered", |
56 | HCS_PPC (params) ? "" : " !ppc", | 56 | HCS_PPC (params) ? "" : " !ppc", |
57 | HCS_N_PORTS (params) | 57 | HCS_N_PORTS (params) |
58 | ); | 58 | ); |
@@ -91,20 +91,20 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) | |||
91 | 91 | ||
92 | if (HCC_ISOC_CACHE (params)) { | 92 | if (HCC_ISOC_CACHE (params)) { |
93 | ehci_dbg (ehci, | 93 | ehci_dbg (ehci, |
94 | "%s hcc_params %04x caching frame %s%s%s\n", | 94 | "%s hcc_params %04x caching frame %s%s%s\n", |
95 | label, params, | 95 | label, params, |
96 | HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024", | 96 | HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", |
97 | HCC_CANPARK (params) ? " park" : "", | 97 | HCC_CANPARK(params) ? " park" : "", |
98 | HCC_64BIT_ADDR (params) ? " 64 bit addr" : ""); | 98 | HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); |
99 | } else { | 99 | } else { |
100 | ehci_dbg (ehci, | 100 | ehci_dbg (ehci, |
101 | "%s hcc_params %04x thresh %d uframes %s%s%s\n", | 101 | "%s hcc_params %04x thresh %d uframes %s%s%s\n", |
102 | label, | 102 | label, |
103 | params, | 103 | params, |
104 | HCC_ISOC_THRES (params), | 104 | HCC_ISOC_THRES(params), |
105 | HCC_PGM_FRAMELISTLEN (params) ? "256/512/1024" : "1024", | 105 | HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", |
106 | HCC_CANPARK (params) ? " park" : "", | 106 | HCC_CANPARK(params) ? " park" : "", |
107 | HCC_64BIT_ADDR (params) ? " 64 bit addr" : ""); | 107 | HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); |
108 | } | 108 | } |
109 | } | 109 | } |
110 | #else | 110 | #else |
@@ -115,23 +115,23 @@ static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} | |||
115 | 115 | ||
116 | #ifdef DEBUG | 116 | #ifdef DEBUG |
117 | 117 | ||
118 | static void __attribute__((__unused__)) | 118 | static void __maybe_unused |
119 | dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) | 119 | dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) |
120 | { | 120 | { |
121 | ehci_dbg (ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, | 121 | ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, |
122 | le32_to_cpup (&qtd->hw_next), | 122 | hc32_to_cpup(ehci, &qtd->hw_next), |
123 | le32_to_cpup (&qtd->hw_alt_next), | 123 | hc32_to_cpup(ehci, &qtd->hw_alt_next), |
124 | le32_to_cpup (&qtd->hw_token), | 124 | hc32_to_cpup(ehci, &qtd->hw_token), |
125 | le32_to_cpup (&qtd->hw_buf [0])); | 125 | hc32_to_cpup(ehci, &qtd->hw_buf [0])); |
126 | if (qtd->hw_buf [1]) | 126 | if (qtd->hw_buf [1]) |
127 | ehci_dbg (ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n", | 127 | ehci_dbg(ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n", |
128 | le32_to_cpup (&qtd->hw_buf [1]), | 128 | hc32_to_cpup(ehci, &qtd->hw_buf[1]), |
129 | le32_to_cpup (&qtd->hw_buf [2]), | 129 | hc32_to_cpup(ehci, &qtd->hw_buf[2]), |
130 | le32_to_cpup (&qtd->hw_buf [3]), | 130 | hc32_to_cpup(ehci, &qtd->hw_buf[3]), |
131 | le32_to_cpup (&qtd->hw_buf [4])); | 131 | hc32_to_cpup(ehci, &qtd->hw_buf[4])); |
132 | } | 132 | } |
133 | 133 | ||
134 | static void __attribute__((__unused__)) | 134 | static void __maybe_unused |
135 | dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) | 135 | dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) |
136 | { | 136 | { |
137 | ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, | 137 | ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, |
@@ -140,51 +140,53 @@ dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
140 | dbg_qtd ("overlay", ehci, (struct ehci_qtd *) &qh->hw_qtd_next); | 140 | dbg_qtd ("overlay", ehci, (struct ehci_qtd *) &qh->hw_qtd_next); |
141 | } | 141 | } |
142 | 142 | ||
143 | static void __attribute__((__unused__)) | 143 | static void __maybe_unused |
144 | dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) | 144 | dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) |
145 | { | 145 | { |
146 | ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n", | 146 | ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n", |
147 | label, itd->frame, itd, le32_to_cpu(itd->hw_next), itd->urb); | 147 | label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next), |
148 | itd->urb); | ||
148 | ehci_dbg (ehci, | 149 | ehci_dbg (ehci, |
149 | " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", | 150 | " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", |
150 | le32_to_cpu(itd->hw_transaction[0]), | 151 | hc32_to_cpu(ehci, itd->hw_transaction[0]), |
151 | le32_to_cpu(itd->hw_transaction[1]), | 152 | hc32_to_cpu(ehci, itd->hw_transaction[1]), |
152 | le32_to_cpu(itd->hw_transaction[2]), | 153 | hc32_to_cpu(ehci, itd->hw_transaction[2]), |
153 | le32_to_cpu(itd->hw_transaction[3]), | 154 | hc32_to_cpu(ehci, itd->hw_transaction[3]), |
154 | le32_to_cpu(itd->hw_transaction[4]), | 155 | hc32_to_cpu(ehci, itd->hw_transaction[4]), |
155 | le32_to_cpu(itd->hw_transaction[5]), | 156 | hc32_to_cpu(ehci, itd->hw_transaction[5]), |
156 | le32_to_cpu(itd->hw_transaction[6]), | 157 | hc32_to_cpu(ehci, itd->hw_transaction[6]), |
157 | le32_to_cpu(itd->hw_transaction[7])); | 158 | hc32_to_cpu(ehci, itd->hw_transaction[7])); |
158 | ehci_dbg (ehci, | 159 | ehci_dbg (ehci, |
159 | " buf: %08x %08x %08x %08x %08x %08x %08x\n", | 160 | " buf: %08x %08x %08x %08x %08x %08x %08x\n", |
160 | le32_to_cpu(itd->hw_bufp[0]), | 161 | hc32_to_cpu(ehci, itd->hw_bufp[0]), |
161 | le32_to_cpu(itd->hw_bufp[1]), | 162 | hc32_to_cpu(ehci, itd->hw_bufp[1]), |
162 | le32_to_cpu(itd->hw_bufp[2]), | 163 | hc32_to_cpu(ehci, itd->hw_bufp[2]), |
163 | le32_to_cpu(itd->hw_bufp[3]), | 164 | hc32_to_cpu(ehci, itd->hw_bufp[3]), |
164 | le32_to_cpu(itd->hw_bufp[4]), | 165 | hc32_to_cpu(ehci, itd->hw_bufp[4]), |
165 | le32_to_cpu(itd->hw_bufp[5]), | 166 | hc32_to_cpu(ehci, itd->hw_bufp[5]), |
166 | le32_to_cpu(itd->hw_bufp[6])); | 167 | hc32_to_cpu(ehci, itd->hw_bufp[6])); |
167 | ehci_dbg (ehci, " index: %d %d %d %d %d %d %d %d\n", | 168 | ehci_dbg (ehci, " index: %d %d %d %d %d %d %d %d\n", |
168 | itd->index[0], itd->index[1], itd->index[2], | 169 | itd->index[0], itd->index[1], itd->index[2], |
169 | itd->index[3], itd->index[4], itd->index[5], | 170 | itd->index[3], itd->index[4], itd->index[5], |
170 | itd->index[6], itd->index[7]); | 171 | itd->index[6], itd->index[7]); |
171 | } | 172 | } |
172 | 173 | ||
173 | static void __attribute__((__unused__)) | 174 | static void __maybe_unused |
174 | dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) | 175 | dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) |
175 | { | 176 | { |
176 | ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n", | 177 | ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n", |
177 | label, sitd->frame, sitd, le32_to_cpu(sitd->hw_next), sitd->urb); | 178 | label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next), |
179 | sitd->urb); | ||
178 | ehci_dbg (ehci, | 180 | ehci_dbg (ehci, |
179 | " addr %08x sched %04x result %08x buf %08x %08x\n", | 181 | " addr %08x sched %04x result %08x buf %08x %08x\n", |
180 | le32_to_cpu(sitd->hw_fullspeed_ep), | 182 | hc32_to_cpu(ehci, sitd->hw_fullspeed_ep), |
181 | le32_to_cpu(sitd->hw_uframe), | 183 | hc32_to_cpu(ehci, sitd->hw_uframe), |
182 | le32_to_cpu(sitd->hw_results), | 184 | hc32_to_cpu(ehci, sitd->hw_results), |
183 | le32_to_cpu(sitd->hw_buf [0]), | 185 | hc32_to_cpu(ehci, sitd->hw_buf[0]), |
184 | le32_to_cpu(sitd->hw_buf [1])); | 186 | hc32_to_cpu(ehci, sitd->hw_buf[1])); |
185 | } | 187 | } |
186 | 188 | ||
187 | static int __attribute__((__unused__)) | 189 | static int __maybe_unused |
188 | dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) | 190 | dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) |
189 | { | 191 | { |
190 | return scnprintf (buf, len, | 192 | return scnprintf (buf, len, |
@@ -203,7 +205,7 @@ dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) | |||
203 | ); | 205 | ); |
204 | } | 206 | } |
205 | 207 | ||
206 | static int __attribute__((__unused__)) | 208 | static int __maybe_unused |
207 | dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) | 209 | dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) |
208 | { | 210 | { |
209 | return scnprintf (buf, len, | 211 | return scnprintf (buf, len, |
@@ -267,28 +269,27 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) | |||
267 | (status & PORT_PEC) ? " PEC" : "", | 269 | (status & PORT_PEC) ? " PEC" : "", |
268 | (status & PORT_PE) ? " PE" : "", | 270 | (status & PORT_PE) ? " PE" : "", |
269 | (status & PORT_CSC) ? " CSC" : "", | 271 | (status & PORT_CSC) ? " CSC" : "", |
270 | (status & PORT_CONNECT) ? " CONNECT" : "" | 272 | (status & PORT_CONNECT) ? " CONNECT" : ""); |
271 | ); | ||
272 | } | 273 | } |
273 | 274 | ||
274 | #else | 275 | #else |
275 | static inline void __attribute__((__unused__)) | 276 | static inline void __maybe_unused |
276 | dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) | 277 | dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) |
277 | {} | 278 | {} |
278 | 279 | ||
279 | static inline int __attribute__((__unused__)) | 280 | static inline int __maybe_unused |
280 | dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) | 281 | dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) |
281 | { return 0; } | 282 | { return 0; } |
282 | 283 | ||
283 | static inline int __attribute__((__unused__)) | 284 | static inline int __maybe_unused |
284 | dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) | 285 | dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) |
285 | { return 0; } | 286 | { return 0; } |
286 | 287 | ||
287 | static inline int __attribute__((__unused__)) | 288 | static inline int __maybe_unused |
288 | dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) | 289 | dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) |
289 | { return 0; } | 290 | { return 0; } |
290 | 291 | ||
291 | static inline int __attribute__((__unused__)) | 292 | static inline int __maybe_unused |
292 | dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) | 293 | dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) |
293 | { return 0; } | 294 | { return 0; } |
294 | 295 | ||
@@ -332,9 +333,10 @@ static inline void remove_debug_files (struct ehci_hcd *bus) { } | |||
332 | default: tmp = '?'; break; \ | 333 | default: tmp = '?'; break; \ |
333 | }; tmp; }) | 334 | }; tmp; }) |
334 | 335 | ||
335 | static inline char token_mark (__le32 token) | 336 | static inline char token_mark(struct ehci_hcd *ehci, __hc32 token) |
336 | { | 337 | { |
337 | __u32 v = le32_to_cpu (token); | 338 | __u32 v = hc32_to_cpu(ehci, token); |
339 | |||
338 | if (v & QTD_STS_ACTIVE) | 340 | if (v & QTD_STS_ACTIVE) |
339 | return '*'; | 341 | return '*'; |
340 | if (v & QTD_STS_HALT) | 342 | if (v & QTD_STS_HALT) |
@@ -360,46 +362,48 @@ static void qh_lines ( | |||
360 | unsigned size = *sizep; | 362 | unsigned size = *sizep; |
361 | char *next = *nextp; | 363 | char *next = *nextp; |
362 | char mark; | 364 | char mark; |
365 | u32 list_end = EHCI_LIST_END(ehci); | ||
363 | 366 | ||
364 | if (qh->hw_qtd_next == EHCI_LIST_END) /* NEC does this */ | 367 | if (qh->hw_qtd_next == list_end) /* NEC does this */ |
365 | mark = '@'; | 368 | mark = '@'; |
366 | else | 369 | else |
367 | mark = token_mark (qh->hw_token); | 370 | mark = token_mark(ehci, qh->hw_token); |
368 | if (mark == '/') { /* qh_alt_next controls qh advance? */ | 371 | if (mark == '/') { /* qh_alt_next controls qh advance? */ |
369 | if ((qh->hw_alt_next & QTD_MASK) == ehci->async->hw_alt_next) | 372 | if ((qh->hw_alt_next & QTD_MASK(ehci)) |
373 | == ehci->async->hw_alt_next) | ||
370 | mark = '#'; /* blocked */ | 374 | mark = '#'; /* blocked */ |
371 | else if (qh->hw_alt_next == EHCI_LIST_END) | 375 | else if (qh->hw_alt_next == list_end) |
372 | mark = '.'; /* use hw_qtd_next */ | 376 | mark = '.'; /* use hw_qtd_next */ |
373 | /* else alt_next points to some other qtd */ | 377 | /* else alt_next points to some other qtd */ |
374 | } | 378 | } |
375 | scratch = le32_to_cpup (&qh->hw_info1); | 379 | scratch = hc32_to_cpup(ehci, &qh->hw_info1); |
376 | hw_curr = (mark == '*') ? le32_to_cpup (&qh->hw_current) : 0; | 380 | hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &qh->hw_current) : 0; |
377 | temp = scnprintf (next, size, | 381 | temp = scnprintf (next, size, |
378 | "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", | 382 | "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", |
379 | qh, scratch & 0x007f, | 383 | qh, scratch & 0x007f, |
380 | speed_char (scratch), | 384 | speed_char (scratch), |
381 | (scratch >> 8) & 0x000f, | 385 | (scratch >> 8) & 0x000f, |
382 | scratch, le32_to_cpup (&qh->hw_info2), | 386 | scratch, hc32_to_cpup(ehci, &qh->hw_info2), |
383 | le32_to_cpup (&qh->hw_token), mark, | 387 | hc32_to_cpup(ehci, &qh->hw_token), mark, |
384 | (__constant_cpu_to_le32 (QTD_TOGGLE) & qh->hw_token) | 388 | (cpu_to_hc32(ehci, QTD_TOGGLE) & qh->hw_token) |
385 | ? "data1" : "data0", | 389 | ? "data1" : "data0", |
386 | (le32_to_cpup (&qh->hw_alt_next) >> 1) & 0x0f); | 390 | (hc32_to_cpup(ehci, &qh->hw_alt_next) >> 1) & 0x0f); |
387 | size -= temp; | 391 | size -= temp; |
388 | next += temp; | 392 | next += temp; |
389 | 393 | ||
390 | /* hc may be modifying the list as we read it ... */ | 394 | /* hc may be modifying the list as we read it ... */ |
391 | list_for_each (entry, &qh->qtd_list) { | 395 | list_for_each (entry, &qh->qtd_list) { |
392 | td = list_entry (entry, struct ehci_qtd, qtd_list); | 396 | td = list_entry (entry, struct ehci_qtd, qtd_list); |
393 | scratch = le32_to_cpup (&td->hw_token); | 397 | scratch = hc32_to_cpup(ehci, &td->hw_token); |
394 | mark = ' '; | 398 | mark = ' '; |
395 | if (hw_curr == td->qtd_dma) | 399 | if (hw_curr == td->qtd_dma) |
396 | mark = '*'; | 400 | mark = '*'; |
397 | else if (qh->hw_qtd_next == cpu_to_le32(td->qtd_dma)) | 401 | else if (qh->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) |
398 | mark = '+'; | 402 | mark = '+'; |
399 | else if (QTD_LENGTH (scratch)) { | 403 | else if (QTD_LENGTH (scratch)) { |
400 | if (td->hw_alt_next == ehci->async->hw_alt_next) | 404 | if (td->hw_alt_next == ehci->async->hw_alt_next) |
401 | mark = '#'; | 405 | mark = '#'; |
402 | else if (td->hw_alt_next != EHCI_LIST_END) | 406 | else if (td->hw_alt_next != list_end) |
403 | mark = '/'; | 407 | mark = '/'; |
404 | } | 408 | } |
405 | temp = snprintf (next, size, | 409 | temp = snprintf (next, size, |
@@ -490,7 +494,7 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
490 | unsigned temp, size, seen_count; | 494 | unsigned temp, size, seen_count; |
491 | char *next; | 495 | char *next; |
492 | unsigned i; | 496 | unsigned i; |
493 | __le32 tag; | 497 | __hc32 tag; |
494 | 498 | ||
495 | if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC))) | 499 | if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC))) |
496 | return 0; | 500 | return 0; |
@@ -514,18 +518,19 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
514 | p = ehci->pshadow [i]; | 518 | p = ehci->pshadow [i]; |
515 | if (likely (!p.ptr)) | 519 | if (likely (!p.ptr)) |
516 | continue; | 520 | continue; |
517 | tag = Q_NEXT_TYPE (ehci->periodic [i]); | 521 | tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]); |
518 | 522 | ||
519 | temp = scnprintf (next, size, "%4d: ", i); | 523 | temp = scnprintf (next, size, "%4d: ", i); |
520 | size -= temp; | 524 | size -= temp; |
521 | next += temp; | 525 | next += temp; |
522 | 526 | ||
523 | do { | 527 | do { |
524 | switch (tag) { | 528 | switch (hc32_to_cpu(ehci, tag)) { |
525 | case Q_TYPE_QH: | 529 | case Q_TYPE_QH: |
526 | temp = scnprintf (next, size, " qh%d-%04x/%p", | 530 | temp = scnprintf (next, size, " qh%d-%04x/%p", |
527 | p.qh->period, | 531 | p.qh->period, |
528 | le32_to_cpup (&p.qh->hw_info2) | 532 | hc32_to_cpup(ehci, |
533 | &p.qh->hw_info2) | ||
529 | /* uframe masks */ | 534 | /* uframe masks */ |
530 | & (QH_CMASK | QH_SMASK), | 535 | & (QH_CMASK | QH_SMASK), |
531 | p.qh); | 536 | p.qh); |
@@ -543,7 +548,7 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
543 | } | 548 | } |
544 | /* show more info the first time around */ | 549 | /* show more info the first time around */ |
545 | if (temp == seen_count && p.ptr) { | 550 | if (temp == seen_count && p.ptr) { |
546 | u32 scratch = le32_to_cpup ( | 551 | u32 scratch = hc32_to_cpup(ehci, |
547 | &p.qh->hw_info1); | 552 | &p.qh->hw_info1); |
548 | struct ehci_qtd *qtd; | 553 | struct ehci_qtd *qtd; |
549 | char *type = ""; | 554 | char *type = ""; |
@@ -554,7 +559,8 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
554 | &p.qh->qtd_list, | 559 | &p.qh->qtd_list, |
555 | qtd_list) { | 560 | qtd_list) { |
556 | temp++; | 561 | temp++; |
557 | switch (0x03 & (le32_to_cpu ( | 562 | switch (0x03 & (hc32_to_cpu( |
563 | ehci, | ||
558 | qtd->hw_token) >> 8)) { | 564 | qtd->hw_token) >> 8)) { |
559 | case 0: type = "out"; continue; | 565 | case 0: type = "out"; continue; |
560 | case 1: type = "in"; continue; | 566 | case 1: type = "in"; continue; |
@@ -576,7 +582,7 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
576 | } else | 582 | } else |
577 | temp = 0; | 583 | temp = 0; |
578 | if (p.qh) { | 584 | if (p.qh) { |
579 | tag = Q_NEXT_TYPE (p.qh->hw_next); | 585 | tag = Q_NEXT_TYPE(ehci, p.qh->hw_next); |
580 | p = p.qh->qh_next; | 586 | p = p.qh->qh_next; |
581 | } | 587 | } |
582 | break; | 588 | break; |
@@ -584,23 +590,23 @@ show_periodic (struct class_device *class_dev, char *buf) | |||
584 | temp = scnprintf (next, size, | 590 | temp = scnprintf (next, size, |
585 | " fstn-%8x/%p", p.fstn->hw_prev, | 591 | " fstn-%8x/%p", p.fstn->hw_prev, |
586 | p.fstn); | 592 | p.fstn); |
587 | tag = Q_NEXT_TYPE (p.fstn->hw_next); | 593 | tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next); |
588 | p = p.fstn->fstn_next; | 594 | p = p.fstn->fstn_next; |
589 | break; | 595 | break; |
590 | case Q_TYPE_ITD: | 596 | case Q_TYPE_ITD: |
591 | temp = scnprintf (next, size, | 597 | temp = scnprintf (next, size, |
592 | " itd/%p", p.itd); | 598 | " itd/%p", p.itd); |
593 | tag = Q_NEXT_TYPE (p.itd->hw_next); | 599 | tag = Q_NEXT_TYPE(ehci, p.itd->hw_next); |
594 | p = p.itd->itd_next; | 600 | p = p.itd->itd_next; |
595 | break; | 601 | break; |
596 | case Q_TYPE_SITD: | 602 | case Q_TYPE_SITD: |
597 | temp = scnprintf (next, size, | 603 | temp = scnprintf (next, size, |
598 | " sitd%d-%04x/%p", | 604 | " sitd%d-%04x/%p", |
599 | p.sitd->stream->interval, | 605 | p.sitd->stream->interval, |
600 | le32_to_cpup (&p.sitd->hw_uframe) | 606 | hc32_to_cpup(ehci, &p.sitd->hw_uframe) |
601 | & 0x0000ffff, | 607 | & 0x0000ffff, |
602 | p.sitd); | 608 | p.sitd); |
603 | tag = Q_NEXT_TYPE (p.sitd->hw_next); | 609 | tag = Q_NEXT_TYPE(ehci, p.sitd->hw_next); |
604 | p = p.sitd->sitd_next; | 610 | p = p.sitd->sitd_next; |
605 | break; | 611 | break; |
606 | } | 612 | } |
@@ -673,7 +679,8 @@ show_registers (struct class_device *class_dev, char *buf) | |||
673 | unsigned count = 256/4; | 679 | unsigned count = 256/4; |
674 | 680 | ||
675 | pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); | 681 | pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); |
676 | offset = HCC_EXT_CAPS (ehci_readl(ehci, &ehci->caps->hcc_params)); | 682 | offset = HCC_EXT_CAPS(ehci_readl(ehci, |
683 | &ehci->caps->hcc_params)); | ||
677 | while (offset && count--) { | 684 | while (offset && count--) { |
678 | pci_read_config_dword (pdev, offset, &cap); | 685 | pci_read_config_dword (pdev, offset, &cap); |
679 | switch (cap & 0xff) { | 686 | switch (cap & 0xff) { |
@@ -740,14 +747,16 @@ show_registers (struct class_device *class_dev, char *buf) | |||
740 | 747 | ||
741 | for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { | 748 | for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { |
742 | temp = dbg_port_buf (scratch, sizeof scratch, label, i, | 749 | temp = dbg_port_buf (scratch, sizeof scratch, label, i, |
743 | ehci_readl(ehci, &ehci->regs->port_status [i - 1])); | 750 | ehci_readl(ehci, |
751 | &ehci->regs->port_status[i - 1])); | ||
744 | temp = scnprintf (next, size, fmt, temp, scratch); | 752 | temp = scnprintf (next, size, fmt, temp, scratch); |
745 | size -= temp; | 753 | size -= temp; |
746 | next += temp; | 754 | next += temp; |
747 | if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { | 755 | if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { |
748 | temp = scnprintf (next, size, | 756 | temp = scnprintf (next, size, |
749 | " debug control %08x\n", | 757 | " debug control %08x\n", |
750 | ehci_readl(ehci, &ehci->debug->control)); | 758 | ehci_readl(ehci, |
759 | &ehci->debug->control)); | ||
751 | size -= temp; | 760 | size -= temp; |
752 | next += temp; | 761 | next += temp; |
753 | } | 762 | } |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index c7a7c590426f..b7b7bfbce527 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -67,7 +67,8 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver, | |||
67 | * in host mode. | 67 | * in host mode. |
68 | */ | 68 | */ |
69 | if (!((pdata->operating_mode == FSL_USB2_DR_HOST) || | 69 | if (!((pdata->operating_mode == FSL_USB2_DR_HOST) || |
70 | (pdata->operating_mode == FSL_USB2_MPH_HOST))) { | 70 | (pdata->operating_mode == FSL_USB2_MPH_HOST) || |
71 | (pdata->operating_mode == FSL_USB2_DR_OTG))) { | ||
71 | dev_err(&pdev->dev, | 72 | dev_err(&pdev->dev, |
72 | "Non Host Mode configured for %s. Wrong driver linked.\n", | 73 | "Non Host Mode configured for %s. Wrong driver linked.\n", |
73 | pdev->dev.bus_id); | 74 | pdev->dev.bus_id); |
@@ -185,12 +186,14 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) | |||
185 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 186 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
186 | struct fsl_usb2_platform_data *pdata; | 187 | struct fsl_usb2_platform_data *pdata; |
187 | void __iomem *non_ehci = hcd->regs; | 188 | void __iomem *non_ehci = hcd->regs; |
189 | u32 temp; | ||
188 | 190 | ||
189 | pdata = | 191 | pdata = |
190 | (struct fsl_usb2_platform_data *)hcd->self.controller-> | 192 | (struct fsl_usb2_platform_data *)hcd->self.controller-> |
191 | platform_data; | 193 | platform_data; |
192 | /* Enable PHY interface in the control reg. */ | 194 | /* Enable PHY interface in the control reg. */ |
193 | out_be32(non_ehci + FSL_SOC_USB_CTRL, 0x00000004); | 195 | temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); |
196 | out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); | ||
194 | out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); | 197 | out_be32(non_ehci + FSL_SOC_USB_SNOOP1, 0x0000001b); |
195 | 198 | ||
196 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) | 199 | #if defined(CONFIG_PPC32) && !defined(CONFIG_NOT_COHERENT_CACHE) |
@@ -206,7 +209,8 @@ static void mpc83xx_usb_setup(struct usb_hcd *hcd) | |||
206 | out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); | 209 | out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB); |
207 | #endif | 210 | #endif |
208 | 211 | ||
209 | if (pdata->operating_mode == FSL_USB2_DR_HOST) | 212 | if ((pdata->operating_mode == FSL_USB2_DR_HOST) || |
213 | (pdata->operating_mode == FSL_USB2_DR_OTG)) | ||
210 | mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); | 214 | mpc83xx_setup_phy(ehci, pdata->phy_mode, 0); |
211 | 215 | ||
212 | if (pdata->operating_mode == FSL_USB2_MPH_HOST) { | 216 | if (pdata->operating_mode == FSL_USB2_MPH_HOST) { |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 099aff64f536..c4e15ed1405a 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -41,10 +41,6 @@ | |||
41 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
42 | #include <asm/system.h> | 42 | #include <asm/system.h> |
43 | #include <asm/unaligned.h> | 43 | #include <asm/unaligned.h> |
44 | #ifdef CONFIG_PPC_PS3 | ||
45 | #include <asm/firmware.h> | ||
46 | #endif | ||
47 | |||
48 | 44 | ||
49 | /*-------------------------------------------------------------------------*/ | 45 | /*-------------------------------------------------------------------------*/ |
50 | 46 | ||
@@ -201,9 +197,15 @@ static void tdi_reset (struct ehci_hcd *ehci) | |||
201 | u32 __iomem *reg_ptr; | 197 | u32 __iomem *reg_ptr; |
202 | u32 tmp; | 198 | u32 tmp; |
203 | 199 | ||
204 | reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68); | 200 | reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + USBMODE); |
205 | tmp = ehci_readl(ehci, reg_ptr); | 201 | tmp = ehci_readl(ehci, reg_ptr); |
206 | tmp |= 0x3; | 202 | tmp |= USBMODE_CM_HC; |
203 | /* The default byte access to MMR space is LE after | ||
204 | * controller reset. Set the required endian mode | ||
205 | * for transfer buffers to match the host microprocessor | ||
206 | */ | ||
207 | if (ehci_big_endian_mmio(ehci)) | ||
208 | tmp |= USBMODE_BE; | ||
207 | ehci_writel(ehci, tmp, reg_ptr); | 209 | ehci_writel(ehci, tmp, reg_ptr); |
208 | } | 210 | } |
209 | 211 | ||
@@ -273,6 +275,58 @@ static void ehci_work(struct ehci_hcd *ehci); | |||
273 | 275 | ||
274 | /*-------------------------------------------------------------------------*/ | 276 | /*-------------------------------------------------------------------------*/ |
275 | 277 | ||
278 | #ifdef CONFIG_CPU_FREQ | ||
279 | |||
280 | #include <linux/cpufreq.h> | ||
281 | |||
282 | static void ehci_cpufreq_pause (struct ehci_hcd *ehci) | ||
283 | { | ||
284 | unsigned long flags; | ||
285 | |||
286 | spin_lock_irqsave(&ehci->lock, flags); | ||
287 | if (!ehci->cpufreq_changing++) | ||
288 | qh_inactivate_split_intr_qhs(ehci); | ||
289 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
290 | } | ||
291 | |||
292 | static void ehci_cpufreq_unpause (struct ehci_hcd *ehci) | ||
293 | { | ||
294 | unsigned long flags; | ||
295 | |||
296 | spin_lock_irqsave(&ehci->lock, flags); | ||
297 | if (!--ehci->cpufreq_changing) | ||
298 | qh_reactivate_split_intr_qhs(ehci); | ||
299 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * ehci_cpufreq_notifier is needed to avoid MMF errors that occur when | ||
304 | * EHCI controllers that don't cache many uframes get delayed trying to | ||
305 | * read main memory during CPU frequency transitions. This can cause | ||
306 | * split interrupt transactions to not be completed in the required uframe. | ||
307 | * This has been observed on the Broadcom/ServerWorks HT1000 controller. | ||
308 | */ | ||
309 | static int ehci_cpufreq_notifier(struct notifier_block *nb, unsigned long val, | ||
310 | void *data) | ||
311 | { | ||
312 | struct ehci_hcd *ehci = container_of(nb, struct ehci_hcd, | ||
313 | cpufreq_transition); | ||
314 | |||
315 | switch (val) { | ||
316 | case CPUFREQ_PRECHANGE: | ||
317 | ehci_cpufreq_pause(ehci); | ||
318 | break; | ||
319 | case CPUFREQ_POSTCHANGE: | ||
320 | ehci_cpufreq_unpause(ehci); | ||
321 | break; | ||
322 | } | ||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | #endif | ||
327 | |||
328 | /*-------------------------------------------------------------------------*/ | ||
329 | |||
276 | static void ehci_watchdog (unsigned long param) | 330 | static void ehci_watchdog (unsigned long param) |
277 | { | 331 | { |
278 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; | 332 | struct ehci_hcd *ehci = (struct ehci_hcd *) param; |
@@ -347,6 +401,8 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) | |||
347 | is_on ? SetPortFeature : ClearPortFeature, | 401 | is_on ? SetPortFeature : ClearPortFeature, |
348 | USB_PORT_FEAT_POWER, | 402 | USB_PORT_FEAT_POWER, |
349 | port--, NULL, 0); | 403 | port--, NULL, 0); |
404 | /* Flush those writes */ | ||
405 | ehci_readl(ehci, &ehci->regs->command); | ||
350 | msleep(20); | 406 | msleep(20); |
351 | } | 407 | } |
352 | 408 | ||
@@ -404,6 +460,10 @@ static void ehci_stop (struct usb_hcd *hcd) | |||
404 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); | 460 | ehci_writel(ehci, 0, &ehci->regs->intr_enable); |
405 | spin_unlock_irq(&ehci->lock); | 461 | spin_unlock_irq(&ehci->lock); |
406 | 462 | ||
463 | #ifdef CONFIG_CPU_FREQ | ||
464 | cpufreq_unregister_notifier(&ehci->cpufreq_transition, | ||
465 | CPUFREQ_TRANSITION_NOTIFIER); | ||
466 | #endif | ||
407 | /* let companion controllers work when we aren't */ | 467 | /* let companion controllers work when we aren't */ |
408 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); | 468 | ehci_writel(ehci, 0, &ehci->regs->configured_flag); |
409 | 469 | ||
@@ -470,12 +530,12 @@ static int ehci_init(struct usb_hcd *hcd) | |||
470 | * from automatically advancing to the next td after short reads. | 530 | * from automatically advancing to the next td after short reads. |
471 | */ | 531 | */ |
472 | ehci->async->qh_next.qh = NULL; | 532 | ehci->async->qh_next.qh = NULL; |
473 | ehci->async->hw_next = QH_NEXT(ehci->async->qh_dma); | 533 | ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); |
474 | ehci->async->hw_info1 = cpu_to_le32(QH_HEAD); | 534 | ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); |
475 | ehci->async->hw_token = cpu_to_le32(QTD_STS_HALT); | 535 | ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); |
476 | ehci->async->hw_qtd_next = EHCI_LIST_END; | 536 | ehci->async->hw_qtd_next = EHCI_LIST_END(ehci); |
477 | ehci->async->qh_state = QH_STATE_LINKED; | 537 | ehci->async->qh_state = QH_STATE_LINKED; |
478 | ehci->async->hw_alt_next = QTD_NEXT(ehci->async->dummy->qtd_dma); | 538 | ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); |
479 | 539 | ||
480 | /* clear interrupt enables, set irq latency */ | 540 | /* clear interrupt enables, set irq latency */ |
481 | if (log2_irq_thresh < 0 || log2_irq_thresh > 6) | 541 | if (log2_irq_thresh < 0 || log2_irq_thresh > 6) |
@@ -509,6 +569,17 @@ static int ehci_init(struct usb_hcd *hcd) | |||
509 | } | 569 | } |
510 | ehci->command = temp; | 570 | ehci->command = temp; |
511 | 571 | ||
572 | #ifdef CONFIG_CPU_FREQ | ||
573 | INIT_LIST_HEAD(&ehci->split_intr_qhs); | ||
574 | /* | ||
575 | * If the EHCI controller caches enough uframes, this probably | ||
576 | * isn't needed unless there are so many low/full speed devices | ||
577 | * that the controller's can't cache it all. | ||
578 | */ | ||
579 | ehci->cpufreq_transition.notifier_call = ehci_cpufreq_notifier; | ||
580 | cpufreq_register_notifier(&ehci->cpufreq_transition, | ||
581 | CPUFREQ_TRANSITION_NOTIFIER); | ||
582 | #endif | ||
512 | return 0; | 583 | return 0; |
513 | } | 584 | } |
514 | 585 | ||
@@ -925,7 +996,7 @@ MODULE_LICENSE ("GPL"); | |||
925 | #define PCI_DRIVER ehci_pci_driver | 996 | #define PCI_DRIVER ehci_pci_driver |
926 | #endif | 997 | #endif |
927 | 998 | ||
928 | #ifdef CONFIG_MPC834x | 999 | #ifdef CONFIG_USB_EHCI_FSL |
929 | #include "ehci-fsl.c" | 1000 | #include "ehci-fsl.c" |
930 | #define PLATFORM_DRIVER ehci_fsl_driver | 1001 | #define PLATFORM_DRIVER ehci_fsl_driver |
931 | #endif | 1002 | #endif |
@@ -937,7 +1008,12 @@ MODULE_LICENSE ("GPL"); | |||
937 | 1008 | ||
938 | #ifdef CONFIG_PPC_PS3 | 1009 | #ifdef CONFIG_PPC_PS3 |
939 | #include "ehci-ps3.c" | 1010 | #include "ehci-ps3.c" |
940 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_sb_driver | 1011 | #define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver |
1012 | #endif | ||
1013 | |||
1014 | #ifdef CONFIG_440EPX | ||
1015 | #include "ehci-ppc-soc.c" | ||
1016 | #define PLATFORM_DRIVER ehci_ppc_soc_driver | ||
941 | #endif | 1017 | #endif |
942 | 1018 | ||
943 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ | 1019 | #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ |
@@ -971,18 +1047,15 @@ static int __init ehci_hcd_init(void) | |||
971 | #endif | 1047 | #endif |
972 | 1048 | ||
973 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1049 | #ifdef PS3_SYSTEM_BUS_DRIVER |
974 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { | 1050 | retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); |
975 | retval = ps3_system_bus_driver_register( | 1051 | if (retval < 0) { |
976 | &PS3_SYSTEM_BUS_DRIVER); | ||
977 | if (retval < 0) { | ||
978 | #ifdef PLATFORM_DRIVER | 1052 | #ifdef PLATFORM_DRIVER |
979 | platform_driver_unregister(&PLATFORM_DRIVER); | 1053 | platform_driver_unregister(&PLATFORM_DRIVER); |
980 | #endif | 1054 | #endif |
981 | #ifdef PCI_DRIVER | 1055 | #ifdef PCI_DRIVER |
982 | pci_unregister_driver(&PCI_DRIVER); | 1056 | pci_unregister_driver(&PCI_DRIVER); |
983 | #endif | 1057 | #endif |
984 | return retval; | 1058 | return retval; |
985 | } | ||
986 | } | 1059 | } |
987 | #endif | 1060 | #endif |
988 | 1061 | ||
@@ -999,8 +1072,7 @@ static void __exit ehci_hcd_cleanup(void) | |||
999 | pci_unregister_driver(&PCI_DRIVER); | 1072 | pci_unregister_driver(&PCI_DRIVER); |
1000 | #endif | 1073 | #endif |
1001 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1074 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1002 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) | 1075 | ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
1003 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
1004 | #endif | 1076 | #endif |
1005 | } | 1077 | } |
1006 | module_exit(ehci_hcd_cleanup); | 1078 | module_exit(ehci_hcd_cleanup); |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index f4d301bc83b9..0dcb4164dc83 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -28,6 +28,89 @@ | |||
28 | 28 | ||
29 | /*-------------------------------------------------------------------------*/ | 29 | /*-------------------------------------------------------------------------*/ |
30 | 30 | ||
31 | #ifdef CONFIG_USB_PERSIST | ||
32 | |||
33 | static int ehci_hub_control( | ||
34 | struct usb_hcd *hcd, | ||
35 | u16 typeReq, | ||
36 | u16 wValue, | ||
37 | u16 wIndex, | ||
38 | char *buf, | ||
39 | u16 wLength | ||
40 | ); | ||
41 | |||
42 | /* After a power loss, ports that were owned by the companion must be | ||
43 | * reset so that the companion can still own them. | ||
44 | */ | ||
45 | static void ehci_handover_companion_ports(struct ehci_hcd *ehci) | ||
46 | { | ||
47 | u32 __iomem *reg; | ||
48 | u32 status; | ||
49 | int port; | ||
50 | __le32 buf; | ||
51 | struct usb_hcd *hcd = ehci_to_hcd(ehci); | ||
52 | |||
53 | if (!ehci->owned_ports) | ||
54 | return; | ||
55 | |||
56 | /* Give the connections some time to appear */ | ||
57 | msleep(20); | ||
58 | |||
59 | port = HCS_N_PORTS(ehci->hcs_params); | ||
60 | while (port--) { | ||
61 | if (test_bit(port, &ehci->owned_ports)) { | ||
62 | reg = &ehci->regs->port_status[port]; | ||
63 | status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; | ||
64 | |||
65 | /* Port already owned by companion? */ | ||
66 | if (status & PORT_OWNER) | ||
67 | clear_bit(port, &ehci->owned_ports); | ||
68 | else if (test_bit(port, &ehci->companion_ports)) | ||
69 | ehci_writel(ehci, status & ~PORT_PE, reg); | ||
70 | else | ||
71 | ehci_hub_control(hcd, SetPortFeature, | ||
72 | USB_PORT_FEAT_RESET, port + 1, | ||
73 | NULL, 0); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | if (!ehci->owned_ports) | ||
78 | return; | ||
79 | msleep(90); /* Wait for resets to complete */ | ||
80 | |||
81 | port = HCS_N_PORTS(ehci->hcs_params); | ||
82 | while (port--) { | ||
83 | if (test_bit(port, &ehci->owned_ports)) { | ||
84 | ehci_hub_control(hcd, GetPortStatus, | ||
85 | 0, port + 1, | ||
86 | (char *) &buf, sizeof(buf)); | ||
87 | |||
88 | /* The companion should now own the port, | ||
89 | * but if something went wrong the port must not | ||
90 | * remain enabled. | ||
91 | */ | ||
92 | reg = &ehci->regs->port_status[port]; | ||
93 | status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; | ||
94 | if (status & PORT_OWNER) | ||
95 | ehci_writel(ehci, status | PORT_CSC, reg); | ||
96 | else { | ||
97 | ehci_dbg(ehci, "failed handover port %d: %x\n", | ||
98 | port + 1, status); | ||
99 | ehci_writel(ehci, status & ~PORT_PE, reg); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
104 | ehci->owned_ports = 0; | ||
105 | } | ||
106 | |||
107 | #else /* CONFIG_USB_PERSIST */ | ||
108 | |||
109 | static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci) | ||
110 | { } | ||
111 | |||
112 | #endif | ||
113 | |||
31 | #ifdef CONFIG_PM | 114 | #ifdef CONFIG_PM |
32 | 115 | ||
33 | static int ehci_bus_suspend (struct usb_hcd *hcd) | 116 | static int ehci_bus_suspend (struct usb_hcd *hcd) |
@@ -60,14 +143,16 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
60 | * then manually resume them in the bus_resume() routine. | 143 | * then manually resume them in the bus_resume() routine. |
61 | */ | 144 | */ |
62 | ehci->bus_suspended = 0; | 145 | ehci->bus_suspended = 0; |
146 | ehci->owned_ports = 0; | ||
63 | while (port--) { | 147 | while (port--) { |
64 | u32 __iomem *reg = &ehci->regs->port_status [port]; | 148 | u32 __iomem *reg = &ehci->regs->port_status [port]; |
65 | u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; | 149 | u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; |
66 | u32 t2 = t1; | 150 | u32 t2 = t1; |
67 | 151 | ||
68 | /* keep track of which ports we suspend */ | 152 | /* keep track of which ports we suspend */ |
69 | if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) && | 153 | if (t1 & PORT_OWNER) |
70 | !(t1 & PORT_SUSPEND)) { | 154 | set_bit(port, &ehci->owned_ports); |
155 | else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) { | ||
71 | t2 |= PORT_SUSPEND; | 156 | t2 |= PORT_SUSPEND; |
72 | set_bit(port, &ehci->bus_suspended); | 157 | set_bit(port, &ehci->bus_suspended); |
73 | } | 158 | } |
@@ -108,11 +193,16 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
108 | { | 193 | { |
109 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 194 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
110 | u32 temp; | 195 | u32 temp; |
196 | u32 power_okay; | ||
111 | int i; | 197 | int i; |
112 | 198 | ||
113 | if (time_before (jiffies, ehci->next_statechange)) | 199 | if (time_before (jiffies, ehci->next_statechange)) |
114 | msleep(5); | 200 | msleep(5); |
115 | spin_lock_irq (&ehci->lock); | 201 | spin_lock_irq (&ehci->lock); |
202 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | ||
203 | spin_unlock_irq(&ehci->lock); | ||
204 | return -ESHUTDOWN; | ||
205 | } | ||
116 | 206 | ||
117 | /* Ideally and we've got a real resume here, and no port's power | 207 | /* Ideally and we've got a real resume here, and no port's power |
118 | * was lost. (For PCI, that means Vaux was maintained.) But we | 208 | * was lost. (For PCI, that means Vaux was maintained.) But we |
@@ -120,8 +210,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
120 | * the last user of the controller, not reset/pm hardware keeping | 210 | * the last user of the controller, not reset/pm hardware keeping |
121 | * state we gave to it. | 211 | * state we gave to it. |
122 | */ | 212 | */ |
123 | temp = ehci_readl(ehci, &ehci->regs->intr_enable); | 213 | power_okay = ehci_readl(ehci, &ehci->regs->intr_enable); |
124 | ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss"); | 214 | ehci_dbg(ehci, "resume root hub%s\n", |
215 | power_okay ? "" : " after power loss"); | ||
125 | 216 | ||
126 | /* at least some APM implementations will try to deliver | 217 | /* at least some APM implementations will try to deliver |
127 | * IRQs right away, so delay them until we're ready. | 218 | * IRQs right away, so delay them until we're ready. |
@@ -184,6 +275,9 @@ static int ehci_bus_resume (struct usb_hcd *hcd) | |||
184 | ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); | 275 | ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); |
185 | 276 | ||
186 | spin_unlock_irq (&ehci->lock); | 277 | spin_unlock_irq (&ehci->lock); |
278 | |||
279 | if (!power_okay) | ||
280 | ehci_handover_companion_ports(ehci); | ||
187 | return 0; | 281 | return 0; |
188 | } | 282 | } |
189 | 283 | ||
@@ -448,7 +542,8 @@ static int ehci_hub_control ( | |||
448 | ) { | 542 | ) { |
449 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); | 543 | struct ehci_hcd *ehci = hcd_to_ehci (hcd); |
450 | int ports = HCS_N_PORTS (ehci->hcs_params); | 544 | int ports = HCS_N_PORTS (ehci->hcs_params); |
451 | u32 __iomem *status_reg = &ehci->regs->port_status[wIndex - 1]; | 545 | u32 __iomem *status_reg = &ehci->regs->port_status[ |
546 | (wIndex & 0xff) - 1]; | ||
452 | u32 temp, status; | 547 | u32 temp, status; |
453 | unsigned long flags; | 548 | unsigned long flags; |
454 | int retval = 0; | 549 | int retval = 0; |
@@ -556,9 +651,24 @@ static int ehci_hub_control ( | |||
556 | status |= 1 << USB_PORT_FEAT_C_CONNECTION; | 651 | status |= 1 << USB_PORT_FEAT_C_CONNECTION; |
557 | if (temp & PORT_PEC) | 652 | if (temp & PORT_PEC) |
558 | status |= 1 << USB_PORT_FEAT_C_ENABLE; | 653 | status |= 1 << USB_PORT_FEAT_C_ENABLE; |
559 | if ((temp & PORT_OCC) && !ignore_oc) | 654 | |
655 | if ((temp & PORT_OCC) && !ignore_oc){ | ||
560 | status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; | 656 | status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; |
561 | 657 | ||
658 | /* | ||
659 | * Hubs should disable port power on over-current. | ||
660 | * However, not all EHCI implementations do this | ||
661 | * automatically, even if they _do_ support per-port | ||
662 | * power switching; they're allowed to just limit the | ||
663 | * current. khubd will turn the power back on. | ||
664 | */ | ||
665 | if (HCS_PPC (ehci->hcs_params)){ | ||
666 | ehci_writel(ehci, | ||
667 | temp & ~(PORT_RWC_BITS | PORT_POWER), | ||
668 | status_reg); | ||
669 | } | ||
670 | } | ||
671 | |||
562 | /* whoever resumes must GetPortStatus to complete it!! */ | 672 | /* whoever resumes must GetPortStatus to complete it!! */ |
563 | if (temp & PORT_RESUME) { | 673 | if (temp & PORT_RESUME) { |
564 | 674 | ||
diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index a8ba2e1497a4..8816d09903d0 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c | |||
@@ -27,7 +27,7 @@ | |||
27 | * need to use dma_pool or dma_alloc_coherent | 27 | * need to use dma_pool or dma_alloc_coherent |
28 | * - driver buffers, read/written by HC ... single shot DMA mapped | 28 | * - driver buffers, read/written by HC ... single shot DMA mapped |
29 | * | 29 | * |
30 | * There's also PCI "register" data, which is memory mapped. | 30 | * There's also "register" data (e.g. PCI or SOC), which is memory mapped. |
31 | * No memory seen by this driver is pageable. | 31 | * No memory seen by this driver is pageable. |
32 | */ | 32 | */ |
33 | 33 | ||
@@ -35,13 +35,14 @@ | |||
35 | 35 | ||
36 | /* Allocate the key transfer structures from the previously allocated pool */ | 36 | /* Allocate the key transfer structures from the previously allocated pool */ |
37 | 37 | ||
38 | static inline void ehci_qtd_init (struct ehci_qtd *qtd, dma_addr_t dma) | 38 | static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd, |
39 | dma_addr_t dma) | ||
39 | { | 40 | { |
40 | memset (qtd, 0, sizeof *qtd); | 41 | memset (qtd, 0, sizeof *qtd); |
41 | qtd->qtd_dma = dma; | 42 | qtd->qtd_dma = dma; |
42 | qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); | 43 | qtd->hw_token = cpu_to_le32 (QTD_STS_HALT); |
43 | qtd->hw_next = EHCI_LIST_END; | 44 | qtd->hw_next = EHCI_LIST_END(ehci); |
44 | qtd->hw_alt_next = EHCI_LIST_END; | 45 | qtd->hw_alt_next = EHCI_LIST_END(ehci); |
45 | INIT_LIST_HEAD (&qtd->qtd_list); | 46 | INIT_LIST_HEAD (&qtd->qtd_list); |
46 | } | 47 | } |
47 | 48 | ||
@@ -52,7 +53,7 @@ static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags) | |||
52 | 53 | ||
53 | qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma); | 54 | qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma); |
54 | if (qtd != NULL) { | 55 | if (qtd != NULL) { |
55 | ehci_qtd_init (qtd, dma); | 56 | ehci_qtd_init(ehci, qtd, dma); |
56 | } | 57 | } |
57 | return qtd; | 58 | return qtd; |
58 | } | 59 | } |
@@ -63,9 +64,8 @@ static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd) | |||
63 | } | 64 | } |
64 | 65 | ||
65 | 66 | ||
66 | static void qh_destroy (struct kref *kref) | 67 | static void qh_destroy(struct ehci_qh *qh) |
67 | { | 68 | { |
68 | struct ehci_qh *qh = container_of(kref, struct ehci_qh, kref); | ||
69 | struct ehci_hcd *ehci = qh->ehci; | 69 | struct ehci_hcd *ehci = qh->ehci; |
70 | 70 | ||
71 | /* clean qtds first, and know this is not linked */ | 71 | /* clean qtds first, and know this is not linked */ |
@@ -89,11 +89,14 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) | |||
89 | return qh; | 89 | return qh; |
90 | 90 | ||
91 | memset (qh, 0, sizeof *qh); | 91 | memset (qh, 0, sizeof *qh); |
92 | kref_init(&qh->kref); | 92 | qh->refcount = 1; |
93 | qh->ehci = ehci; | 93 | qh->ehci = ehci; |
94 | qh->qh_dma = dma; | 94 | qh->qh_dma = dma; |
95 | // INIT_LIST_HEAD (&qh->qh_list); | 95 | // INIT_LIST_HEAD (&qh->qh_list); |
96 | INIT_LIST_HEAD (&qh->qtd_list); | 96 | INIT_LIST_HEAD (&qh->qtd_list); |
97 | #ifdef CONFIG_CPU_FREQ | ||
98 | INIT_LIST_HEAD (&qh->split_intr_qhs); | ||
99 | #endif | ||
97 | 100 | ||
98 | /* dummy td enables safe urb queuing */ | 101 | /* dummy td enables safe urb queuing */ |
99 | qh->dummy = ehci_qtd_alloc (ehci, flags); | 102 | qh->dummy = ehci_qtd_alloc (ehci, flags); |
@@ -108,13 +111,15 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) | |||
108 | /* to share a qh (cpu threads, or hc) */ | 111 | /* to share a qh (cpu threads, or hc) */ |
109 | static inline struct ehci_qh *qh_get (struct ehci_qh *qh) | 112 | static inline struct ehci_qh *qh_get (struct ehci_qh *qh) |
110 | { | 113 | { |
111 | kref_get(&qh->kref); | 114 | WARN_ON(!qh->refcount); |
115 | qh->refcount++; | ||
112 | return qh; | 116 | return qh; |
113 | } | 117 | } |
114 | 118 | ||
115 | static inline void qh_put (struct ehci_qh *qh) | 119 | static inline void qh_put (struct ehci_qh *qh) |
116 | { | 120 | { |
117 | kref_put(&qh->kref, qh_destroy); | 121 | if (!--qh->refcount) |
122 | qh_destroy(qh); | ||
118 | } | 123 | } |
119 | 124 | ||
120 | /*-------------------------------------------------------------------------*/ | 125 | /*-------------------------------------------------------------------------*/ |
@@ -217,7 +222,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) | |||
217 | goto fail; | 222 | goto fail; |
218 | } | 223 | } |
219 | for (i = 0; i < ehci->periodic_size; i++) | 224 | for (i = 0; i < ehci->periodic_size; i++) |
220 | ehci->periodic [i] = EHCI_LIST_END; | 225 | ehci->periodic [i] = EHCI_LIST_END(ehci); |
221 | 226 | ||
222 | /* software shadow of hardware table */ | 227 | /* software shadow of hardware table */ |
223 | ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags); | 228 | ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags); |
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 966965f72338..a7816e392a85 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -312,13 +312,14 @@ static int ehci_pci_resume(struct usb_hcd *hcd) | |||
312 | ehci_work(ehci); | 312 | ehci_work(ehci); |
313 | spin_unlock_irq(&ehci->lock); | 313 | spin_unlock_irq(&ehci->lock); |
314 | 314 | ||
315 | /* here we "know" root ports should always stay powered */ | ||
316 | ehci_port_power(ehci, 1); | ||
317 | |||
318 | ehci_writel(ehci, ehci->command, &ehci->regs->command); | 315 | ehci_writel(ehci, ehci->command, &ehci->regs->command); |
319 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); | 316 | ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); |
320 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ | 317 | ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ |
321 | 318 | ||
319 | /* here we "know" root ports should always stay powered */ | ||
320 | ehci_port_power(ehci, 1); | ||
321 | ehci_handover_companion_ports(ehci); | ||
322 | |||
322 | hcd->state = HC_STATE_SUSPENDED; | 323 | hcd->state = HC_STATE_SUSPENDED; |
323 | return 0; | 324 | return 0; |
324 | } | 325 | } |
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c new file mode 100644 index 000000000000..c2cedb09ed8b --- /dev/null +++ b/drivers/usb/host/ehci-ppc-soc.c | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * EHCI HCD (Host Controller Driver) for USB. | ||
3 | * | ||
4 | * (C) Copyright 2006-2007 Stefan Roese <sr@denx.de>, DENX Software Engineering | ||
5 | * | ||
6 | * Bus Glue for PPC On-Chip EHCI driver | ||
7 | * Tested on AMCC 440EPx | ||
8 | * | ||
9 | * Based on "ehci-au12xx.c" by David Brownell <dbrownell@users.sourceforge.net> | ||
10 | * | ||
11 | * This file is licenced under the GPL. | ||
12 | */ | ||
13 | |||
14 | #include <linux/platform_device.h> | ||
15 | |||
16 | extern int usb_disabled(void); | ||
17 | |||
18 | /** | ||
19 | * usb_ehci_ppc_soc_probe - initialize PPC-SoC-based HCDs | ||
20 | * Context: !in_interrupt() | ||
21 | * | ||
22 | * Allocates basic resources for this USB host controller, and | ||
23 | * then invokes the start() method for the HCD associated with it | ||
24 | * through the hotplug entry's driver_data. | ||
25 | * | ||
26 | */ | ||
27 | int usb_ehci_ppc_soc_probe(const struct hc_driver *driver, | ||
28 | struct usb_hcd **hcd_out, | ||
29 | struct platform_device *dev) | ||
30 | { | ||
31 | int retval; | ||
32 | struct usb_hcd *hcd; | ||
33 | struct ehci_hcd *ehci; | ||
34 | |||
35 | if (dev->resource[1].flags != IORESOURCE_IRQ) { | ||
36 | pr_debug("resource[1] is not IORESOURCE_IRQ"); | ||
37 | retval = -ENOMEM; | ||
38 | } | ||
39 | hcd = usb_create_hcd(driver, &dev->dev, "PPC-SOC EHCI"); | ||
40 | if (!hcd) | ||
41 | return -ENOMEM; | ||
42 | hcd->rsrc_start = dev->resource[0].start; | ||
43 | hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; | ||
44 | |||
45 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { | ||
46 | pr_debug("request_mem_region failed"); | ||
47 | retval = -EBUSY; | ||
48 | goto err1; | ||
49 | } | ||
50 | |||
51 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | ||
52 | if (!hcd->regs) { | ||
53 | pr_debug("ioremap failed"); | ||
54 | retval = -ENOMEM; | ||
55 | goto err2; | ||
56 | } | ||
57 | |||
58 | ehci = hcd_to_ehci(hcd); | ||
59 | ehci->big_endian_mmio = 1; | ||
60 | ehci->big_endian_desc = 1; | ||
61 | ehci->caps = hcd->regs; | ||
62 | ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); | ||
63 | |||
64 | /* cache this readonly data; minimize chip reads */ | ||
65 | ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); | ||
66 | |||
67 | #if defined(CONFIG_440EPX) | ||
68 | /* | ||
69 | * 440EPx Errata USBH_3 | ||
70 | * Fix: Enable Break Memory Transfer (BMT) in INSNREG3 | ||
71 | */ | ||
72 | out_be32((void *)((ulong)(&ehci->regs->command) + 0x8c), (1 << 0)); | ||
73 | ehci_dbg(ehci, "Break Memory Transfer (BMT) has beed enabled!\n"); | ||
74 | #endif | ||
75 | |||
76 | retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED); | ||
77 | if (retval == 0) | ||
78 | return retval; | ||
79 | |||
80 | iounmap(hcd->regs); | ||
81 | err2: | ||
82 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
83 | err1: | ||
84 | usb_put_hcd(hcd); | ||
85 | return retval; | ||
86 | } | ||
87 | |||
88 | /* may be called without controller electrically present */ | ||
89 | /* may be called with controller, bus, and devices active */ | ||
90 | |||
91 | /** | ||
92 | * usb_ehci_hcd_ppc_soc_remove - shutdown processing for PPC-SoC-based HCDs | ||
93 | * @dev: USB Host Controller being removed | ||
94 | * Context: !in_interrupt() | ||
95 | * | ||
96 | * Reverses the effect of usb_ehci_hcd_ppc_soc_probe(), first invoking | ||
97 | * the HCD's stop() method. It is always called from a thread | ||
98 | * context, normally "rmmod", "apmd", or something similar. | ||
99 | * | ||
100 | */ | ||
101 | void usb_ehci_ppc_soc_remove(struct usb_hcd *hcd, struct platform_device *dev) | ||
102 | { | ||
103 | usb_remove_hcd(hcd); | ||
104 | iounmap(hcd->regs); | ||
105 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
106 | usb_put_hcd(hcd); | ||
107 | } | ||
108 | |||
109 | static const struct hc_driver ehci_ppc_soc_hc_driver = { | ||
110 | .description = hcd_name, | ||
111 | .product_desc = "PPC-SOC EHCI", | ||
112 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
113 | |||
114 | /* | ||
115 | * generic hardware linkage | ||
116 | */ | ||
117 | .irq = ehci_irq, | ||
118 | .flags = HCD_MEMORY | HCD_USB2, | ||
119 | |||
120 | /* | ||
121 | * basic lifecycle operations | ||
122 | */ | ||
123 | .reset = ehci_init, | ||
124 | .start = ehci_run, | ||
125 | .stop = ehci_stop, | ||
126 | .shutdown = ehci_shutdown, | ||
127 | |||
128 | /* | ||
129 | * managing i/o requests and associated device resources | ||
130 | */ | ||
131 | .urb_enqueue = ehci_urb_enqueue, | ||
132 | .urb_dequeue = ehci_urb_dequeue, | ||
133 | .endpoint_disable = ehci_endpoint_disable, | ||
134 | |||
135 | /* | ||
136 | * scheduling support | ||
137 | */ | ||
138 | .get_frame_number = ehci_get_frame, | ||
139 | |||
140 | /* | ||
141 | * root hub support | ||
142 | */ | ||
143 | .hub_status_data = ehci_hub_status_data, | ||
144 | .hub_control = ehci_hub_control, | ||
145 | #ifdef CONFIG_PM | ||
146 | .hub_suspend = ehci_hub_suspend, | ||
147 | .hub_resume = ehci_hub_resume, | ||
148 | #endif | ||
149 | }; | ||
150 | |||
151 | static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) | ||
152 | { | ||
153 | struct usb_hcd *hcd = NULL; | ||
154 | int ret; | ||
155 | |||
156 | pr_debug("In ehci_hcd_ppc_soc_drv_probe\n"); | ||
157 | |||
158 | if (usb_disabled()) | ||
159 | return -ENODEV; | ||
160 | |||
161 | ret = usb_ehci_ppc_soc_probe(&ehci_ppc_soc_hc_driver, &hcd, pdev); | ||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | static int ehci_hcd_ppc_soc_drv_remove(struct platform_device *pdev) | ||
166 | { | ||
167 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | ||
168 | |||
169 | usb_ehci_ppc_soc_remove(hcd, pdev); | ||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | MODULE_ALIAS("ppc-soc-ehci"); | ||
174 | static struct platform_driver ehci_ppc_soc_driver = { | ||
175 | .probe = ehci_hcd_ppc_soc_drv_probe, | ||
176 | .remove = ehci_hcd_ppc_soc_drv_remove, | ||
177 | .shutdown = usb_hcd_platform_shutdown, | ||
178 | .driver = { | ||
179 | .name = "ppc-soc-ehci", | ||
180 | .bus = &platform_bus_type | ||
181 | } | ||
182 | }; | ||
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c index 37b83ba09969..829fe649a981 100644 --- a/drivers/usb/host/ehci-ps3.c +++ b/drivers/usb/host/ehci-ps3.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <asm/firmware.h> | ||
21 | #include <asm/ps3.h> | 22 | #include <asm/ps3.h> |
22 | 23 | ||
23 | static int ps3_ehci_hc_reset(struct usb_hcd *hcd) | 24 | static int ps3_ehci_hc_reset(struct usb_hcd *hcd) |
@@ -73,7 +74,7 @@ static const struct hc_driver ps3_ehci_hc_driver = { | |||
73 | #endif | 74 | #endif |
74 | }; | 75 | }; |
75 | 76 | ||
76 | static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) | 77 | static int ps3_ehci_probe(struct ps3_system_bus_device *dev) |
77 | { | 78 | { |
78 | int result; | 79 | int result; |
79 | struct usb_hcd *hcd; | 80 | struct usb_hcd *hcd; |
@@ -85,13 +86,30 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) | |||
85 | goto fail_start; | 86 | goto fail_start; |
86 | } | 87 | } |
87 | 88 | ||
89 | result = ps3_open_hv_device(dev); | ||
90 | |||
91 | if (result) { | ||
92 | dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed\n", | ||
93 | __func__, __LINE__); | ||
94 | goto fail_open; | ||
95 | } | ||
96 | |||
97 | result = ps3_dma_region_create(dev->d_region); | ||
98 | |||
99 | if (result) { | ||
100 | dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: " | ||
101 | "(%d)\n", __func__, __LINE__, result); | ||
102 | BUG_ON("check region type"); | ||
103 | goto fail_dma_region; | ||
104 | } | ||
105 | |||
88 | result = ps3_mmio_region_create(dev->m_region); | 106 | result = ps3_mmio_region_create(dev->m_region); |
89 | 107 | ||
90 | if (result) { | 108 | if (result) { |
91 | dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", | 109 | dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", |
92 | __func__, __LINE__); | 110 | __func__, __LINE__); |
93 | result = -EPERM; | 111 | result = -EPERM; |
94 | goto fail_mmio; | 112 | goto fail_mmio_region; |
95 | } | 113 | } |
96 | 114 | ||
97 | dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, | 115 | dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, |
@@ -120,6 +138,11 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) | |||
120 | 138 | ||
121 | hcd->rsrc_start = dev->m_region->lpar_addr; | 139 | hcd->rsrc_start = dev->m_region->lpar_addr; |
122 | hcd->rsrc_len = dev->m_region->len; | 140 | hcd->rsrc_len = dev->m_region->len; |
141 | |||
142 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) | ||
143 | dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n", | ||
144 | __func__, __LINE__); | ||
145 | |||
123 | hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); | 146 | hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); |
124 | 147 | ||
125 | if (!hcd->regs) { | 148 | if (!hcd->regs) { |
@@ -153,34 +176,73 @@ static int ps3_ehci_sb_probe(struct ps3_system_bus_device *dev) | |||
153 | fail_add_hcd: | 176 | fail_add_hcd: |
154 | iounmap(hcd->regs); | 177 | iounmap(hcd->regs); |
155 | fail_ioremap: | 178 | fail_ioremap: |
179 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
156 | usb_put_hcd(hcd); | 180 | usb_put_hcd(hcd); |
157 | fail_create_hcd: | 181 | fail_create_hcd: |
158 | ps3_io_irq_destroy(virq); | 182 | ps3_io_irq_destroy(virq); |
159 | fail_irq: | 183 | fail_irq: |
160 | ps3_free_mmio_region(dev->m_region); | 184 | ps3_free_mmio_region(dev->m_region); |
161 | fail_mmio: | 185 | fail_mmio_region: |
186 | ps3_dma_region_free(dev->d_region); | ||
187 | fail_dma_region: | ||
188 | ps3_close_hv_device(dev); | ||
189 | fail_open: | ||
162 | fail_start: | 190 | fail_start: |
163 | return result; | 191 | return result; |
164 | } | 192 | } |
165 | 193 | ||
166 | static int ps3_ehci_sb_remove(struct ps3_system_bus_device *dev) | 194 | static int ps3_ehci_remove(struct ps3_system_bus_device *dev) |
167 | { | 195 | { |
196 | unsigned int tmp; | ||
168 | struct usb_hcd *hcd = | 197 | struct usb_hcd *hcd = |
169 | (struct usb_hcd *)ps3_system_bus_get_driver_data(dev); | 198 | (struct usb_hcd *)ps3_system_bus_get_driver_data(dev); |
170 | 199 | ||
171 | usb_put_hcd(hcd); | 200 | BUG_ON(!hcd); |
201 | |||
202 | dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs); | ||
203 | dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq); | ||
204 | |||
205 | tmp = hcd->irq; | ||
206 | |||
207 | usb_remove_hcd(hcd); | ||
208 | |||
172 | ps3_system_bus_set_driver_data(dev, NULL); | 209 | ps3_system_bus_set_driver_data(dev, NULL); |
173 | 210 | ||
211 | BUG_ON(!hcd->regs); | ||
212 | iounmap(hcd->regs); | ||
213 | |||
214 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
215 | usb_put_hcd(hcd); | ||
216 | |||
217 | ps3_io_irq_destroy(tmp); | ||
218 | ps3_free_mmio_region(dev->m_region); | ||
219 | |||
220 | ps3_dma_region_free(dev->d_region); | ||
221 | ps3_close_hv_device(dev); | ||
222 | |||
174 | return 0; | 223 | return 0; |
175 | } | 224 | } |
176 | 225 | ||
177 | MODULE_ALIAS("ps3-ehci"); | 226 | static int ps3_ehci_driver_register(struct ps3_system_bus_driver *drv) |
227 | { | ||
228 | return firmware_has_feature(FW_FEATURE_PS3_LV1) | ||
229 | ? ps3_system_bus_driver_register(drv) | ||
230 | : 0; | ||
231 | } | ||
232 | |||
233 | static void ps3_ehci_driver_unregister(struct ps3_system_bus_driver *drv) | ||
234 | { | ||
235 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
236 | ps3_system_bus_driver_unregister(drv); | ||
237 | } | ||
238 | |||
239 | MODULE_ALIAS(PS3_MODULE_ALIAS_EHCI); | ||
178 | 240 | ||
179 | static struct ps3_system_bus_driver ps3_ehci_sb_driver = { | 241 | static struct ps3_system_bus_driver ps3_ehci_driver = { |
242 | .core.name = "ps3-ehci-driver", | ||
243 | .core.owner = THIS_MODULE, | ||
180 | .match_id = PS3_MATCH_ID_EHCI, | 244 | .match_id = PS3_MATCH_ID_EHCI, |
181 | .core = { | 245 | .probe = ps3_ehci_probe, |
182 | .name = "ps3-ehci-driver", | 246 | .remove = ps3_ehci_remove, |
183 | }, | 247 | .shutdown = ps3_ehci_remove, |
184 | .probe = ps3_ehci_sb_probe, | ||
185 | .remove = ps3_ehci_sb_remove, | ||
186 | }; | 248 | }; |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index e7fbbd00e7cd..2284028f8aa5 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -43,15 +43,15 @@ | |||
43 | /* fill a qtd, returning how much of the buffer we were able to queue up */ | 43 | /* fill a qtd, returning how much of the buffer we were able to queue up */ |
44 | 44 | ||
45 | static int | 45 | static int |
46 | qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, | 46 | qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf, |
47 | int token, int maxpacket) | 47 | size_t len, int token, int maxpacket) |
48 | { | 48 | { |
49 | int i, count; | 49 | int i, count; |
50 | u64 addr = buf; | 50 | u64 addr = buf; |
51 | 51 | ||
52 | /* one buffer entry per 4K ... first might be short or unaligned */ | 52 | /* one buffer entry per 4K ... first might be short or unaligned */ |
53 | qtd->hw_buf [0] = cpu_to_le32 ((u32)addr); | 53 | qtd->hw_buf[0] = cpu_to_hc32(ehci, (u32)addr); |
54 | qtd->hw_buf_hi [0] = cpu_to_le32 ((u32)(addr >> 32)); | 54 | qtd->hw_buf_hi[0] = cpu_to_hc32(ehci, (u32)(addr >> 32)); |
55 | count = 0x1000 - (buf & 0x0fff); /* rest of that page */ | 55 | count = 0x1000 - (buf & 0x0fff); /* rest of that page */ |
56 | if (likely (len < count)) /* ... iff needed */ | 56 | if (likely (len < count)) /* ... iff needed */ |
57 | count = len; | 57 | count = len; |
@@ -62,8 +62,9 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, | |||
62 | /* per-qtd limit: from 16K to 20K (best alignment) */ | 62 | /* per-qtd limit: from 16K to 20K (best alignment) */ |
63 | for (i = 1; count < len && i < 5; i++) { | 63 | for (i = 1; count < len && i < 5; i++) { |
64 | addr = buf; | 64 | addr = buf; |
65 | qtd->hw_buf [i] = cpu_to_le32 ((u32)addr); | 65 | qtd->hw_buf[i] = cpu_to_hc32(ehci, (u32)addr); |
66 | qtd->hw_buf_hi [i] = cpu_to_le32 ((u32)(addr >> 32)); | 66 | qtd->hw_buf_hi[i] = cpu_to_hc32(ehci, |
67 | (u32)(addr >> 32)); | ||
67 | buf += 0x1000; | 68 | buf += 0x1000; |
68 | if ((count + 0x1000) < len) | 69 | if ((count + 0x1000) < len) |
69 | count += 0x1000; | 70 | count += 0x1000; |
@@ -75,7 +76,7 @@ qtd_fill (struct ehci_qtd *qtd, dma_addr_t buf, size_t len, | |||
75 | if (count != len) | 76 | if (count != len) |
76 | count -= (count % maxpacket); | 77 | count -= (count % maxpacket); |
77 | } | 78 | } |
78 | qtd->hw_token = cpu_to_le32 ((count << 16) | token); | 79 | qtd->hw_token = cpu_to_hc32(ehci, (count << 16) | token); |
79 | qtd->length = count; | 80 | qtd->length = count; |
80 | 81 | ||
81 | return count; | 82 | return count; |
@@ -89,28 +90,28 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) | |||
89 | /* writes to an active overlay are unsafe */ | 90 | /* writes to an active overlay are unsafe */ |
90 | BUG_ON(qh->qh_state != QH_STATE_IDLE); | 91 | BUG_ON(qh->qh_state != QH_STATE_IDLE); |
91 | 92 | ||
92 | qh->hw_qtd_next = QTD_NEXT (qtd->qtd_dma); | 93 | qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); |
93 | qh->hw_alt_next = EHCI_LIST_END; | 94 | qh->hw_alt_next = EHCI_LIST_END(ehci); |
94 | 95 | ||
95 | /* Except for control endpoints, we make hardware maintain data | 96 | /* Except for control endpoints, we make hardware maintain data |
96 | * toggle (like OHCI) ... here (re)initialize the toggle in the QH, | 97 | * toggle (like OHCI) ... here (re)initialize the toggle in the QH, |
97 | * and set the pseudo-toggle in udev. Only usb_clear_halt() will | 98 | * and set the pseudo-toggle in udev. Only usb_clear_halt() will |
98 | * ever clear it. | 99 | * ever clear it. |
99 | */ | 100 | */ |
100 | if (!(qh->hw_info1 & cpu_to_le32(1 << 14))) { | 101 | if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { |
101 | unsigned is_out, epnum; | 102 | unsigned is_out, epnum; |
102 | 103 | ||
103 | is_out = !(qtd->hw_token & cpu_to_le32(1 << 8)); | 104 | is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8)); |
104 | epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f; | 105 | epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f; |
105 | if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { | 106 | if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { |
106 | qh->hw_token &= ~__constant_cpu_to_le32 (QTD_TOGGLE); | 107 | qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); |
107 | usb_settoggle (qh->dev, epnum, is_out, 1); | 108 | usb_settoggle (qh->dev, epnum, is_out, 1); |
108 | } | 109 | } |
109 | } | 110 | } |
110 | 111 | ||
111 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ | 112 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ |
112 | wmb (); | 113 | wmb (); |
113 | qh->hw_token &= __constant_cpu_to_le32 (QTD_TOGGLE | QTD_STS_PING); | 114 | qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); |
114 | } | 115 | } |
115 | 116 | ||
116 | /* if it weren't for a common silicon quirk (writing the dummy into the qh | 117 | /* if it weren't for a common silicon quirk (writing the dummy into the qh |
@@ -128,7 +129,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
128 | qtd = list_entry (qh->qtd_list.next, | 129 | qtd = list_entry (qh->qtd_list.next, |
129 | struct ehci_qtd, qtd_list); | 130 | struct ehci_qtd, qtd_list); |
130 | /* first qtd may already be partially processed */ | 131 | /* first qtd may already be partially processed */ |
131 | if (cpu_to_le32 (qtd->qtd_dma) == qh->hw_current) | 132 | if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw_current) |
132 | qtd = NULL; | 133 | qtd = NULL; |
133 | } | 134 | } |
134 | 135 | ||
@@ -222,7 +223,7 @@ __acquires(ehci->lock) | |||
222 | struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; | 223 | struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; |
223 | 224 | ||
224 | /* S-mask in a QH means it's an interrupt urb */ | 225 | /* S-mask in a QH means it's an interrupt urb */ |
225 | if ((qh->hw_info2 & __constant_cpu_to_le32 (QH_SMASK)) != 0) { | 226 | if ((qh->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { |
226 | 227 | ||
227 | /* ... update hc-wide periodic stats (for usbfs) */ | 228 | /* ... update hc-wide periodic stats (for usbfs) */ |
228 | ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; | 229 | ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; |
@@ -277,7 +278,6 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); | |||
277 | * Chases up to qh->hw_current. Returns number of completions called, | 278 | * Chases up to qh->hw_current. Returns number of completions called, |
278 | * indicating how much "real" work we did. | 279 | * indicating how much "real" work we did. |
279 | */ | 280 | */ |
280 | #define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT) | ||
281 | static unsigned | 281 | static unsigned |
282 | qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | 282 | qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) |
283 | { | 283 | { |
@@ -287,6 +287,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
287 | unsigned count = 0; | 287 | unsigned count = 0; |
288 | int do_status = 0; | 288 | int do_status = 0; |
289 | u8 state; | 289 | u8 state; |
290 | u32 halt = HALT_BIT(ehci); | ||
290 | 291 | ||
291 | if (unlikely (list_empty (&qh->qtd_list))) | 292 | if (unlikely (list_empty (&qh->qtd_list))) |
292 | return count; | 293 | return count; |
@@ -311,6 +312,10 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
311 | struct urb *urb; | 312 | struct urb *urb; |
312 | u32 token = 0; | 313 | u32 token = 0; |
313 | 314 | ||
315 | /* ignore QHs that are currently inactive */ | ||
316 | if (qh->hw_info1 & __constant_cpu_to_le32(QH_INACTIVATE)) | ||
317 | break; | ||
318 | |||
314 | qtd = list_entry (entry, struct ehci_qtd, qtd_list); | 319 | qtd = list_entry (entry, struct ehci_qtd, qtd_list); |
315 | urb = qtd->urb; | 320 | urb = qtd->urb; |
316 | 321 | ||
@@ -330,7 +335,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
330 | 335 | ||
331 | /* hardware copies qtd out of qh overlay */ | 336 | /* hardware copies qtd out of qh overlay */ |
332 | rmb (); | 337 | rmb (); |
333 | token = le32_to_cpu (qtd->hw_token); | 338 | token = hc32_to_cpu(ehci, qtd->hw_token); |
334 | 339 | ||
335 | /* always clean up qtds the hc de-activated */ | 340 | /* always clean up qtds the hc de-activated */ |
336 | if ((token & QTD_STS_ACTIVE) == 0) { | 341 | if ((token & QTD_STS_ACTIVE) == 0) { |
@@ -342,7 +347,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
342 | * that silicon quirk can kick in with this dummy too. | 347 | * that silicon quirk can kick in with this dummy too. |
343 | */ | 348 | */ |
344 | } else if (IS_SHORT_READ (token) | 349 | } else if (IS_SHORT_READ (token) |
345 | && !(qtd->hw_alt_next & EHCI_LIST_END)) { | 350 | && !(qtd->hw_alt_next |
351 | & EHCI_LIST_END(ehci))) { | ||
346 | stopped = 1; | 352 | stopped = 1; |
347 | goto halt; | 353 | goto halt; |
348 | } | 354 | } |
@@ -374,17 +380,17 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
374 | 380 | ||
375 | /* token in overlay may be most current */ | 381 | /* token in overlay may be most current */ |
376 | if (state == QH_STATE_IDLE | 382 | if (state == QH_STATE_IDLE |
377 | && cpu_to_le32 (qtd->qtd_dma) | 383 | && cpu_to_hc32(ehci, qtd->qtd_dma) |
378 | == qh->hw_current) | 384 | == qh->hw_current) |
379 | token = le32_to_cpu (qh->hw_token); | 385 | token = hc32_to_cpu(ehci, qh->hw_token); |
380 | 386 | ||
381 | /* force halt for unlinked or blocked qh, so we'll | 387 | /* force halt for unlinked or blocked qh, so we'll |
382 | * patch the qh later and so that completions can't | 388 | * patch the qh later and so that completions can't |
383 | * activate it while we "know" it's stopped. | 389 | * activate it while we "know" it's stopped. |
384 | */ | 390 | */ |
385 | if ((HALT_BIT & qh->hw_token) == 0) { | 391 | if ((halt & qh->hw_token) == 0) { |
386 | halt: | 392 | halt: |
387 | qh->hw_token |= HALT_BIT; | 393 | qh->hw_token |= halt; |
388 | wmb (); | 394 | wmb (); |
389 | } | 395 | } |
390 | } | 396 | } |
@@ -419,7 +425,7 @@ halt: | |||
419 | * it after fault cleanup, or recovering from silicon wrongly | 425 | * it after fault cleanup, or recovering from silicon wrongly |
420 | * overlaying the dummy qtd (which reduces DMA chatter). | 426 | * overlaying the dummy qtd (which reduces DMA chatter). |
421 | */ | 427 | */ |
422 | if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END) { | 428 | if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) { |
423 | switch (state) { | 429 | switch (state) { |
424 | case QH_STATE_IDLE: | 430 | case QH_STATE_IDLE: |
425 | qh_refresh(ehci, qh); | 431 | qh_refresh(ehci, qh); |
@@ -428,7 +434,7 @@ halt: | |||
428 | /* should be rare for periodic transfers, | 434 | /* should be rare for periodic transfers, |
429 | * except maybe high bandwidth ... | 435 | * except maybe high bandwidth ... |
430 | */ | 436 | */ |
431 | if ((__constant_cpu_to_le32 (QH_SMASK) | 437 | if ((cpu_to_hc32(ehci, QH_SMASK) |
432 | & qh->hw_info2) != 0) { | 438 | & qh->hw_info2) != 0) { |
433 | intr_deschedule (ehci, qh); | 439 | intr_deschedule (ehci, qh); |
434 | (void) qh_schedule (ehci, qh); | 440 | (void) qh_schedule (ehci, qh); |
@@ -502,8 +508,9 @@ qh_urb_transaction ( | |||
502 | is_input = usb_pipein (urb->pipe); | 508 | is_input = usb_pipein (urb->pipe); |
503 | if (usb_pipecontrol (urb->pipe)) { | 509 | if (usb_pipecontrol (urb->pipe)) { |
504 | /* SETUP pid */ | 510 | /* SETUP pid */ |
505 | qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest), | 511 | qtd_fill(ehci, qtd, urb->setup_dma, |
506 | token | (2 /* "setup" */ << 8), 8); | 512 | sizeof (struct usb_ctrlrequest), |
513 | token | (2 /* "setup" */ << 8), 8); | ||
507 | 514 | ||
508 | /* ... and always at least one more pid */ | 515 | /* ... and always at least one more pid */ |
509 | token ^= QTD_TOGGLE; | 516 | token ^= QTD_TOGGLE; |
@@ -512,7 +519,7 @@ qh_urb_transaction ( | |||
512 | if (unlikely (!qtd)) | 519 | if (unlikely (!qtd)) |
513 | goto cleanup; | 520 | goto cleanup; |
514 | qtd->urb = urb; | 521 | qtd->urb = urb; |
515 | qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); | 522 | qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); |
516 | list_add_tail (&qtd->qtd_list, head); | 523 | list_add_tail (&qtd->qtd_list, head); |
517 | 524 | ||
518 | /* for zero length DATA stages, STATUS is always IN */ | 525 | /* for zero length DATA stages, STATUS is always IN */ |
@@ -539,7 +546,7 @@ qh_urb_transaction ( | |||
539 | for (;;) { | 546 | for (;;) { |
540 | int this_qtd_len; | 547 | int this_qtd_len; |
541 | 548 | ||
542 | this_qtd_len = qtd_fill (qtd, buf, len, token, maxpacket); | 549 | this_qtd_len = qtd_fill(ehci, qtd, buf, len, token, maxpacket); |
543 | len -= this_qtd_len; | 550 | len -= this_qtd_len; |
544 | buf += this_qtd_len; | 551 | buf += this_qtd_len; |
545 | if (is_input) | 552 | if (is_input) |
@@ -557,7 +564,7 @@ qh_urb_transaction ( | |||
557 | if (unlikely (!qtd)) | 564 | if (unlikely (!qtd)) |
558 | goto cleanup; | 565 | goto cleanup; |
559 | qtd->urb = urb; | 566 | qtd->urb = urb; |
560 | qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); | 567 | qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); |
561 | list_add_tail (&qtd->qtd_list, head); | 568 | list_add_tail (&qtd->qtd_list, head); |
562 | } | 569 | } |
563 | 570 | ||
@@ -566,7 +573,7 @@ qh_urb_transaction ( | |||
566 | */ | 573 | */ |
567 | if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 | 574 | if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 |
568 | || usb_pipecontrol (urb->pipe))) | 575 | || usb_pipecontrol (urb->pipe))) |
569 | qtd->hw_alt_next = EHCI_LIST_END; | 576 | qtd->hw_alt_next = EHCI_LIST_END(ehci); |
570 | 577 | ||
571 | /* | 578 | /* |
572 | * control requests may need a terminating data "status" ack; | 579 | * control requests may need a terminating data "status" ack; |
@@ -590,17 +597,17 @@ qh_urb_transaction ( | |||
590 | if (unlikely (!qtd)) | 597 | if (unlikely (!qtd)) |
591 | goto cleanup; | 598 | goto cleanup; |
592 | qtd->urb = urb; | 599 | qtd->urb = urb; |
593 | qtd_prev->hw_next = QTD_NEXT (qtd->qtd_dma); | 600 | qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); |
594 | list_add_tail (&qtd->qtd_list, head); | 601 | list_add_tail (&qtd->qtd_list, head); |
595 | 602 | ||
596 | /* never any data in such packets */ | 603 | /* never any data in such packets */ |
597 | qtd_fill (qtd, 0, 0, token, 0); | 604 | qtd_fill(ehci, qtd, 0, 0, token, 0); |
598 | } | 605 | } |
599 | } | 606 | } |
600 | 607 | ||
601 | /* by default, enable interrupt on urb completion */ | 608 | /* by default, enable interrupt on urb completion */ |
602 | if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT))) | 609 | if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT))) |
603 | qtd->hw_token |= __constant_cpu_to_le32 (QTD_IOC); | 610 | qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC); |
604 | return head; | 611 | return head; |
605 | 612 | ||
606 | cleanup: | 613 | cleanup: |
@@ -769,8 +776,8 @@ done: | |||
769 | 776 | ||
770 | /* init as live, toggle clear, advance to dummy */ | 777 | /* init as live, toggle clear, advance to dummy */ |
771 | qh->qh_state = QH_STATE_IDLE; | 778 | qh->qh_state = QH_STATE_IDLE; |
772 | qh->hw_info1 = cpu_to_le32 (info1); | 779 | qh->hw_info1 = cpu_to_hc32(ehci, info1); |
773 | qh->hw_info2 = cpu_to_le32 (info2); | 780 | qh->hw_info2 = cpu_to_hc32(ehci, info2); |
774 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); | 781 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); |
775 | qh_refresh (ehci, qh); | 782 | qh_refresh (ehci, qh); |
776 | return qh; | 783 | return qh; |
@@ -782,7 +789,7 @@ done: | |||
782 | 789 | ||
783 | static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | 790 | static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) |
784 | { | 791 | { |
785 | __le32 dma = QH_NEXT (qh->qh_dma); | 792 | __hc32 dma = QH_NEXT(ehci, qh->qh_dma); |
786 | struct ehci_qh *head; | 793 | struct ehci_qh *head; |
787 | 794 | ||
788 | /* (re)start the async schedule? */ | 795 | /* (re)start the async schedule? */ |
@@ -820,8 +827,6 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
820 | 827 | ||
821 | /*-------------------------------------------------------------------------*/ | 828 | /*-------------------------------------------------------------------------*/ |
822 | 829 | ||
823 | #define QH_ADDR_MASK __constant_cpu_to_le32(0x7f) | ||
824 | |||
825 | /* | 830 | /* |
826 | * For control/bulk/interrupt, return QH with these TDs appended. | 831 | * For control/bulk/interrupt, return QH with these TDs appended. |
827 | * Allocates and initializes the QH if necessary. | 832 | * Allocates and initializes the QH if necessary. |
@@ -837,6 +842,7 @@ static struct ehci_qh *qh_append_tds ( | |||
837 | ) | 842 | ) |
838 | { | 843 | { |
839 | struct ehci_qh *qh = NULL; | 844 | struct ehci_qh *qh = NULL; |
845 | u32 qh_addr_mask = cpu_to_hc32(ehci, 0x7f); | ||
840 | 846 | ||
841 | qh = (struct ehci_qh *) *ptr; | 847 | qh = (struct ehci_qh *) *ptr; |
842 | if (unlikely (qh == NULL)) { | 848 | if (unlikely (qh == NULL)) { |
@@ -858,7 +864,7 @@ static struct ehci_qh *qh_append_tds ( | |||
858 | 864 | ||
859 | /* usb_reset_device() briefly reverts to address 0 */ | 865 | /* usb_reset_device() briefly reverts to address 0 */ |
860 | if (usb_pipedevice (urb->pipe) == 0) | 866 | if (usb_pipedevice (urb->pipe) == 0) |
861 | qh->hw_info1 &= ~QH_ADDR_MASK; | 867 | qh->hw_info1 &= ~qh_addr_mask; |
862 | } | 868 | } |
863 | 869 | ||
864 | /* just one way to queue requests: swap with the dummy qtd. | 870 | /* just one way to queue requests: swap with the dummy qtd. |
@@ -867,7 +873,7 @@ static struct ehci_qh *qh_append_tds ( | |||
867 | if (likely (qtd != NULL)) { | 873 | if (likely (qtd != NULL)) { |
868 | struct ehci_qtd *dummy; | 874 | struct ehci_qtd *dummy; |
869 | dma_addr_t dma; | 875 | dma_addr_t dma; |
870 | __le32 token; | 876 | __hc32 token; |
871 | 877 | ||
872 | /* to avoid racing the HC, use the dummy td instead of | 878 | /* to avoid racing the HC, use the dummy td instead of |
873 | * the first td of our list (becomes new dummy). both | 879 | * the first td of our list (becomes new dummy). both |
@@ -875,7 +881,7 @@ static struct ehci_qh *qh_append_tds ( | |||
875 | * HC is allowed to fetch the old dummy (4.10.2). | 881 | * HC is allowed to fetch the old dummy (4.10.2). |
876 | */ | 882 | */ |
877 | token = qtd->hw_token; | 883 | token = qtd->hw_token; |
878 | qtd->hw_token = HALT_BIT; | 884 | qtd->hw_token = HALT_BIT(ehci); |
879 | wmb (); | 885 | wmb (); |
880 | dummy = qh->dummy; | 886 | dummy = qh->dummy; |
881 | 887 | ||
@@ -887,14 +893,14 @@ static struct ehci_qh *qh_append_tds ( | |||
887 | list_add (&dummy->qtd_list, qtd_list); | 893 | list_add (&dummy->qtd_list, qtd_list); |
888 | __list_splice (qtd_list, qh->qtd_list.prev); | 894 | __list_splice (qtd_list, qh->qtd_list.prev); |
889 | 895 | ||
890 | ehci_qtd_init (qtd, qtd->qtd_dma); | 896 | ehci_qtd_init(ehci, qtd, qtd->qtd_dma); |
891 | qh->dummy = qtd; | 897 | qh->dummy = qtd; |
892 | 898 | ||
893 | /* hc must see the new dummy at list end */ | 899 | /* hc must see the new dummy at list end */ |
894 | dma = qtd->qtd_dma; | 900 | dma = qtd->qtd_dma; |
895 | qtd = list_entry (qh->qtd_list.prev, | 901 | qtd = list_entry (qh->qtd_list.prev, |
896 | struct ehci_qtd, qtd_list); | 902 | struct ehci_qtd, qtd_list); |
897 | qtd->hw_next = QTD_NEXT (dma); | 903 | qtd->hw_next = QTD_NEXT(ehci, dma); |
898 | 904 | ||
899 | /* let the hc process these next qtds */ | 905 | /* let the hc process these next qtds */ |
900 | wmb (); | 906 | wmb (); |
@@ -970,7 +976,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) | |||
970 | 976 | ||
971 | timer_action_done (ehci, TIMER_IAA_WATCHDOG); | 977 | timer_action_done (ehci, TIMER_IAA_WATCHDOG); |
972 | 978 | ||
973 | // qh->hw_next = cpu_to_le32 (qh->qh_dma); | 979 | // qh->hw_next = cpu_to_hc32(qh->qh_dma); |
974 | qh->qh_state = QH_STATE_IDLE; | 980 | qh->qh_state = QH_STATE_IDLE; |
975 | qh->qh_next.qh = NULL; | 981 | qh->qh_next.qh = NULL; |
976 | qh_put (qh); // refcount from reclaim | 982 | qh_put (qh); // refcount from reclaim |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 7b5ae7111f23..d4a8ace49676 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -44,9 +44,10 @@ static int ehci_get_frame (struct usb_hcd *hcd); | |||
44 | * @tag: hardware tag for type of this record | 44 | * @tag: hardware tag for type of this record |
45 | */ | 45 | */ |
46 | static union ehci_shadow * | 46 | static union ehci_shadow * |
47 | periodic_next_shadow (union ehci_shadow *periodic, __le32 tag) | 47 | periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic, |
48 | __hc32 tag) | ||
48 | { | 49 | { |
49 | switch (tag) { | 50 | switch (hc32_to_cpu(ehci, tag)) { |
50 | case Q_TYPE_QH: | 51 | case Q_TYPE_QH: |
51 | return &periodic->qh->qh_next; | 52 | return &periodic->qh->qh_next; |
52 | case Q_TYPE_FSTN: | 53 | case Q_TYPE_FSTN: |
@@ -62,13 +63,14 @@ periodic_next_shadow (union ehci_shadow *periodic, __le32 tag) | |||
62 | /* caller must hold ehci->lock */ | 63 | /* caller must hold ehci->lock */ |
63 | static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) | 64 | static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) |
64 | { | 65 | { |
65 | union ehci_shadow *prev_p = &ehci->pshadow [frame]; | 66 | union ehci_shadow *prev_p = &ehci->pshadow[frame]; |
66 | __le32 *hw_p = &ehci->periodic [frame]; | 67 | __hc32 *hw_p = &ehci->periodic[frame]; |
67 | union ehci_shadow here = *prev_p; | 68 | union ehci_shadow here = *prev_p; |
68 | 69 | ||
69 | /* find predecessor of "ptr"; hw and shadow lists are in sync */ | 70 | /* find predecessor of "ptr"; hw and shadow lists are in sync */ |
70 | while (here.ptr && here.ptr != ptr) { | 71 | while (here.ptr && here.ptr != ptr) { |
71 | prev_p = periodic_next_shadow (prev_p, Q_NEXT_TYPE (*hw_p)); | 72 | prev_p = periodic_next_shadow(ehci, prev_p, |
73 | Q_NEXT_TYPE(ehci, *hw_p)); | ||
72 | hw_p = here.hw_next; | 74 | hw_p = here.hw_next; |
73 | here = *prev_p; | 75 | here = *prev_p; |
74 | } | 76 | } |
@@ -79,7 +81,8 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) | |||
79 | /* update shadow and hardware lists ... the old "next" pointers | 81 | /* update shadow and hardware lists ... the old "next" pointers |
80 | * from ptr may still be in use, the caller updates them. | 82 | * from ptr may still be in use, the caller updates them. |
81 | */ | 83 | */ |
82 | *prev_p = *periodic_next_shadow (&here, Q_NEXT_TYPE (*hw_p)); | 84 | *prev_p = *periodic_next_shadow(ehci, &here, |
85 | Q_NEXT_TYPE(ehci, *hw_p)); | ||
83 | *hw_p = *here.hw_next; | 86 | *hw_p = *here.hw_next; |
84 | } | 87 | } |
85 | 88 | ||
@@ -87,18 +90,19 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) | |||
87 | static unsigned short | 90 | static unsigned short |
88 | periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) | 91 | periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) |
89 | { | 92 | { |
90 | __le32 *hw_p = &ehci->periodic [frame]; | 93 | __hc32 *hw_p = &ehci->periodic [frame]; |
91 | union ehci_shadow *q = &ehci->pshadow [frame]; | 94 | union ehci_shadow *q = &ehci->pshadow [frame]; |
92 | unsigned usecs = 0; | 95 | unsigned usecs = 0; |
93 | 96 | ||
94 | while (q->ptr) { | 97 | while (q->ptr) { |
95 | switch (Q_NEXT_TYPE (*hw_p)) { | 98 | switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) { |
96 | case Q_TYPE_QH: | 99 | case Q_TYPE_QH: |
97 | /* is it in the S-mask? */ | 100 | /* is it in the S-mask? */ |
98 | if (q->qh->hw_info2 & cpu_to_le32 (1 << uframe)) | 101 | if (q->qh->hw_info2 & cpu_to_hc32(ehci, 1 << uframe)) |
99 | usecs += q->qh->usecs; | 102 | usecs += q->qh->usecs; |
100 | /* ... or C-mask? */ | 103 | /* ... or C-mask? */ |
101 | if (q->qh->hw_info2 & cpu_to_le32 (1 << (8 + uframe))) | 104 | if (q->qh->hw_info2 & cpu_to_hc32(ehci, |
105 | 1 << (8 + uframe))) | ||
102 | usecs += q->qh->c_usecs; | 106 | usecs += q->qh->c_usecs; |
103 | hw_p = &q->qh->hw_next; | 107 | hw_p = &q->qh->hw_next; |
104 | q = &q->qh->qh_next; | 108 | q = &q->qh->qh_next; |
@@ -108,7 +112,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) | |||
108 | /* for "save place" FSTNs, count the relevant INTR | 112 | /* for "save place" FSTNs, count the relevant INTR |
109 | * bandwidth from the previous frame | 113 | * bandwidth from the previous frame |
110 | */ | 114 | */ |
111 | if (q->fstn->hw_prev != EHCI_LIST_END) { | 115 | if (q->fstn->hw_prev != EHCI_LIST_END(ehci)) { |
112 | ehci_dbg (ehci, "ignoring FSTN cost ...\n"); | 116 | ehci_dbg (ehci, "ignoring FSTN cost ...\n"); |
113 | } | 117 | } |
114 | hw_p = &q->fstn->hw_next; | 118 | hw_p = &q->fstn->hw_next; |
@@ -121,9 +125,10 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) | |||
121 | break; | 125 | break; |
122 | case Q_TYPE_SITD: | 126 | case Q_TYPE_SITD: |
123 | /* is it in the S-mask? (count SPLIT, DATA) */ | 127 | /* is it in the S-mask? (count SPLIT, DATA) */ |
124 | if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) { | 128 | if (q->sitd->hw_uframe & cpu_to_hc32(ehci, |
129 | 1 << uframe)) { | ||
125 | if (q->sitd->hw_fullspeed_ep & | 130 | if (q->sitd->hw_fullspeed_ep & |
126 | __constant_cpu_to_le32 (1<<31)) | 131 | cpu_to_hc32(ehci, 1<<31)) |
127 | usecs += q->sitd->stream->usecs; | 132 | usecs += q->sitd->stream->usecs; |
128 | else /* worst case for OUT start-split */ | 133 | else /* worst case for OUT start-split */ |
129 | usecs += HS_USECS_ISO (188); | 134 | usecs += HS_USECS_ISO (188); |
@@ -131,7 +136,7 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) | |||
131 | 136 | ||
132 | /* ... C-mask? (count CSPLIT, DATA) */ | 137 | /* ... C-mask? (count CSPLIT, DATA) */ |
133 | if (q->sitd->hw_uframe & | 138 | if (q->sitd->hw_uframe & |
134 | cpu_to_le32 (1 << (8 + uframe))) { | 139 | cpu_to_hc32(ehci, 1 << (8 + uframe))) { |
135 | /* worst case for IN complete-split */ | 140 | /* worst case for IN complete-split */ |
136 | usecs += q->sitd->stream->c_usecs; | 141 | usecs += q->sitd->stream->c_usecs; |
137 | } | 142 | } |
@@ -173,9 +178,9 @@ static int same_tt (struct usb_device *dev1, struct usb_device *dev2) | |||
173 | * will cause a transfer in "B-frame" uframe 0. "B-frames" lag | 178 | * will cause a transfer in "B-frame" uframe 0. "B-frames" lag |
174 | * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. | 179 | * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. |
175 | */ | 180 | */ |
176 | static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __le32 mask) | 181 | static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) |
177 | { | 182 | { |
178 | unsigned char smask = QH_SMASK & le32_to_cpu(mask); | 183 | unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask); |
179 | if (!smask) { | 184 | if (!smask) { |
180 | ehci_err(ehci, "invalid empty smask!\n"); | 185 | ehci_err(ehci, "invalid empty smask!\n"); |
181 | /* uframe 7 can't have bw so this will indicate failure */ | 186 | /* uframe 7 can't have bw so this will indicate failure */ |
@@ -217,14 +222,14 @@ periodic_tt_usecs ( | |||
217 | unsigned short tt_usecs[8] | 222 | unsigned short tt_usecs[8] |
218 | ) | 223 | ) |
219 | { | 224 | { |
220 | __le32 *hw_p = &ehci->periodic [frame]; | 225 | __hc32 *hw_p = &ehci->periodic [frame]; |
221 | union ehci_shadow *q = &ehci->pshadow [frame]; | 226 | union ehci_shadow *q = &ehci->pshadow [frame]; |
222 | unsigned char uf; | 227 | unsigned char uf; |
223 | 228 | ||
224 | memset(tt_usecs, 0, 16); | 229 | memset(tt_usecs, 0, 16); |
225 | 230 | ||
226 | while (q->ptr) { | 231 | while (q->ptr) { |
227 | switch (Q_NEXT_TYPE(*hw_p)) { | 232 | switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) { |
228 | case Q_TYPE_ITD: | 233 | case Q_TYPE_ITD: |
229 | hw_p = &q->itd->hw_next; | 234 | hw_p = &q->itd->hw_next; |
230 | q = &q->itd->itd_next; | 235 | q = &q->itd->itd_next; |
@@ -247,8 +252,8 @@ periodic_tt_usecs ( | |||
247 | continue; | 252 | continue; |
248 | // case Q_TYPE_FSTN: | 253 | // case Q_TYPE_FSTN: |
249 | default: | 254 | default: |
250 | ehci_dbg(ehci, | 255 | ehci_dbg(ehci, "ignoring periodic frame %d FSTN\n", |
251 | "ignoring periodic frame %d FSTN\n", frame); | 256 | frame); |
252 | hw_p = &q->fstn->hw_next; | 257 | hw_p = &q->fstn->hw_next; |
253 | q = &q->fstn->fstn_next; | 258 | q = &q->fstn->fstn_next; |
254 | } | 259 | } |
@@ -368,41 +373,42 @@ static int tt_no_collision ( | |||
368 | */ | 373 | */ |
369 | for (; frame < ehci->periodic_size; frame += period) { | 374 | for (; frame < ehci->periodic_size; frame += period) { |
370 | union ehci_shadow here; | 375 | union ehci_shadow here; |
371 | __le32 type; | 376 | __hc32 type; |
372 | 377 | ||
373 | here = ehci->pshadow [frame]; | 378 | here = ehci->pshadow [frame]; |
374 | type = Q_NEXT_TYPE (ehci->periodic [frame]); | 379 | type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]); |
375 | while (here.ptr) { | 380 | while (here.ptr) { |
376 | switch (type) { | 381 | switch (hc32_to_cpu(ehci, type)) { |
377 | case Q_TYPE_ITD: | 382 | case Q_TYPE_ITD: |
378 | type = Q_NEXT_TYPE (here.itd->hw_next); | 383 | type = Q_NEXT_TYPE(ehci, here.itd->hw_next); |
379 | here = here.itd->itd_next; | 384 | here = here.itd->itd_next; |
380 | continue; | 385 | continue; |
381 | case Q_TYPE_QH: | 386 | case Q_TYPE_QH: |
382 | if (same_tt (dev, here.qh->dev)) { | 387 | if (same_tt (dev, here.qh->dev)) { |
383 | u32 mask; | 388 | u32 mask; |
384 | 389 | ||
385 | mask = le32_to_cpu (here.qh->hw_info2); | 390 | mask = hc32_to_cpu(ehci, |
391 | here.qh->hw_info2); | ||
386 | /* "knows" no gap is needed */ | 392 | /* "knows" no gap is needed */ |
387 | mask |= mask >> 8; | 393 | mask |= mask >> 8; |
388 | if (mask & uf_mask) | 394 | if (mask & uf_mask) |
389 | break; | 395 | break; |
390 | } | 396 | } |
391 | type = Q_NEXT_TYPE (here.qh->hw_next); | 397 | type = Q_NEXT_TYPE(ehci, here.qh->hw_next); |
392 | here = here.qh->qh_next; | 398 | here = here.qh->qh_next; |
393 | continue; | 399 | continue; |
394 | case Q_TYPE_SITD: | 400 | case Q_TYPE_SITD: |
395 | if (same_tt (dev, here.sitd->urb->dev)) { | 401 | if (same_tt (dev, here.sitd->urb->dev)) { |
396 | u16 mask; | 402 | u16 mask; |
397 | 403 | ||
398 | mask = le32_to_cpu (here.sitd | 404 | mask = hc32_to_cpu(ehci, here.sitd |
399 | ->hw_uframe); | 405 | ->hw_uframe); |
400 | /* FIXME assumes no gap for IN! */ | 406 | /* FIXME assumes no gap for IN! */ |
401 | mask |= mask >> 8; | 407 | mask |= mask >> 8; |
402 | if (mask & uf_mask) | 408 | if (mask & uf_mask) |
403 | break; | 409 | break; |
404 | } | 410 | } |
405 | type = Q_NEXT_TYPE (here.sitd->hw_next); | 411 | type = Q_NEXT_TYPE(ehci, here.sitd->hw_next); |
406 | here = here.sitd->sitd_next; | 412 | here = here.sitd->sitd_next; |
407 | continue; | 413 | continue; |
408 | // case Q_TYPE_FSTN: | 414 | // case Q_TYPE_FSTN: |
@@ -473,6 +479,109 @@ static int disable_periodic (struct ehci_hcd *ehci) | |||
473 | } | 479 | } |
474 | 480 | ||
475 | /*-------------------------------------------------------------------------*/ | 481 | /*-------------------------------------------------------------------------*/ |
482 | #ifdef CONFIG_CPU_FREQ | ||
483 | |||
484 | static int safe_to_modify_i (struct ehci_hcd *ehci, struct ehci_qh *qh) | ||
485 | { | ||
486 | int now; /* current (frame * 8) + uframe */ | ||
487 | int prev_start, next_start; /* uframes from/to split start */ | ||
488 | int start_uframe = ffs(le32_to_cpup (&qh->hw_info2) & QH_SMASK); | ||
489 | int end_uframe = fls((le32_to_cpup (&qh->hw_info2) & QH_CMASK) >> 8); | ||
490 | int split_duration = end_uframe - start_uframe; | ||
491 | |||
492 | now = readl(&ehci->regs->frame_index) % (ehci->periodic_size << 3); | ||
493 | |||
494 | next_start = ((1024 << 3) + (qh->start << 3) + start_uframe - now) | ||
495 | % (qh->period << 3); | ||
496 | prev_start = (qh->period << 3) - next_start; | ||
497 | |||
498 | /* | ||
499 | * Make sure there will be at least one uframe when qh is safe. | ||
500 | */ | ||
501 | if ((qh->period << 3) <= (ehci->i_thresh + 2 + split_duration)) | ||
502 | /* never safe */ | ||
503 | return -EINVAL; | ||
504 | |||
505 | /* | ||
506 | * Wait 1 uframe after transaction should have started, to make | ||
507 | * sure controller has time to write back overlay, so we can | ||
508 | * check QTD_STS_STS to see if transaction is in progress. | ||
509 | */ | ||
510 | if ((next_start > ehci->i_thresh) && (prev_start > 1)) | ||
511 | /* safe to set "i" bit if split isn't in progress */ | ||
512 | return (qh->hw_token & STATUS_BIT(ehci)) ? 0 : 1; | ||
513 | else | ||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | /* Set inactivate bit for all the split interrupt QHs. */ | ||
518 | static void qh_inactivate_split_intr_qhs (struct ehci_hcd *ehci) | ||
519 | { | ||
520 | struct ehci_qh *qh; | ||
521 | int not_done, safe; | ||
522 | u32 inactivate = INACTIVATE_BIT(ehci); | ||
523 | u32 active = ACTIVE_BIT(ehci); | ||
524 | |||
525 | do { | ||
526 | not_done = 0; | ||
527 | list_for_each_entry(qh, &ehci->split_intr_qhs, | ||
528 | split_intr_qhs) { | ||
529 | if (qh->hw_info1 & inactivate) | ||
530 | /* already off */ | ||
531 | continue; | ||
532 | /* | ||
533 | * To avoid setting "I" after the start split happens, | ||
534 | * don't set it if the QH might be cached in the | ||
535 | * controller. Some HCs (Broadcom/ServerWorks HT1000) | ||
536 | * will stop in the middle of a split transaction when | ||
537 | * the "I" bit is set. | ||
538 | */ | ||
539 | safe = safe_to_modify_i(ehci, qh); | ||
540 | if (safe == 0) { | ||
541 | not_done = 1; | ||
542 | } else if (safe > 0) { | ||
543 | qh->was_active = qh->hw_token & active; | ||
544 | qh->hw_info1 |= inactivate; | ||
545 | } | ||
546 | } | ||
547 | } while (not_done); | ||
548 | wmb(); | ||
549 | } | ||
550 | |||
551 | static void qh_reactivate_split_intr_qhs (struct ehci_hcd *ehci) | ||
552 | { | ||
553 | struct ehci_qh *qh; | ||
554 | u32 token; | ||
555 | int not_done, safe; | ||
556 | u32 inactivate = INACTIVATE_BIT(ehci); | ||
557 | u32 active = ACTIVE_BIT(ehci); | ||
558 | u32 halt = HALT_BIT(ehci); | ||
559 | |||
560 | do { | ||
561 | not_done = 0; | ||
562 | list_for_each_entry(qh, &ehci->split_intr_qhs, split_intr_qhs) { | ||
563 | if (!(qh->hw_info1 & inactivate)) /* already on */ | ||
564 | continue; | ||
565 | /* | ||
566 | * Don't reactivate if cached, or controller might | ||
567 | * overwrite overlay after we modify it! | ||
568 | */ | ||
569 | safe = safe_to_modify_i(ehci, qh); | ||
570 | if (safe == 0) { | ||
571 | not_done = 1; | ||
572 | } else if (safe > 0) { | ||
573 | /* See EHCI 1.0 section 4.15.2.4. */ | ||
574 | token = qh->hw_token; | ||
575 | qh->hw_token = (token | halt) & ~active; | ||
576 | wmb(); | ||
577 | qh->hw_info1 &= ~inactivate; | ||
578 | wmb(); | ||
579 | qh->hw_token = (token & ~halt) | qh->was_active; | ||
580 | } | ||
581 | } | ||
582 | } while (not_done); | ||
583 | } | ||
584 | #endif | ||
476 | 585 | ||
477 | /* periodic schedule slots have iso tds (normal or split) first, then a | 586 | /* periodic schedule slots have iso tds (normal or split) first, then a |
478 | * sparse tree for active interrupt transfers. | 587 | * sparse tree for active interrupt transfers. |
@@ -487,25 +596,36 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
487 | 596 | ||
488 | dev_dbg (&qh->dev->dev, | 597 | dev_dbg (&qh->dev->dev, |
489 | "link qh%d-%04x/%p start %d [%d/%d us]\n", | 598 | "link qh%d-%04x/%p start %d [%d/%d us]\n", |
490 | period, le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK), | 599 | period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK), |
491 | qh, qh->start, qh->usecs, qh->c_usecs); | 600 | qh, qh->start, qh->usecs, qh->c_usecs); |
492 | 601 | ||
602 | #ifdef CONFIG_CPU_FREQ | ||
603 | /* | ||
604 | * If low/full speed interrupt QHs are inactive (because of | ||
605 | * cpufreq changing processor speeds), start QH with I flag set-- | ||
606 | * it will automatically be cleared when cpufreq is done. | ||
607 | */ | ||
608 | if (ehci->cpufreq_changing) | ||
609 | if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) | ||
610 | qh->hw_info1 |= INACTIVATE_BIT(ehci); | ||
611 | #endif | ||
612 | |||
493 | /* high bandwidth, or otherwise every microframe */ | 613 | /* high bandwidth, or otherwise every microframe */ |
494 | if (period == 0) | 614 | if (period == 0) |
495 | period = 1; | 615 | period = 1; |
496 | 616 | ||
497 | for (i = qh->start; i < ehci->periodic_size; i += period) { | 617 | for (i = qh->start; i < ehci->periodic_size; i += period) { |
498 | union ehci_shadow *prev = &ehci->pshadow [i]; | 618 | union ehci_shadow *prev = &ehci->pshadow[i]; |
499 | __le32 *hw_p = &ehci->periodic [i]; | 619 | __hc32 *hw_p = &ehci->periodic[i]; |
500 | union ehci_shadow here = *prev; | 620 | union ehci_shadow here = *prev; |
501 | __le32 type = 0; | 621 | __hc32 type = 0; |
502 | 622 | ||
503 | /* skip the iso nodes at list head */ | 623 | /* skip the iso nodes at list head */ |
504 | while (here.ptr) { | 624 | while (here.ptr) { |
505 | type = Q_NEXT_TYPE (*hw_p); | 625 | type = Q_NEXT_TYPE(ehci, *hw_p); |
506 | if (type == Q_TYPE_QH) | 626 | if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) |
507 | break; | 627 | break; |
508 | prev = periodic_next_shadow (prev, type); | 628 | prev = periodic_next_shadow(ehci, prev, type); |
509 | hw_p = &here.qh->hw_next; | 629 | hw_p = &here.qh->hw_next; |
510 | here = *prev; | 630 | here = *prev; |
511 | } | 631 | } |
@@ -527,7 +647,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
527 | qh->hw_next = *hw_p; | 647 | qh->hw_next = *hw_p; |
528 | wmb (); | 648 | wmb (); |
529 | prev->qh = qh; | 649 | prev->qh = qh; |
530 | *hw_p = QH_NEXT (qh->qh_dma); | 650 | *hw_p = QH_NEXT (ehci, qh->qh_dma); |
531 | } | 651 | } |
532 | } | 652 | } |
533 | qh->qh_state = QH_STATE_LINKED; | 653 | qh->qh_state = QH_STATE_LINKED; |
@@ -538,6 +658,12 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
538 | ? ((qh->usecs + qh->c_usecs) / qh->period) | 658 | ? ((qh->usecs + qh->c_usecs) / qh->period) |
539 | : (qh->usecs * 8); | 659 | : (qh->usecs * 8); |
540 | 660 | ||
661 | #ifdef CONFIG_CPU_FREQ | ||
662 | /* add qh to list of low/full speed interrupt QHs, if applicable */ | ||
663 | if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) { | ||
664 | list_add(&qh->split_intr_qhs, &ehci->split_intr_qhs); | ||
665 | } | ||
666 | #endif | ||
541 | /* maybe enable periodic schedule processing */ | 667 | /* maybe enable periodic schedule processing */ |
542 | if (!ehci->periodic_sched++) | 668 | if (!ehci->periodic_sched++) |
543 | return enable_periodic (ehci); | 669 | return enable_periodic (ehci); |
@@ -555,7 +681,14 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
555 | // and this qh is active in the current uframe | 681 | // and this qh is active in the current uframe |
556 | // (and overlay token SplitXstate is false?) | 682 | // (and overlay token SplitXstate is false?) |
557 | // THEN | 683 | // THEN |
558 | // qh->hw_info1 |= __constant_cpu_to_le32 (1 << 7 /* "ignore" */); | 684 | // qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */); |
685 | |||
686 | #ifdef CONFIG_CPU_FREQ | ||
687 | /* remove qh from list of low/full speed interrupt QHs */ | ||
688 | if (!(qh->hw_info1 & (cpu_to_le32(1 << 13)))) { | ||
689 | list_del_init(&qh->split_intr_qhs); | ||
690 | } | ||
691 | #endif | ||
559 | 692 | ||
560 | /* high bandwidth, or otherwise part of every microframe */ | 693 | /* high bandwidth, or otherwise part of every microframe */ |
561 | if ((period = qh->period) == 0) | 694 | if ((period = qh->period) == 0) |
@@ -572,7 +705,7 @@ static void qh_unlink_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
572 | dev_dbg (&qh->dev->dev, | 705 | dev_dbg (&qh->dev->dev, |
573 | "unlink qh%d-%04x/%p start %d [%d/%d us]\n", | 706 | "unlink qh%d-%04x/%p start %d [%d/%d us]\n", |
574 | qh->period, | 707 | qh->period, |
575 | le32_to_cpup (&qh->hw_info2) & (QH_CMASK | QH_SMASK), | 708 | hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK), |
576 | qh, qh->start, qh->usecs, qh->c_usecs); | 709 | qh, qh->start, qh->usecs, qh->c_usecs); |
577 | 710 | ||
578 | /* qh->qh_next still "live" to HC */ | 711 | /* qh->qh_next still "live" to HC */ |
@@ -598,7 +731,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
598 | * active high speed queues may need bigger delays... | 731 | * active high speed queues may need bigger delays... |
599 | */ | 732 | */ |
600 | if (list_empty (&qh->qtd_list) | 733 | if (list_empty (&qh->qtd_list) |
601 | || (__constant_cpu_to_le32 (QH_CMASK) | 734 | || (cpu_to_hc32(ehci, QH_CMASK) |
602 | & qh->hw_info2) != 0) | 735 | & qh->hw_info2) != 0) |
603 | wait = 2; | 736 | wait = 2; |
604 | else | 737 | else |
@@ -606,7 +739,7 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
606 | 739 | ||
607 | udelay (wait); | 740 | udelay (wait); |
608 | qh->qh_state = QH_STATE_IDLE; | 741 | qh->qh_state = QH_STATE_IDLE; |
609 | qh->hw_next = EHCI_LIST_END; | 742 | qh->hw_next = EHCI_LIST_END(ehci); |
610 | wmb (); | 743 | wmb (); |
611 | } | 744 | } |
612 | 745 | ||
@@ -663,7 +796,7 @@ static int check_intr_schedule ( | |||
663 | unsigned frame, | 796 | unsigned frame, |
664 | unsigned uframe, | 797 | unsigned uframe, |
665 | const struct ehci_qh *qh, | 798 | const struct ehci_qh *qh, |
666 | __le32 *c_maskp | 799 | __hc32 *c_maskp |
667 | ) | 800 | ) |
668 | { | 801 | { |
669 | int retval = -ENOSPC; | 802 | int retval = -ENOSPC; |
@@ -695,7 +828,7 @@ static int check_intr_schedule ( | |||
695 | 828 | ||
696 | retval = 0; | 829 | retval = 0; |
697 | 830 | ||
698 | *c_maskp = cpu_to_le32 (mask << 8); | 831 | *c_maskp = cpu_to_hc32(ehci, mask << 8); |
699 | } | 832 | } |
700 | #else | 833 | #else |
701 | /* Make sure this tt's buffer is also available for CSPLITs. | 834 | /* Make sure this tt's buffer is also available for CSPLITs. |
@@ -706,7 +839,7 @@ static int check_intr_schedule ( | |||
706 | * one smart pass... | 839 | * one smart pass... |
707 | */ | 840 | */ |
708 | mask = 0x03 << (uframe + qh->gap_uf); | 841 | mask = 0x03 << (uframe + qh->gap_uf); |
709 | *c_maskp = cpu_to_le32 (mask << 8); | 842 | *c_maskp = cpu_to_hc32(ehci, mask << 8); |
710 | 843 | ||
711 | mask |= 1 << uframe; | 844 | mask |= 1 << uframe; |
712 | if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) { | 845 | if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) { |
@@ -726,20 +859,20 @@ done: | |||
726 | /* "first fit" scheduling policy used the first time through, | 859 | /* "first fit" scheduling policy used the first time through, |
727 | * or when the previous schedule slot can't be re-used. | 860 | * or when the previous schedule slot can't be re-used. |
728 | */ | 861 | */ |
729 | static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | 862 | static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh) |
730 | { | 863 | { |
731 | int status; | 864 | int status; |
732 | unsigned uframe; | 865 | unsigned uframe; |
733 | __le32 c_mask; | 866 | __hc32 c_mask; |
734 | unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ | 867 | unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ |
735 | 868 | ||
736 | qh_refresh(ehci, qh); | 869 | qh_refresh(ehci, qh); |
737 | qh->hw_next = EHCI_LIST_END; | 870 | qh->hw_next = EHCI_LIST_END(ehci); |
738 | frame = qh->start; | 871 | frame = qh->start; |
739 | 872 | ||
740 | /* reuse the previous schedule slots, if we can */ | 873 | /* reuse the previous schedule slots, if we can */ |
741 | if (frame < qh->period) { | 874 | if (frame < qh->period) { |
742 | uframe = ffs (le32_to_cpup (&qh->hw_info2) & QH_SMASK); | 875 | uframe = ffs(hc32_to_cpup(ehci, &qh->hw_info2) & QH_SMASK); |
743 | status = check_intr_schedule (ehci, frame, --uframe, | 876 | status = check_intr_schedule (ehci, frame, --uframe, |
744 | qh, &c_mask); | 877 | qh, &c_mask); |
745 | } else { | 878 | } else { |
@@ -775,10 +908,10 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
775 | qh->start = frame; | 908 | qh->start = frame; |
776 | 909 | ||
777 | /* reset S-frame and (maybe) C-frame masks */ | 910 | /* reset S-frame and (maybe) C-frame masks */ |
778 | qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK)); | 911 | qh->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK)); |
779 | qh->hw_info2 |= qh->period | 912 | qh->hw_info2 |= qh->period |
780 | ? cpu_to_le32 (1 << uframe) | 913 | ? cpu_to_hc32(ehci, 1 << uframe) |
781 | : __constant_cpu_to_le32 (QH_SMASK); | 914 | : cpu_to_hc32(ehci, QH_SMASK); |
782 | qh->hw_info2 |= c_mask; | 915 | qh->hw_info2 |= c_mask; |
783 | } else | 916 | } else |
784 | ehci_dbg (ehci, "reused qh %p schedule\n", qh); | 917 | ehci_dbg (ehci, "reused qh %p schedule\n", qh); |
@@ -808,7 +941,7 @@ static int intr_submit ( | |||
808 | spin_lock_irqsave (&ehci->lock, flags); | 941 | spin_lock_irqsave (&ehci->lock, flags); |
809 | 942 | ||
810 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, | 943 | if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, |
811 | &ehci_to_hcd(ehci)->flags))) { | 944 | &ehci_to_hcd(ehci)->flags))) { |
812 | status = -ESHUTDOWN; | 945 | status = -ESHUTDOWN; |
813 | goto done; | 946 | goto done; |
814 | } | 947 | } |
@@ -898,9 +1031,9 @@ iso_stream_init ( | |||
898 | buf1 |= maxp; | 1031 | buf1 |= maxp; |
899 | maxp *= multi; | 1032 | maxp *= multi; |
900 | 1033 | ||
901 | stream->buf0 = cpu_to_le32 ((epnum << 8) | dev->devnum); | 1034 | stream->buf0 = cpu_to_hc32(ehci, (epnum << 8) | dev->devnum); |
902 | stream->buf1 = cpu_to_le32 (buf1); | 1035 | stream->buf1 = cpu_to_hc32(ehci, buf1); |
903 | stream->buf2 = cpu_to_le32 (multi); | 1036 | stream->buf2 = cpu_to_hc32(ehci, multi); |
904 | 1037 | ||
905 | /* usbfs wants to report the average usecs per frame tied up | 1038 | /* usbfs wants to report the average usecs per frame tied up |
906 | * when transfers on this endpoint are scheduled ... | 1039 | * when transfers on this endpoint are scheduled ... |
@@ -943,7 +1076,7 @@ iso_stream_init ( | |||
943 | bandwidth /= 1 << (interval + 2); | 1076 | bandwidth /= 1 << (interval + 2); |
944 | 1077 | ||
945 | /* stream->splits gets created from raw_mask later */ | 1078 | /* stream->splits gets created from raw_mask later */ |
946 | stream->address = cpu_to_le32 (addr); | 1079 | stream->address = cpu_to_hc32(ehci, addr); |
947 | } | 1080 | } |
948 | stream->bandwidth = bandwidth; | 1081 | stream->bandwidth = bandwidth; |
949 | 1082 | ||
@@ -1077,7 +1210,8 @@ iso_sched_alloc (unsigned packets, gfp_t mem_flags) | |||
1077 | } | 1210 | } |
1078 | 1211 | ||
1079 | static inline void | 1212 | static inline void |
1080 | itd_sched_init ( | 1213 | itd_sched_init( |
1214 | struct ehci_hcd *ehci, | ||
1081 | struct ehci_iso_sched *iso_sched, | 1215 | struct ehci_iso_sched *iso_sched, |
1082 | struct ehci_iso_stream *stream, | 1216 | struct ehci_iso_stream *stream, |
1083 | struct urb *urb | 1217 | struct urb *urb |
@@ -1107,7 +1241,7 @@ itd_sched_init ( | |||
1107 | && !(urb->transfer_flags & URB_NO_INTERRUPT)) | 1241 | && !(urb->transfer_flags & URB_NO_INTERRUPT)) |
1108 | trans |= EHCI_ITD_IOC; | 1242 | trans |= EHCI_ITD_IOC; |
1109 | trans |= length << 16; | 1243 | trans |= length << 16; |
1110 | uframe->transaction = cpu_to_le32 (trans); | 1244 | uframe->transaction = cpu_to_hc32(ehci, trans); |
1111 | 1245 | ||
1112 | /* might need to cross a buffer page within a uframe */ | 1246 | /* might need to cross a buffer page within a uframe */ |
1113 | uframe->bufp = (buf & ~(u64)0x0fff); | 1247 | uframe->bufp = (buf & ~(u64)0x0fff); |
@@ -1149,7 +1283,7 @@ itd_urb_transaction ( | |||
1149 | if (unlikely (sched == NULL)) | 1283 | if (unlikely (sched == NULL)) |
1150 | return -ENOMEM; | 1284 | return -ENOMEM; |
1151 | 1285 | ||
1152 | itd_sched_init (sched, stream, urb); | 1286 | itd_sched_init(ehci, sched, stream, urb); |
1153 | 1287 | ||
1154 | if (urb->interval < 8) | 1288 | if (urb->interval < 8) |
1155 | num_itds = 1 + (sched->span + 7) / 8; | 1289 | num_itds = 1 + (sched->span + 7) / 8; |
@@ -1167,7 +1301,7 @@ itd_urb_transaction ( | |||
1167 | /* prefer previously-allocated itds */ | 1301 | /* prefer previously-allocated itds */ |
1168 | if (likely (!list_empty(&stream->free_list))) { | 1302 | if (likely (!list_empty(&stream->free_list))) { |
1169 | itd = list_entry (stream->free_list.prev, | 1303 | itd = list_entry (stream->free_list.prev, |
1170 | struct ehci_itd, itd_list); | 1304 | struct ehci_itd, itd_list); |
1171 | list_del (&itd->itd_list); | 1305 | list_del (&itd->itd_list); |
1172 | itd_dma = itd->itd_dma; | 1306 | itd_dma = itd->itd_dma; |
1173 | } else | 1307 | } else |
@@ -1294,7 +1428,7 @@ sitd_slot_ok ( | |||
1294 | uframe += period_uframes; | 1428 | uframe += period_uframes; |
1295 | } while (uframe < mod); | 1429 | } while (uframe < mod); |
1296 | 1430 | ||
1297 | stream->splits = cpu_to_le32(stream->raw_mask << (uframe & 7)); | 1431 | stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7)); |
1298 | return 1; | 1432 | return 1; |
1299 | } | 1433 | } |
1300 | 1434 | ||
@@ -1415,12 +1549,13 @@ ready: | |||
1415 | /*-------------------------------------------------------------------------*/ | 1549 | /*-------------------------------------------------------------------------*/ |
1416 | 1550 | ||
1417 | static inline void | 1551 | static inline void |
1418 | itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd) | 1552 | itd_init(struct ehci_hcd *ehci, struct ehci_iso_stream *stream, |
1553 | struct ehci_itd *itd) | ||
1419 | { | 1554 | { |
1420 | int i; | 1555 | int i; |
1421 | 1556 | ||
1422 | /* it's been recently zeroed */ | 1557 | /* it's been recently zeroed */ |
1423 | itd->hw_next = EHCI_LIST_END; | 1558 | itd->hw_next = EHCI_LIST_END(ehci); |
1424 | itd->hw_bufp [0] = stream->buf0; | 1559 | itd->hw_bufp [0] = stream->buf0; |
1425 | itd->hw_bufp [1] = stream->buf1; | 1560 | itd->hw_bufp [1] = stream->buf1; |
1426 | itd->hw_bufp [2] = stream->buf2; | 1561 | itd->hw_bufp [2] = stream->buf2; |
@@ -1432,7 +1567,8 @@ itd_init (struct ehci_iso_stream *stream, struct ehci_itd *itd) | |||
1432 | } | 1567 | } |
1433 | 1568 | ||
1434 | static inline void | 1569 | static inline void |
1435 | itd_patch ( | 1570 | itd_patch( |
1571 | struct ehci_hcd *ehci, | ||
1436 | struct ehci_itd *itd, | 1572 | struct ehci_itd *itd, |
1437 | struct ehci_iso_sched *iso_sched, | 1573 | struct ehci_iso_sched *iso_sched, |
1438 | unsigned index, | 1574 | unsigned index, |
@@ -1447,17 +1583,18 @@ itd_patch ( | |||
1447 | uframe &= 0x07; | 1583 | uframe &= 0x07; |
1448 | itd->index [uframe] = index; | 1584 | itd->index [uframe] = index; |
1449 | 1585 | ||
1450 | itd->hw_transaction [uframe] = uf->transaction; | 1586 | itd->hw_transaction[uframe] = uf->transaction; |
1451 | itd->hw_transaction [uframe] |= cpu_to_le32 (pg << 12); | 1587 | itd->hw_transaction[uframe] |= cpu_to_hc32(ehci, pg << 12); |
1452 | itd->hw_bufp [pg] |= cpu_to_le32 (uf->bufp & ~(u32)0); | 1588 | itd->hw_bufp[pg] |= cpu_to_hc32(ehci, uf->bufp & ~(u32)0); |
1453 | itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(uf->bufp >> 32)); | 1589 | itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(uf->bufp >> 32)); |
1454 | 1590 | ||
1455 | /* iso_frame_desc[].offset must be strictly increasing */ | 1591 | /* iso_frame_desc[].offset must be strictly increasing */ |
1456 | if (unlikely (uf->cross)) { | 1592 | if (unlikely (uf->cross)) { |
1457 | u64 bufp = uf->bufp + 4096; | 1593 | u64 bufp = uf->bufp + 4096; |
1594 | |||
1458 | itd->pg = ++pg; | 1595 | itd->pg = ++pg; |
1459 | itd->hw_bufp [pg] |= cpu_to_le32 (bufp & ~(u32)0); | 1596 | itd->hw_bufp[pg] |= cpu_to_hc32(ehci, bufp & ~(u32)0); |
1460 | itd->hw_bufp_hi [pg] |= cpu_to_le32 ((u32)(bufp >> 32)); | 1597 | itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(bufp >> 32)); |
1461 | } | 1598 | } |
1462 | } | 1599 | } |
1463 | 1600 | ||
@@ -1470,7 +1607,7 @@ itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) | |||
1470 | ehci->pshadow [frame].itd = itd; | 1607 | ehci->pshadow [frame].itd = itd; |
1471 | itd->frame = frame; | 1608 | itd->frame = frame; |
1472 | wmb (); | 1609 | wmb (); |
1473 | ehci->periodic [frame] = cpu_to_le32 (itd->itd_dma) | Q_TYPE_ITD; | 1610 | ehci->periodic[frame] = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); |
1474 | } | 1611 | } |
1475 | 1612 | ||
1476 | /* fit urb's itds into the selected schedule slot; activate as needed */ | 1613 | /* fit urb's itds into the selected schedule slot; activate as needed */ |
@@ -1515,14 +1652,14 @@ itd_link_urb ( | |||
1515 | list_move_tail (&itd->itd_list, &stream->td_list); | 1652 | list_move_tail (&itd->itd_list, &stream->td_list); |
1516 | itd->stream = iso_stream_get (stream); | 1653 | itd->stream = iso_stream_get (stream); |
1517 | itd->urb = usb_get_urb (urb); | 1654 | itd->urb = usb_get_urb (urb); |
1518 | itd_init (stream, itd); | 1655 | itd_init (ehci, stream, itd); |
1519 | } | 1656 | } |
1520 | 1657 | ||
1521 | uframe = next_uframe & 0x07; | 1658 | uframe = next_uframe & 0x07; |
1522 | frame = next_uframe >> 3; | 1659 | frame = next_uframe >> 3; |
1523 | 1660 | ||
1524 | itd->usecs [uframe] = stream->usecs; | 1661 | itd->usecs [uframe] = stream->usecs; |
1525 | itd_patch (itd, iso_sched, packet, uframe); | 1662 | itd_patch(ehci, itd, iso_sched, packet, uframe); |
1526 | 1663 | ||
1527 | next_uframe += stream->interval; | 1664 | next_uframe += stream->interval; |
1528 | stream->depth += stream->interval; | 1665 | stream->depth += stream->interval; |
@@ -1570,7 +1707,7 @@ itd_complete ( | |||
1570 | urb_index = itd->index[uframe]; | 1707 | urb_index = itd->index[uframe]; |
1571 | desc = &urb->iso_frame_desc [urb_index]; | 1708 | desc = &urb->iso_frame_desc [urb_index]; |
1572 | 1709 | ||
1573 | t = le32_to_cpup (&itd->hw_transaction [uframe]); | 1710 | t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]); |
1574 | itd->hw_transaction [uframe] = 0; | 1711 | itd->hw_transaction [uframe] = 0; |
1575 | stream->depth -= stream->interval; | 1712 | stream->depth -= stream->interval; |
1576 | 1713 | ||
@@ -1700,7 +1837,8 @@ done: | |||
1700 | */ | 1837 | */ |
1701 | 1838 | ||
1702 | static inline void | 1839 | static inline void |
1703 | sitd_sched_init ( | 1840 | sitd_sched_init( |
1841 | struct ehci_hcd *ehci, | ||
1704 | struct ehci_iso_sched *iso_sched, | 1842 | struct ehci_iso_sched *iso_sched, |
1705 | struct ehci_iso_stream *stream, | 1843 | struct ehci_iso_stream *stream, |
1706 | struct urb *urb | 1844 | struct urb *urb |
@@ -1729,7 +1867,7 @@ sitd_sched_init ( | |||
1729 | && !(urb->transfer_flags & URB_NO_INTERRUPT)) | 1867 | && !(urb->transfer_flags & URB_NO_INTERRUPT)) |
1730 | trans |= SITD_IOC; | 1868 | trans |= SITD_IOC; |
1731 | trans |= length << 16; | 1869 | trans |= length << 16; |
1732 | packet->transaction = cpu_to_le32 (trans); | 1870 | packet->transaction = cpu_to_hc32(ehci, trans); |
1733 | 1871 | ||
1734 | /* might need to cross a buffer page within a td */ | 1872 | /* might need to cross a buffer page within a td */ |
1735 | packet->bufp = buf; | 1873 | packet->bufp = buf; |
@@ -1765,7 +1903,7 @@ sitd_urb_transaction ( | |||
1765 | if (iso_sched == NULL) | 1903 | if (iso_sched == NULL) |
1766 | return -ENOMEM; | 1904 | return -ENOMEM; |
1767 | 1905 | ||
1768 | sitd_sched_init (iso_sched, stream, urb); | 1906 | sitd_sched_init(ehci, iso_sched, stream, urb); |
1769 | 1907 | ||
1770 | /* allocate/init sITDs */ | 1908 | /* allocate/init sITDs */ |
1771 | spin_lock_irqsave (&ehci->lock, flags); | 1909 | spin_lock_irqsave (&ehci->lock, flags); |
@@ -1817,7 +1955,8 @@ sitd_urb_transaction ( | |||
1817 | /*-------------------------------------------------------------------------*/ | 1955 | /*-------------------------------------------------------------------------*/ |
1818 | 1956 | ||
1819 | static inline void | 1957 | static inline void |
1820 | sitd_patch ( | 1958 | sitd_patch( |
1959 | struct ehci_hcd *ehci, | ||
1821 | struct ehci_iso_stream *stream, | 1960 | struct ehci_iso_stream *stream, |
1822 | struct ehci_sitd *sitd, | 1961 | struct ehci_sitd *sitd, |
1823 | struct ehci_iso_sched *iso_sched, | 1962 | struct ehci_iso_sched *iso_sched, |
@@ -1827,20 +1966,20 @@ sitd_patch ( | |||
1827 | struct ehci_iso_packet *uf = &iso_sched->packet [index]; | 1966 | struct ehci_iso_packet *uf = &iso_sched->packet [index]; |
1828 | u64 bufp = uf->bufp; | 1967 | u64 bufp = uf->bufp; |
1829 | 1968 | ||
1830 | sitd->hw_next = EHCI_LIST_END; | 1969 | sitd->hw_next = EHCI_LIST_END(ehci); |
1831 | sitd->hw_fullspeed_ep = stream->address; | 1970 | sitd->hw_fullspeed_ep = stream->address; |
1832 | sitd->hw_uframe = stream->splits; | 1971 | sitd->hw_uframe = stream->splits; |
1833 | sitd->hw_results = uf->transaction; | 1972 | sitd->hw_results = uf->transaction; |
1834 | sitd->hw_backpointer = EHCI_LIST_END; | 1973 | sitd->hw_backpointer = EHCI_LIST_END(ehci); |
1835 | 1974 | ||
1836 | bufp = uf->bufp; | 1975 | bufp = uf->bufp; |
1837 | sitd->hw_buf [0] = cpu_to_le32 (bufp); | 1976 | sitd->hw_buf[0] = cpu_to_hc32(ehci, bufp); |
1838 | sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32); | 1977 | sitd->hw_buf_hi[0] = cpu_to_hc32(ehci, bufp >> 32); |
1839 | 1978 | ||
1840 | sitd->hw_buf [1] = cpu_to_le32 (uf->buf1); | 1979 | sitd->hw_buf[1] = cpu_to_hc32(ehci, uf->buf1); |
1841 | if (uf->cross) | 1980 | if (uf->cross) |
1842 | bufp += 4096; | 1981 | bufp += 4096; |
1843 | sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32); | 1982 | sitd->hw_buf_hi[1] = cpu_to_hc32(ehci, bufp >> 32); |
1844 | sitd->index = index; | 1983 | sitd->index = index; |
1845 | } | 1984 | } |
1846 | 1985 | ||
@@ -1853,7 +1992,7 @@ sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) | |||
1853 | ehci->pshadow [frame].sitd = sitd; | 1992 | ehci->pshadow [frame].sitd = sitd; |
1854 | sitd->frame = frame; | 1993 | sitd->frame = frame; |
1855 | wmb (); | 1994 | wmb (); |
1856 | ehci->periodic [frame] = cpu_to_le32 (sitd->sitd_dma) | Q_TYPE_SITD; | 1995 | ehci->periodic[frame] = cpu_to_hc32(ehci, sitd->sitd_dma | Q_TYPE_SITD); |
1857 | } | 1996 | } |
1858 | 1997 | ||
1859 | /* fit urb's sitds into the selected schedule slot; activate as needed */ | 1998 | /* fit urb's sitds into the selected schedule slot; activate as needed */ |
@@ -1881,7 +2020,7 @@ sitd_link_urb ( | |||
1881 | urb->dev->devpath, stream->bEndpointAddress & 0x0f, | 2020 | urb->dev->devpath, stream->bEndpointAddress & 0x0f, |
1882 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", | 2021 | (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", |
1883 | (next_uframe >> 3) % ehci->periodic_size, | 2022 | (next_uframe >> 3) % ehci->periodic_size, |
1884 | stream->interval, le32_to_cpu (stream->splits)); | 2023 | stream->interval, hc32_to_cpu(ehci, stream->splits)); |
1885 | stream->start = jiffies; | 2024 | stream->start = jiffies; |
1886 | } | 2025 | } |
1887 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; | 2026 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; |
@@ -1902,7 +2041,7 @@ sitd_link_urb ( | |||
1902 | sitd->stream = iso_stream_get (stream); | 2041 | sitd->stream = iso_stream_get (stream); |
1903 | sitd->urb = usb_get_urb (urb); | 2042 | sitd->urb = usb_get_urb (urb); |
1904 | 2043 | ||
1905 | sitd_patch (stream, sitd, sched, packet); | 2044 | sitd_patch(ehci, stream, sitd, sched, packet); |
1906 | sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, | 2045 | sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, |
1907 | sitd); | 2046 | sitd); |
1908 | 2047 | ||
@@ -1940,7 +2079,7 @@ sitd_complete ( | |||
1940 | 2079 | ||
1941 | urb_index = sitd->index; | 2080 | urb_index = sitd->index; |
1942 | desc = &urb->iso_frame_desc [urb_index]; | 2081 | desc = &urb->iso_frame_desc [urb_index]; |
1943 | t = le32_to_cpup (&sitd->hw_results); | 2082 | t = hc32_to_cpup(ehci, &sitd->hw_results); |
1944 | 2083 | ||
1945 | /* report transfer status */ | 2084 | /* report transfer status */ |
1946 | if (t & SITD_ERRS) { | 2085 | if (t & SITD_ERRS) { |
@@ -2095,7 +2234,7 @@ scan_periodic (struct ehci_hcd *ehci) | |||
2095 | 2234 | ||
2096 | for (;;) { | 2235 | for (;;) { |
2097 | union ehci_shadow q, *q_p; | 2236 | union ehci_shadow q, *q_p; |
2098 | __le32 type, *hw_p; | 2237 | __hc32 type, *hw_p; |
2099 | unsigned uframes; | 2238 | unsigned uframes; |
2100 | 2239 | ||
2101 | /* don't scan past the live uframe */ | 2240 | /* don't scan past the live uframe */ |
@@ -2113,7 +2252,7 @@ restart: | |||
2113 | q_p = &ehci->pshadow [frame]; | 2252 | q_p = &ehci->pshadow [frame]; |
2114 | hw_p = &ehci->periodic [frame]; | 2253 | hw_p = &ehci->periodic [frame]; |
2115 | q.ptr = q_p->ptr; | 2254 | q.ptr = q_p->ptr; |
2116 | type = Q_NEXT_TYPE (*hw_p); | 2255 | type = Q_NEXT_TYPE(ehci, *hw_p); |
2117 | modified = 0; | 2256 | modified = 0; |
2118 | 2257 | ||
2119 | while (q.ptr != NULL) { | 2258 | while (q.ptr != NULL) { |
@@ -2122,11 +2261,11 @@ restart: | |||
2122 | int live; | 2261 | int live; |
2123 | 2262 | ||
2124 | live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state); | 2263 | live = HC_IS_RUNNING (ehci_to_hcd(ehci)->state); |
2125 | switch (type) { | 2264 | switch (hc32_to_cpu(ehci, type)) { |
2126 | case Q_TYPE_QH: | 2265 | case Q_TYPE_QH: |
2127 | /* handle any completions */ | 2266 | /* handle any completions */ |
2128 | temp.qh = qh_get (q.qh); | 2267 | temp.qh = qh_get (q.qh); |
2129 | type = Q_NEXT_TYPE (q.qh->hw_next); | 2268 | type = Q_NEXT_TYPE(ehci, q.qh->hw_next); |
2130 | q = q.qh->qh_next; | 2269 | q = q.qh->qh_next; |
2131 | modified = qh_completions (ehci, temp.qh); | 2270 | modified = qh_completions (ehci, temp.qh); |
2132 | if (unlikely (list_empty (&temp.qh->qtd_list))) | 2271 | if (unlikely (list_empty (&temp.qh->qtd_list))) |
@@ -2137,10 +2276,10 @@ restart: | |||
2137 | /* for "save place" FSTNs, look at QH entries | 2276 | /* for "save place" FSTNs, look at QH entries |
2138 | * in the previous frame for completions. | 2277 | * in the previous frame for completions. |
2139 | */ | 2278 | */ |
2140 | if (q.fstn->hw_prev != EHCI_LIST_END) { | 2279 | if (q.fstn->hw_prev != EHCI_LIST_END(ehci)) { |
2141 | dbg ("ignoring completions from FSTNs"); | 2280 | dbg ("ignoring completions from FSTNs"); |
2142 | } | 2281 | } |
2143 | type = Q_NEXT_TYPE (q.fstn->hw_next); | 2282 | type = Q_NEXT_TYPE(ehci, q.fstn->hw_next); |
2144 | q = q.fstn->fstn_next; | 2283 | q = q.fstn->fstn_next; |
2145 | break; | 2284 | break; |
2146 | case Q_TYPE_ITD: | 2285 | case Q_TYPE_ITD: |
@@ -2148,11 +2287,12 @@ restart: | |||
2148 | rmb (); | 2287 | rmb (); |
2149 | for (uf = live ? uframes : 8; uf < 8; uf++) { | 2288 | for (uf = live ? uframes : 8; uf < 8; uf++) { |
2150 | if (0 == (q.itd->hw_transaction [uf] | 2289 | if (0 == (q.itd->hw_transaction [uf] |
2151 | & ITD_ACTIVE)) | 2290 | & ITD_ACTIVE(ehci))) |
2152 | continue; | 2291 | continue; |
2153 | q_p = &q.itd->itd_next; | 2292 | q_p = &q.itd->itd_next; |
2154 | hw_p = &q.itd->hw_next; | 2293 | hw_p = &q.itd->hw_next; |
2155 | type = Q_NEXT_TYPE (q.itd->hw_next); | 2294 | type = Q_NEXT_TYPE(ehci, |
2295 | q.itd->hw_next); | ||
2156 | q = *q_p; | 2296 | q = *q_p; |
2157 | break; | 2297 | break; |
2158 | } | 2298 | } |
@@ -2164,23 +2304,24 @@ restart: | |||
2164 | */ | 2304 | */ |
2165 | *q_p = q.itd->itd_next; | 2305 | *q_p = q.itd->itd_next; |
2166 | *hw_p = q.itd->hw_next; | 2306 | *hw_p = q.itd->hw_next; |
2167 | type = Q_NEXT_TYPE (q.itd->hw_next); | 2307 | type = Q_NEXT_TYPE(ehci, q.itd->hw_next); |
2168 | wmb(); | 2308 | wmb(); |
2169 | modified = itd_complete (ehci, q.itd); | 2309 | modified = itd_complete (ehci, q.itd); |
2170 | q = *q_p; | 2310 | q = *q_p; |
2171 | break; | 2311 | break; |
2172 | case Q_TYPE_SITD: | 2312 | case Q_TYPE_SITD: |
2173 | if ((q.sitd->hw_results & SITD_ACTIVE) | 2313 | if ((q.sitd->hw_results & SITD_ACTIVE(ehci)) |
2174 | && live) { | 2314 | && live) { |
2175 | q_p = &q.sitd->sitd_next; | 2315 | q_p = &q.sitd->sitd_next; |
2176 | hw_p = &q.sitd->hw_next; | 2316 | hw_p = &q.sitd->hw_next; |
2177 | type = Q_NEXT_TYPE (q.sitd->hw_next); | 2317 | type = Q_NEXT_TYPE(ehci, |
2318 | q.sitd->hw_next); | ||
2178 | q = *q_p; | 2319 | q = *q_p; |
2179 | break; | 2320 | break; |
2180 | } | 2321 | } |
2181 | *q_p = q.sitd->sitd_next; | 2322 | *q_p = q.sitd->sitd_next; |
2182 | *hw_p = q.sitd->hw_next; | 2323 | *hw_p = q.sitd->hw_next; |
2183 | type = Q_NEXT_TYPE (q.sitd->hw_next); | 2324 | type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); |
2184 | wmb(); | 2325 | wmb(); |
2185 | modified = sitd_complete (ehci, q.sitd); | 2326 | modified = sitd_complete (ehci, q.sitd); |
2186 | q = *q_p; | 2327 | q = *q_p; |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 46fa57a520d0..2c68a04230c1 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -21,6 +21,22 @@ | |||
21 | 21 | ||
22 | /* definitions used for the EHCI driver */ | 22 | /* definitions used for the EHCI driver */ |
23 | 23 | ||
24 | /* | ||
25 | * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to | ||
26 | * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on | ||
27 | * the host controller implementation. | ||
28 | * | ||
29 | * To facilitate the strongest possible byte-order checking from "sparse" | ||
30 | * and so on, we use __leXX unless that's not practical. | ||
31 | */ | ||
32 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC | ||
33 | typedef __u32 __bitwise __hc32; | ||
34 | typedef __u16 __bitwise __hc16; | ||
35 | #else | ||
36 | #define __hc32 __le32 | ||
37 | #define __hc16 __le16 | ||
38 | #endif | ||
39 | |||
24 | /* statistics can be kept for for tuning/monitoring */ | 40 | /* statistics can be kept for for tuning/monitoring */ |
25 | struct ehci_stats { | 41 | struct ehci_stats { |
26 | /* irq usage */ | 42 | /* irq usage */ |
@@ -55,6 +71,12 @@ struct ehci_hcd { /* one per controller */ | |||
55 | __u32 hcs_params; /* cached register copy */ | 71 | __u32 hcs_params; /* cached register copy */ |
56 | spinlock_t lock; | 72 | spinlock_t lock; |
57 | 73 | ||
74 | #ifdef CONFIG_CPU_FREQ | ||
75 | struct notifier_block cpufreq_transition; | ||
76 | int cpufreq_changing; | ||
77 | struct list_head split_intr_qhs; | ||
78 | #endif | ||
79 | |||
58 | /* async schedule support */ | 80 | /* async schedule support */ |
59 | struct ehci_qh *async; | 81 | struct ehci_qh *async; |
60 | struct ehci_qh *reclaim; | 82 | struct ehci_qh *reclaim; |
@@ -64,7 +86,7 @@ struct ehci_hcd { /* one per controller */ | |||
64 | /* periodic schedule support */ | 86 | /* periodic schedule support */ |
65 | #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ | 87 | #define DEFAULT_I_TDPS 1024 /* some HCs can do less */ |
66 | unsigned periodic_size; | 88 | unsigned periodic_size; |
67 | __le32 *periodic; /* hw periodic table */ | 89 | __hc32 *periodic; /* hw periodic table */ |
68 | dma_addr_t periodic_dma; | 90 | dma_addr_t periodic_dma; |
69 | unsigned i_thresh; /* uframes HC might cache */ | 91 | unsigned i_thresh; /* uframes HC might cache */ |
70 | 92 | ||
@@ -74,11 +96,14 @@ struct ehci_hcd { /* one per controller */ | |||
74 | 96 | ||
75 | /* per root hub port */ | 97 | /* per root hub port */ |
76 | unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; | 98 | unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; |
99 | |||
77 | /* bit vectors (one bit per port) */ | 100 | /* bit vectors (one bit per port) */ |
78 | unsigned long bus_suspended; /* which ports were | 101 | unsigned long bus_suspended; /* which ports were |
79 | already suspended at the start of a bus suspend */ | 102 | already suspended at the start of a bus suspend */ |
80 | unsigned long companion_ports; /* which ports are | 103 | unsigned long companion_ports; /* which ports are |
81 | dedicated to the companion controller */ | 104 | dedicated to the companion controller */ |
105 | unsigned long owned_ports; /* which ports are | ||
106 | owned by the companion during a bus suspend */ | ||
82 | 107 | ||
83 | /* per-HC memory pools (could be per-bus, but ...) */ | 108 | /* per-HC memory pools (could be per-bus, but ...) */ |
84 | struct dma_pool *qh_pool; /* qh per active urb */ | 109 | struct dma_pool *qh_pool; /* qh per active urb */ |
@@ -97,6 +122,7 @@ struct ehci_hcd { /* one per controller */ | |||
97 | unsigned no_selective_suspend:1; | 122 | unsigned no_selective_suspend:1; |
98 | unsigned has_fsl_port_bug:1; /* FreeScale */ | 123 | unsigned has_fsl_port_bug:1; /* FreeScale */ |
99 | unsigned big_endian_mmio:1; | 124 | unsigned big_endian_mmio:1; |
125 | unsigned big_endian_desc:1; | ||
100 | 126 | ||
101 | u8 sbrn; /* packed release number */ | 127 | u8 sbrn; /* packed release number */ |
102 | 128 | ||
@@ -276,6 +302,12 @@ struct ehci_regs { | |||
276 | #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) | 302 | #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC) |
277 | } __attribute__ ((packed)); | 303 | } __attribute__ ((packed)); |
278 | 304 | ||
305 | #define USBMODE 0x68 /* USB Device mode */ | ||
306 | #define USBMODE_SDIS (1<<3) /* Stream disable */ | ||
307 | #define USBMODE_BE (1<<2) /* BE/LE endianness select */ | ||
308 | #define USBMODE_CM_HC (3<<0) /* host controller mode */ | ||
309 | #define USBMODE_CM_IDLE (0<<0) /* idle state */ | ||
310 | |||
279 | /* Appendix C, Debug port ... intended for use with special "debug devices" | 311 | /* Appendix C, Debug port ... intended for use with special "debug devices" |
280 | * that can help if there's no serial console. (nonstandard enumeration.) | 312 | * that can help if there's no serial console. (nonstandard enumeration.) |
281 | */ | 313 | */ |
@@ -303,7 +335,7 @@ struct ehci_dbg_port { | |||
303 | 335 | ||
304 | /*-------------------------------------------------------------------------*/ | 336 | /*-------------------------------------------------------------------------*/ |
305 | 337 | ||
306 | #define QTD_NEXT(dma) cpu_to_le32((u32)dma) | 338 | #define QTD_NEXT(ehci, dma) cpu_to_hc32(ehci, (u32)dma) |
307 | 339 | ||
308 | /* | 340 | /* |
309 | * EHCI Specification 0.95 Section 3.5 | 341 | * EHCI Specification 0.95 Section 3.5 |
@@ -315,9 +347,9 @@ struct ehci_dbg_port { | |||
315 | */ | 347 | */ |
316 | struct ehci_qtd { | 348 | struct ehci_qtd { |
317 | /* first part defined by EHCI spec */ | 349 | /* first part defined by EHCI spec */ |
318 | __le32 hw_next; /* see EHCI 3.5.1 */ | 350 | __hc32 hw_next; /* see EHCI 3.5.1 */ |
319 | __le32 hw_alt_next; /* see EHCI 3.5.2 */ | 351 | __hc32 hw_alt_next; /* see EHCI 3.5.2 */ |
320 | __le32 hw_token; /* see EHCI 3.5.3 */ | 352 | __hc32 hw_token; /* see EHCI 3.5.3 */ |
321 | #define QTD_TOGGLE (1 << 31) /* data toggle */ | 353 | #define QTD_TOGGLE (1 << 31) /* data toggle */ |
322 | #define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) | 354 | #define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) |
323 | #define QTD_IOC (1 << 15) /* interrupt on complete */ | 355 | #define QTD_IOC (1 << 15) /* interrupt on complete */ |
@@ -331,8 +363,13 @@ struct ehci_qtd { | |||
331 | #define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ | 363 | #define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ |
332 | #define QTD_STS_STS (1 << 1) /* split transaction state */ | 364 | #define QTD_STS_STS (1 << 1) /* split transaction state */ |
333 | #define QTD_STS_PING (1 << 0) /* issue PING? */ | 365 | #define QTD_STS_PING (1 << 0) /* issue PING? */ |
334 | __le32 hw_buf [5]; /* see EHCI 3.5.4 */ | 366 | |
335 | __le32 hw_buf_hi [5]; /* Appendix B */ | 367 | #define ACTIVE_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_ACTIVE) |
368 | #define HALT_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_HALT) | ||
369 | #define STATUS_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_STS) | ||
370 | |||
371 | __hc32 hw_buf [5]; /* see EHCI 3.5.4 */ | ||
372 | __hc32 hw_buf_hi [5]; /* Appendix B */ | ||
336 | 373 | ||
337 | /* the rest is HCD-private */ | 374 | /* the rest is HCD-private */ |
338 | dma_addr_t qtd_dma; /* qtd address */ | 375 | dma_addr_t qtd_dma; /* qtd address */ |
@@ -342,26 +379,33 @@ struct ehci_qtd { | |||
342 | } __attribute__ ((aligned (32))); | 379 | } __attribute__ ((aligned (32))); |
343 | 380 | ||
344 | /* mask NakCnt+T in qh->hw_alt_next */ | 381 | /* mask NakCnt+T in qh->hw_alt_next */ |
345 | #define QTD_MASK __constant_cpu_to_le32 (~0x1f) | 382 | #define QTD_MASK(ehci) cpu_to_hc32 (ehci, ~0x1f) |
346 | 383 | ||
347 | #define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1) | 384 | #define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1) |
348 | 385 | ||
349 | /*-------------------------------------------------------------------------*/ | 386 | /*-------------------------------------------------------------------------*/ |
350 | 387 | ||
351 | /* type tag from {qh,itd,sitd,fstn}->hw_next */ | 388 | /* type tag from {qh,itd,sitd,fstn}->hw_next */ |
352 | #define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1)) | 389 | #define Q_NEXT_TYPE(ehci,dma) ((dma) & cpu_to_hc32(ehci, 3 << 1)) |
353 | 390 | ||
391 | /* | ||
392 | * Now the following defines are not converted using the | ||
393 | * __constant_cpu_to_le32() macro anymore, since we have to support | ||
394 | * "dynamic" switching between be and le support, so that the driver | ||
395 | * can be used on one system with SoC EHCI controller using big-endian | ||
396 | * descriptors as well as a normal little-endian PCI EHCI controller. | ||
397 | */ | ||
354 | /* values for that type tag */ | 398 | /* values for that type tag */ |
355 | #define Q_TYPE_ITD __constant_cpu_to_le32 (0 << 1) | 399 | #define Q_TYPE_ITD (0 << 1) |
356 | #define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) | 400 | #define Q_TYPE_QH (1 << 1) |
357 | #define Q_TYPE_SITD __constant_cpu_to_le32 (2 << 1) | 401 | #define Q_TYPE_SITD (2 << 1) |
358 | #define Q_TYPE_FSTN __constant_cpu_to_le32 (3 << 1) | 402 | #define Q_TYPE_FSTN (3 << 1) |
359 | 403 | ||
360 | /* next async queue entry, or pointer to interrupt/periodic QH */ | 404 | /* next async queue entry, or pointer to interrupt/periodic QH */ |
361 | #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) | 405 | #define QH_NEXT(ehci,dma) (cpu_to_hc32(ehci, (((u32)dma)&~0x01f)|Q_TYPE_QH)) |
362 | 406 | ||
363 | /* for periodic/async schedules and qtd lists, mark end of list */ | 407 | /* for periodic/async schedules and qtd lists, mark end of list */ |
364 | #define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */ | 408 | #define EHCI_LIST_END(ehci) cpu_to_hc32(ehci, 1) /* "null pointer" to hw */ |
365 | 409 | ||
366 | /* | 410 | /* |
367 | * Entries in periodic shadow table are pointers to one of four kinds | 411 | * Entries in periodic shadow table are pointers to one of four kinds |
@@ -376,7 +420,7 @@ union ehci_shadow { | |||
376 | struct ehci_itd *itd; /* Q_TYPE_ITD */ | 420 | struct ehci_itd *itd; /* Q_TYPE_ITD */ |
377 | struct ehci_sitd *sitd; /* Q_TYPE_SITD */ | 421 | struct ehci_sitd *sitd; /* Q_TYPE_SITD */ |
378 | struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ | 422 | struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ |
379 | __le32 *hw_next; /* (all types) */ | 423 | __hc32 *hw_next; /* (all types) */ |
380 | void *ptr; | 424 | void *ptr; |
381 | }; | 425 | }; |
382 | 426 | ||
@@ -392,23 +436,27 @@ union ehci_shadow { | |||
392 | 436 | ||
393 | struct ehci_qh { | 437 | struct ehci_qh { |
394 | /* first part defined by EHCI spec */ | 438 | /* first part defined by EHCI spec */ |
395 | __le32 hw_next; /* see EHCI 3.6.1 */ | 439 | __hc32 hw_next; /* see EHCI 3.6.1 */ |
396 | __le32 hw_info1; /* see EHCI 3.6.2 */ | 440 | __hc32 hw_info1; /* see EHCI 3.6.2 */ |
397 | #define QH_HEAD 0x00008000 | 441 | #define QH_HEAD 0x00008000 |
398 | __le32 hw_info2; /* see EHCI 3.6.2 */ | 442 | #define QH_INACTIVATE 0x00000080 |
443 | |||
444 | #define INACTIVATE_BIT(ehci) cpu_to_hc32(ehci, QH_INACTIVATE) | ||
445 | |||
446 | __hc32 hw_info2; /* see EHCI 3.6.2 */ | ||
399 | #define QH_SMASK 0x000000ff | 447 | #define QH_SMASK 0x000000ff |
400 | #define QH_CMASK 0x0000ff00 | 448 | #define QH_CMASK 0x0000ff00 |
401 | #define QH_HUBADDR 0x007f0000 | 449 | #define QH_HUBADDR 0x007f0000 |
402 | #define QH_HUBPORT 0x3f800000 | 450 | #define QH_HUBPORT 0x3f800000 |
403 | #define QH_MULT 0xc0000000 | 451 | #define QH_MULT 0xc0000000 |
404 | __le32 hw_current; /* qtd list - see EHCI 3.6.4 */ | 452 | __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */ |
405 | 453 | ||
406 | /* qtd overlay (hardware parts of a struct ehci_qtd) */ | 454 | /* qtd overlay (hardware parts of a struct ehci_qtd) */ |
407 | __le32 hw_qtd_next; | 455 | __hc32 hw_qtd_next; |
408 | __le32 hw_alt_next; | 456 | __hc32 hw_alt_next; |
409 | __le32 hw_token; | 457 | __hc32 hw_token; |
410 | __le32 hw_buf [5]; | 458 | __hc32 hw_buf [5]; |
411 | __le32 hw_buf_hi [5]; | 459 | __hc32 hw_buf_hi [5]; |
412 | 460 | ||
413 | /* the rest is HCD-private */ | 461 | /* the rest is HCD-private */ |
414 | dma_addr_t qh_dma; /* address of qh */ | 462 | dma_addr_t qh_dma; /* address of qh */ |
@@ -418,7 +466,14 @@ struct ehci_qh { | |||
418 | struct ehci_qh *reclaim; /* next to reclaim */ | 466 | struct ehci_qh *reclaim; /* next to reclaim */ |
419 | 467 | ||
420 | struct ehci_hcd *ehci; | 468 | struct ehci_hcd *ehci; |
421 | struct kref kref; | 469 | |
470 | /* | ||
471 | * Do NOT use atomic operations for QH refcounting. On some CPUs | ||
472 | * (PPC7448 for example), atomic operations cannot be performed on | ||
473 | * memory that is cache-inhibited (i.e. being used for DMA). | ||
474 | * Spinlocks are used to protect all QH fields. | ||
475 | */ | ||
476 | u32 refcount; | ||
422 | unsigned stamp; | 477 | unsigned stamp; |
423 | 478 | ||
424 | u8 qh_state; | 479 | u8 qh_state; |
@@ -437,6 +492,10 @@ struct ehci_qh { | |||
437 | unsigned short start; /* where polling starts */ | 492 | unsigned short start; /* where polling starts */ |
438 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ | 493 | #define NO_FRAME ((unsigned short)~0) /* pick new start */ |
439 | struct usb_device *dev; /* access to TT */ | 494 | struct usb_device *dev; /* access to TT */ |
495 | #ifdef CONFIG_CPU_FREQ | ||
496 | struct list_head split_intr_qhs; /* list of split qhs */ | ||
497 | __le32 was_active; /* active bit before "i" set */ | ||
498 | #endif | ||
440 | } __attribute__ ((aligned (32))); | 499 | } __attribute__ ((aligned (32))); |
441 | 500 | ||
442 | /*-------------------------------------------------------------------------*/ | 501 | /*-------------------------------------------------------------------------*/ |
@@ -445,7 +504,7 @@ struct ehci_qh { | |||
445 | struct ehci_iso_packet { | 504 | struct ehci_iso_packet { |
446 | /* These will be copied to iTD when scheduling */ | 505 | /* These will be copied to iTD when scheduling */ |
447 | u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ | 506 | u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ |
448 | __le32 transaction; /* itd->hw_transaction[i] |= */ | 507 | __hc32 transaction; /* itd->hw_transaction[i] |= */ |
449 | u8 cross; /* buf crosses pages */ | 508 | u8 cross; /* buf crosses pages */ |
450 | /* for full speed OUT splits */ | 509 | /* for full speed OUT splits */ |
451 | u32 buf1; | 510 | u32 buf1; |
@@ -467,8 +526,8 @@ struct ehci_iso_sched { | |||
467 | */ | 526 | */ |
468 | struct ehci_iso_stream { | 527 | struct ehci_iso_stream { |
469 | /* first two fields match QH, but info1 == 0 */ | 528 | /* first two fields match QH, but info1 == 0 */ |
470 | __le32 hw_next; | 529 | __hc32 hw_next; |
471 | __le32 hw_info1; | 530 | __hc32 hw_info1; |
472 | 531 | ||
473 | u32 refcount; | 532 | u32 refcount; |
474 | u8 bEndpointAddress; | 533 | u8 bEndpointAddress; |
@@ -483,7 +542,7 @@ struct ehci_iso_stream { | |||
483 | unsigned long start; /* jiffies */ | 542 | unsigned long start; /* jiffies */ |
484 | unsigned long rescheduled; | 543 | unsigned long rescheduled; |
485 | int next_uframe; | 544 | int next_uframe; |
486 | __le32 splits; | 545 | __hc32 splits; |
487 | 546 | ||
488 | /* the rest is derived from the endpoint descriptor, | 547 | /* the rest is derived from the endpoint descriptor, |
489 | * trusting urb->interval == f(epdesc->bInterval) and | 548 | * trusting urb->interval == f(epdesc->bInterval) and |
@@ -497,12 +556,12 @@ struct ehci_iso_stream { | |||
497 | unsigned bandwidth; | 556 | unsigned bandwidth; |
498 | 557 | ||
499 | /* This is used to initialize iTD's hw_bufp fields */ | 558 | /* This is used to initialize iTD's hw_bufp fields */ |
500 | __le32 buf0; | 559 | __hc32 buf0; |
501 | __le32 buf1; | 560 | __hc32 buf1; |
502 | __le32 buf2; | 561 | __hc32 buf2; |
503 | 562 | ||
504 | /* this is used to initialize sITD's tt info */ | 563 | /* this is used to initialize sITD's tt info */ |
505 | __le32 address; | 564 | __hc32 address; |
506 | }; | 565 | }; |
507 | 566 | ||
508 | /*-------------------------------------------------------------------------*/ | 567 | /*-------------------------------------------------------------------------*/ |
@@ -515,8 +574,8 @@ struct ehci_iso_stream { | |||
515 | */ | 574 | */ |
516 | struct ehci_itd { | 575 | struct ehci_itd { |
517 | /* first part defined by EHCI spec */ | 576 | /* first part defined by EHCI spec */ |
518 | __le32 hw_next; /* see EHCI 3.3.1 */ | 577 | __hc32 hw_next; /* see EHCI 3.3.1 */ |
519 | __le32 hw_transaction [8]; /* see EHCI 3.3.2 */ | 578 | __hc32 hw_transaction [8]; /* see EHCI 3.3.2 */ |
520 | #define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ | 579 | #define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ |
521 | #define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ | 580 | #define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ |
522 | #define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ | 581 | #define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ |
@@ -524,10 +583,10 @@ struct ehci_itd { | |||
524 | #define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) | 583 | #define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) |
525 | #define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */ | 584 | #define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */ |
526 | 585 | ||
527 | #define ITD_ACTIVE __constant_cpu_to_le32(EHCI_ISOC_ACTIVE) | 586 | #define ITD_ACTIVE(ehci) cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE) |
528 | 587 | ||
529 | __le32 hw_bufp [7]; /* see EHCI 3.3.3 */ | 588 | __hc32 hw_bufp [7]; /* see EHCI 3.3.3 */ |
530 | __le32 hw_bufp_hi [7]; /* Appendix B */ | 589 | __hc32 hw_bufp_hi [7]; /* Appendix B */ |
531 | 590 | ||
532 | /* the rest is HCD-private */ | 591 | /* the rest is HCD-private */ |
533 | dma_addr_t itd_dma; /* for this itd */ | 592 | dma_addr_t itd_dma; /* for this itd */ |
@@ -554,11 +613,11 @@ struct ehci_itd { | |||
554 | */ | 613 | */ |
555 | struct ehci_sitd { | 614 | struct ehci_sitd { |
556 | /* first part defined by EHCI spec */ | 615 | /* first part defined by EHCI spec */ |
557 | __le32 hw_next; | 616 | __hc32 hw_next; |
558 | /* uses bit field macros above - see EHCI 0.95 Table 3-8 */ | 617 | /* uses bit field macros above - see EHCI 0.95 Table 3-8 */ |
559 | __le32 hw_fullspeed_ep; /* EHCI table 3-9 */ | 618 | __hc32 hw_fullspeed_ep; /* EHCI table 3-9 */ |
560 | __le32 hw_uframe; /* EHCI table 3-10 */ | 619 | __hc32 hw_uframe; /* EHCI table 3-10 */ |
561 | __le32 hw_results; /* EHCI table 3-11 */ | 620 | __hc32 hw_results; /* EHCI table 3-11 */ |
562 | #define SITD_IOC (1 << 31) /* interrupt on completion */ | 621 | #define SITD_IOC (1 << 31) /* interrupt on completion */ |
563 | #define SITD_PAGE (1 << 30) /* buffer 0/1 */ | 622 | #define SITD_PAGE (1 << 30) /* buffer 0/1 */ |
564 | #define SITD_LENGTH(x) (0x3ff & ((x)>>16)) | 623 | #define SITD_LENGTH(x) (0x3ff & ((x)>>16)) |
@@ -570,11 +629,11 @@ struct ehci_sitd { | |||
570 | #define SITD_STS_MMF (1 << 2) /* incomplete split transaction */ | 629 | #define SITD_STS_MMF (1 << 2) /* incomplete split transaction */ |
571 | #define SITD_STS_STS (1 << 1) /* split transaction state */ | 630 | #define SITD_STS_STS (1 << 1) /* split transaction state */ |
572 | 631 | ||
573 | #define SITD_ACTIVE __constant_cpu_to_le32(SITD_STS_ACTIVE) | 632 | #define SITD_ACTIVE(ehci) cpu_to_hc32(ehci, SITD_STS_ACTIVE) |
574 | 633 | ||
575 | __le32 hw_buf [2]; /* EHCI table 3-12 */ | 634 | __hc32 hw_buf [2]; /* EHCI table 3-12 */ |
576 | __le32 hw_backpointer; /* EHCI table 3-13 */ | 635 | __hc32 hw_backpointer; /* EHCI table 3-13 */ |
577 | __le32 hw_buf_hi [2]; /* Appendix B */ | 636 | __hc32 hw_buf_hi [2]; /* Appendix B */ |
578 | 637 | ||
579 | /* the rest is HCD-private */ | 638 | /* the rest is HCD-private */ |
580 | dma_addr_t sitd_dma; | 639 | dma_addr_t sitd_dma; |
@@ -599,8 +658,8 @@ struct ehci_sitd { | |||
599 | * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. | 658 | * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. |
600 | */ | 659 | */ |
601 | struct ehci_fstn { | 660 | struct ehci_fstn { |
602 | __le32 hw_next; /* any periodic q entry */ | 661 | __hc32 hw_next; /* any periodic q entry */ |
603 | __le32 hw_prev; /* qh or EHCI_LIST_END */ | 662 | __hc32 hw_prev; /* qh or EHCI_LIST_END */ |
604 | 663 | ||
605 | /* the rest is HCD-private */ | 664 | /* the rest is HCD-private */ |
606 | dma_addr_t fstn_dma; | 665 | dma_addr_t fstn_dma; |
@@ -672,8 +731,21 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) | |||
672 | #define ehci_big_endian_mmio(e) 0 | 731 | #define ehci_big_endian_mmio(e) 0 |
673 | #endif | 732 | #endif |
674 | 733 | ||
675 | static inline unsigned int ehci_readl (const struct ehci_hcd *ehci, | 734 | /* |
676 | __u32 __iomem * regs) | 735 | * Big-endian read/write functions are arch-specific. |
736 | * Other arches can be added if/when they're needed. | ||
737 | * | ||
738 | * REVISIT: arch/powerpc now has readl/writel_be, so the | ||
739 | * definition below can die once the 4xx support is | ||
740 | * finally ported over. | ||
741 | */ | ||
742 | #if defined(CONFIG_PPC) | ||
743 | #define readl_be(addr) in_be32((__force unsigned *)addr) | ||
744 | #define writel_be(val, addr) out_be32((__force unsigned *)addr, val) | ||
745 | #endif | ||
746 | |||
747 | static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, | ||
748 | __u32 __iomem * regs) | ||
677 | { | 749 | { |
678 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO | 750 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO |
679 | return ehci_big_endian_mmio(ehci) ? | 751 | return ehci_big_endian_mmio(ehci) ? |
@@ -684,8 +756,8 @@ static inline unsigned int ehci_readl (const struct ehci_hcd *ehci, | |||
684 | #endif | 756 | #endif |
685 | } | 757 | } |
686 | 758 | ||
687 | static inline void ehci_writel (const struct ehci_hcd *ehci, | 759 | static inline void ehci_writel(const struct ehci_hcd *ehci, |
688 | const unsigned int val, __u32 __iomem *regs) | 760 | const unsigned int val, __u32 __iomem *regs) |
689 | { | 761 | { |
690 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO | 762 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO |
691 | ehci_big_endian_mmio(ehci) ? | 763 | ehci_big_endian_mmio(ehci) ? |
@@ -698,6 +770,62 @@ static inline void ehci_writel (const struct ehci_hcd *ehci, | |||
698 | 770 | ||
699 | /*-------------------------------------------------------------------------*/ | 771 | /*-------------------------------------------------------------------------*/ |
700 | 772 | ||
773 | /* | ||
774 | * The AMCC 440EPx not only implements its EHCI registers in big-endian | ||
775 | * format, but also its DMA data structures (descriptors). | ||
776 | * | ||
777 | * EHCI controllers accessed through PCI work normally (little-endian | ||
778 | * everywhere), so we won't bother supporting a BE-only mode for now. | ||
779 | */ | ||
780 | #ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC | ||
781 | #define ehci_big_endian_desc(e) ((e)->big_endian_desc) | ||
782 | |||
783 | /* cpu to ehci */ | ||
784 | static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) | ||
785 | { | ||
786 | return ehci_big_endian_desc(ehci) | ||
787 | ? (__force __hc32)cpu_to_be32(x) | ||
788 | : (__force __hc32)cpu_to_le32(x); | ||
789 | } | ||
790 | |||
791 | /* ehci to cpu */ | ||
792 | static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) | ||
793 | { | ||
794 | return ehci_big_endian_desc(ehci) | ||
795 | ? be32_to_cpu((__force __be32)x) | ||
796 | : le32_to_cpu((__force __le32)x); | ||
797 | } | ||
798 | |||
799 | static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) | ||
800 | { | ||
801 | return ehci_big_endian_desc(ehci) | ||
802 | ? be32_to_cpup((__force __be32 *)x) | ||
803 | : le32_to_cpup((__force __le32 *)x); | ||
804 | } | ||
805 | |||
806 | #else | ||
807 | |||
808 | /* cpu to ehci */ | ||
809 | static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) | ||
810 | { | ||
811 | return cpu_to_le32(x); | ||
812 | } | ||
813 | |||
814 | /* ehci to cpu */ | ||
815 | static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) | ||
816 | { | ||
817 | return le32_to_cpu(x); | ||
818 | } | ||
819 | |||
820 | static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) | ||
821 | { | ||
822 | return le32_to_cpup(x); | ||
823 | } | ||
824 | |||
825 | #endif | ||
826 | |||
827 | /*-------------------------------------------------------------------------*/ | ||
828 | |||
701 | #ifndef DEBUG | 829 | #ifndef DEBUG |
702 | #define STUB_DEBUG_FILES | 830 | #define STUB_DEBUG_FILES |
703 | #endif /* DEBUG */ | 831 | #endif /* DEBUG */ |
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 273d5ddb72be..6f9e43e9a6ca 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c | |||
@@ -23,7 +23,7 @@ | |||
23 | /* debug| print the main components of an URB | 23 | /* debug| print the main components of an URB |
24 | * small: 0) header + data packets 1) just header | 24 | * small: 0) header + data packets 1) just header |
25 | */ | 25 | */ |
26 | static void __attribute__((unused)) | 26 | static void __maybe_unused |
27 | urb_print (struct urb * urb, char * str, int small) | 27 | urb_print (struct urb * urb, char * str, int small) |
28 | { | 28 | { |
29 | unsigned int pipe= urb->pipe; | 29 | unsigned int pipe= urb->pipe; |
@@ -338,7 +338,7 @@ static void ohci_dump_td (const struct ohci_hcd *ohci, const char *label, | |||
338 | } | 338 | } |
339 | 339 | ||
340 | /* caller MUST own hcd spinlock if verbose is set! */ | 340 | /* caller MUST own hcd spinlock if verbose is set! */ |
341 | static void __attribute__((unused)) | 341 | static void __maybe_unused |
342 | ohci_dump_ed (const struct ohci_hcd *ohci, const char *label, | 342 | ohci_dump_ed (const struct ohci_hcd *ohci, const char *label, |
343 | const struct ed *ed, int verbose) | 343 | const struct ed *ed, int verbose) |
344 | { | 344 | { |
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index a66637e725f3..2038125b7f8c 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -35,15 +35,13 @@ | |||
35 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
36 | #include <linux/dmapool.h> | 36 | #include <linux/dmapool.h> |
37 | #include <linux/reboot.h> | 37 | #include <linux/reboot.h> |
38 | #include <linux/workqueue.h> | ||
38 | 39 | ||
39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
40 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
41 | #include <asm/system.h> | 42 | #include <asm/system.h> |
42 | #include <asm/unaligned.h> | 43 | #include <asm/unaligned.h> |
43 | #include <asm/byteorder.h> | 44 | #include <asm/byteorder.h> |
44 | #ifdef CONFIG_PPC_PS3 | ||
45 | #include <asm/firmware.h> | ||
46 | #endif | ||
47 | 45 | ||
48 | #include "../core/hcd.h" | 46 | #include "../core/hcd.h" |
49 | 47 | ||
@@ -82,6 +80,8 @@ static const char hcd_name [] = "ohci_hcd"; | |||
82 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); | 80 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); |
83 | static int ohci_init (struct ohci_hcd *ohci); | 81 | static int ohci_init (struct ohci_hcd *ohci); |
84 | static void ohci_stop (struct usb_hcd *hcd); | 82 | static void ohci_stop (struct usb_hcd *hcd); |
83 | static int ohci_restart (struct ohci_hcd *ohci); | ||
84 | static void ohci_quirk_nec_worker (struct work_struct *work); | ||
85 | 85 | ||
86 | #include "ohci-hub.c" | 86 | #include "ohci-hub.c" |
87 | #include "ohci-dbg.c" | 87 | #include "ohci-dbg.c" |
@@ -510,15 +510,7 @@ static int ohci_run (struct ohci_hcd *ohci) | |||
510 | // flush the writes | 510 | // flush the writes |
511 | (void) ohci_readl (ohci, &ohci->regs->control); | 511 | (void) ohci_readl (ohci, &ohci->regs->control); |
512 | msleep(temp); | 512 | msleep(temp); |
513 | temp = roothub_a (ohci); | 513 | |
514 | if (!(temp & RH_A_NPS)) { | ||
515 | /* power down each port */ | ||
516 | for (temp = 0; temp < ohci->num_ports; temp++) | ||
517 | ohci_writel (ohci, RH_PS_LSDA, | ||
518 | &ohci->regs->roothub.portstatus [temp]); | ||
519 | } | ||
520 | // flush those writes | ||
521 | (void) ohci_readl (ohci, &ohci->regs->control); | ||
522 | memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); | 514 | memset (ohci->hcca, 0, sizeof (struct ohci_hcca)); |
523 | 515 | ||
524 | /* 2msec timelimit here means no irqs/preempt */ | 516 | /* 2msec timelimit here means no irqs/preempt */ |
@@ -659,9 +651,20 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) | |||
659 | } | 651 | } |
660 | 652 | ||
661 | if (ints & OHCI_INTR_UE) { | 653 | if (ints & OHCI_INTR_UE) { |
662 | disable (ohci); | ||
663 | ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); | ||
664 | // e.g. due to PCI Master/Target Abort | 654 | // e.g. due to PCI Master/Target Abort |
655 | if (ohci->flags & OHCI_QUIRK_NEC) { | ||
656 | /* Workaround for a silicon bug in some NEC chips used | ||
657 | * in Apple's PowerBooks. Adapted from Darwin code. | ||
658 | */ | ||
659 | ohci_err (ohci, "OHCI Unrecoverable Error, scheduling NEC chip restart\n"); | ||
660 | |||
661 | ohci_writel (ohci, OHCI_INTR_UE, ®s->intrdisable); | ||
662 | |||
663 | schedule_work (&ohci->nec_work); | ||
664 | } else { | ||
665 | disable (ohci); | ||
666 | ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); | ||
667 | } | ||
665 | 668 | ||
666 | ohci_dump (ohci, 1); | 669 | ohci_dump (ohci, 1); |
667 | ohci_usb_reset (ohci); | 670 | ohci_usb_reset (ohci); |
@@ -763,23 +766,16 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
763 | /*-------------------------------------------------------------------------*/ | 766 | /*-------------------------------------------------------------------------*/ |
764 | 767 | ||
765 | /* must not be called from interrupt context */ | 768 | /* must not be called from interrupt context */ |
766 | |||
767 | #ifdef CONFIG_PM | ||
768 | |||
769 | static int ohci_restart (struct ohci_hcd *ohci) | 769 | static int ohci_restart (struct ohci_hcd *ohci) |
770 | { | 770 | { |
771 | int temp; | 771 | int temp; |
772 | int i; | 772 | int i; |
773 | struct urb_priv *priv; | 773 | struct urb_priv *priv; |
774 | 774 | ||
775 | /* mark any devices gone, so they do nothing till khubd disconnects. | ||
776 | * recycle any "live" eds/tds (and urbs) right away. | ||
777 | * later, khubd disconnect processing will recycle the other state, | ||
778 | * (either as disconnect/reconnect, or maybe someday as a reset). | ||
779 | */ | ||
780 | spin_lock_irq(&ohci->lock); | 775 | spin_lock_irq(&ohci->lock); |
781 | disable (ohci); | 776 | disable (ohci); |
782 | usb_root_hub_lost_power(ohci_to_hcd(ohci)->self.root_hub); | 777 | |
778 | /* Recycle any "live" eds/tds (and urbs). */ | ||
783 | if (!list_empty (&ohci->pending)) | 779 | if (!list_empty (&ohci->pending)) |
784 | ohci_dbg(ohci, "abort schedule...\n"); | 780 | ohci_dbg(ohci, "abort schedule...\n"); |
785 | list_for_each_entry (priv, &ohci->pending, pending) { | 781 | list_for_each_entry (priv, &ohci->pending, pending) { |
@@ -826,20 +822,31 @@ static int ohci_restart (struct ohci_hcd *ohci) | |||
826 | if ((temp = ohci_run (ohci)) < 0) { | 822 | if ((temp = ohci_run (ohci)) < 0) { |
827 | ohci_err (ohci, "can't restart, %d\n", temp); | 823 | ohci_err (ohci, "can't restart, %d\n", temp); |
828 | return temp; | 824 | return temp; |
829 | } else { | ||
830 | /* here we "know" root ports should always stay powered, | ||
831 | * and that if we try to turn them back on the root hub | ||
832 | * will respond to CSC processing. | ||
833 | */ | ||
834 | i = ohci->num_ports; | ||
835 | while (i--) | ||
836 | ohci_writel (ohci, RH_PS_PSS, | ||
837 | &ohci->regs->roothub.portstatus [i]); | ||
838 | ohci_dbg (ohci, "restart complete\n"); | ||
839 | } | 825 | } |
826 | ohci_dbg(ohci, "restart complete\n"); | ||
840 | return 0; | 827 | return 0; |
841 | } | 828 | } |
842 | #endif | 829 | |
830 | /*-------------------------------------------------------------------------*/ | ||
831 | |||
832 | /* NEC workaround */ | ||
833 | static void ohci_quirk_nec_worker(struct work_struct *work) | ||
834 | { | ||
835 | struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work); | ||
836 | int status; | ||
837 | |||
838 | status = ohci_init(ohci); | ||
839 | if (status != 0) { | ||
840 | ohci_err(ohci, "Restarting NEC controller failed " | ||
841 | "in ohci_init, %d\n", status); | ||
842 | return; | ||
843 | } | ||
844 | |||
845 | status = ohci_restart(ohci); | ||
846 | if (status != 0) | ||
847 | ohci_err(ohci, "Restarting NEC controller failed " | ||
848 | "in ohci_restart, %d\n", status); | ||
849 | } | ||
843 | 850 | ||
844 | /*-------------------------------------------------------------------------*/ | 851 | /*-------------------------------------------------------------------------*/ |
845 | 852 | ||
@@ -917,7 +924,7 @@ MODULE_LICENSE ("GPL"); | |||
917 | 924 | ||
918 | #ifdef CONFIG_PPC_PS3 | 925 | #ifdef CONFIG_PPC_PS3 |
919 | #include "ohci-ps3.c" | 926 | #include "ohci-ps3.c" |
920 | #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_sb_driver | 927 | #define PS3_SYSTEM_BUS_DRIVER ps3_ohci_driver |
921 | #endif | 928 | #endif |
922 | 929 | ||
923 | #if !defined(PCI_DRIVER) && \ | 930 | #if !defined(PCI_DRIVER) && \ |
@@ -940,12 +947,9 @@ static int __init ohci_hcd_mod_init(void) | |||
940 | sizeof (struct ed), sizeof (struct td)); | 947 | sizeof (struct ed), sizeof (struct td)); |
941 | 948 | ||
942 | #ifdef PS3_SYSTEM_BUS_DRIVER | 949 | #ifdef PS3_SYSTEM_BUS_DRIVER |
943 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) { | 950 | retval = ps3_ohci_driver_register(&PS3_SYSTEM_BUS_DRIVER); |
944 | retval = ps3_system_bus_driver_register( | 951 | if (retval < 0) |
945 | &PS3_SYSTEM_BUS_DRIVER); | 952 | goto error_ps3; |
946 | if (retval < 0) | ||
947 | goto error_ps3; | ||
948 | } | ||
949 | #endif | 953 | #endif |
950 | 954 | ||
951 | #ifdef PLATFORM_DRIVER | 955 | #ifdef PLATFORM_DRIVER |
@@ -991,8 +995,7 @@ static int __init ohci_hcd_mod_init(void) | |||
991 | error_platform: | 995 | error_platform: |
992 | #endif | 996 | #endif |
993 | #ifdef PS3_SYSTEM_BUS_DRIVER | 997 | #ifdef PS3_SYSTEM_BUS_DRIVER |
994 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) | 998 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
995 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
996 | error_ps3: | 999 | error_ps3: |
997 | #endif | 1000 | #endif |
998 | return retval; | 1001 | return retval; |
@@ -1014,8 +1017,7 @@ static void __exit ohci_hcd_mod_exit(void) | |||
1014 | platform_driver_unregister(&PLATFORM_DRIVER); | 1017 | platform_driver_unregister(&PLATFORM_DRIVER); |
1015 | #endif | 1018 | #endif |
1016 | #ifdef PS3_SYSTEM_BUS_DRIVER | 1019 | #ifdef PS3_SYSTEM_BUS_DRIVER |
1017 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) | 1020 | ps3_ohci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); |
1018 | ps3_system_bus_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); | ||
1019 | #endif | 1021 | #endif |
1020 | } | 1022 | } |
1021 | module_exit(ohci_hcd_mod_exit); | 1023 | module_exit(ohci_hcd_mod_exit); |
diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index bb9cc595219e..48e4b11f4d3e 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c | |||
@@ -55,8 +55,6 @@ static void dl_done_list (struct ohci_hcd *); | |||
55 | static void finish_unlinks (struct ohci_hcd *, u16); | 55 | static void finish_unlinks (struct ohci_hcd *, u16); |
56 | 56 | ||
57 | #ifdef CONFIG_PM | 57 | #ifdef CONFIG_PM |
58 | static int ohci_restart(struct ohci_hcd *ohci); | ||
59 | |||
60 | static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop) | 58 | static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop) |
61 | __releases(ohci->lock) | 59 | __releases(ohci->lock) |
62 | __acquires(ohci->lock) | 60 | __acquires(ohci->lock) |
@@ -191,6 +189,9 @@ __acquires(ohci->lock) | |||
191 | spin_unlock_irq (&ohci->lock); | 189 | spin_unlock_irq (&ohci->lock); |
192 | (void) ohci_init (ohci); | 190 | (void) ohci_init (ohci); |
193 | status = ohci_restart (ohci); | 191 | status = ohci_restart (ohci); |
192 | |||
193 | usb_root_hub_lost_power(hcd->self.root_hub); | ||
194 | |||
194 | spin_lock_irq (&ohci->lock); | 195 | spin_lock_irq (&ohci->lock); |
195 | } | 196 | } |
196 | return status; | 197 | return status; |
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index 2f20d3dc895b..450c7b460c5a 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c | |||
@@ -28,6 +28,7 @@ static void ohci_hcd_init (struct ohci_hcd *ohci) | |||
28 | ohci->next_statechange = jiffies; | 28 | ohci->next_statechange = jiffies; |
29 | spin_lock_init (&ohci->lock); | 29 | spin_lock_init (&ohci->lock); |
30 | INIT_LIST_HEAD (&ohci->pending); | 30 | INIT_LIST_HEAD (&ohci->pending); |
31 | INIT_WORK (&ohci->nec_work, ohci_quirk_nec_worker); | ||
31 | } | 32 | } |
32 | 33 | ||
33 | /*-------------------------------------------------------------------------*/ | 34 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index ca62cb583221..a5e2eb85d073 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -111,6 +111,18 @@ static int ohci_quirk_toshiba_scc(struct usb_hcd *hcd) | |||
111 | #endif | 111 | #endif |
112 | } | 112 | } |
113 | 113 | ||
114 | /* Check for NEC chip and apply quirk for allegedly lost interrupts. | ||
115 | */ | ||
116 | static int ohci_quirk_nec(struct usb_hcd *hcd) | ||
117 | { | ||
118 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
119 | |||
120 | ohci->flags |= OHCI_QUIRK_NEC; | ||
121 | ohci_dbg (ohci, "enabled NEC chipset lost interrupt quirk\n"); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
114 | /* List of quirks for OHCI */ | 126 | /* List of quirks for OHCI */ |
115 | static const struct pci_device_id ohci_pci_quirks[] = { | 127 | static const struct pci_device_id ohci_pci_quirks[] = { |
116 | { | 128 | { |
@@ -134,6 +146,10 @@ static const struct pci_device_id ohci_pci_quirks[] = { | |||
134 | .driver_data = (unsigned long)ohci_quirk_toshiba_scc, | 146 | .driver_data = (unsigned long)ohci_quirk_toshiba_scc, |
135 | }, | 147 | }, |
136 | { | 148 | { |
149 | PCI_DEVICE(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB), | ||
150 | .driver_data = (unsigned long)ohci_quirk_nec, | ||
151 | }, | ||
152 | { | ||
137 | /* Toshiba portege 4000 */ | 153 | /* Toshiba portege 4000 */ |
138 | .vendor = PCI_VENDOR_ID_AL, | 154 | .vendor = PCI_VENDOR_ID_AL, |
139 | .device = 0x5237, | 155 | .device = 0x5237, |
@@ -202,6 +218,42 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd) | |||
202 | return ret; | 218 | return ret; |
203 | } | 219 | } |
204 | 220 | ||
221 | #if defined(CONFIG_USB_PERSIST) && (defined(CONFIG_USB_EHCI_HCD) || \ | ||
222 | defined(CONFIG_USB_EHCI_HCD_MODULE)) | ||
223 | |||
224 | /* Following a power loss, we must prepare to regain control of the ports | ||
225 | * we used to own. This means turning on the port power before ehci-hcd | ||
226 | * tries to switch ownership. | ||
227 | * | ||
228 | * This isn't a 100% perfect solution. On most systems the OHCI controllers | ||
229 | * lie at lower PCI addresses than the EHCI controller, so they will be | ||
230 | * discovered (and hence resumed) first. But there is no guarantee things | ||
231 | * will always work this way. If the EHCI controller is resumed first and | ||
232 | * the OHCI ports are unpowered, then the handover will fail. | ||
233 | */ | ||
234 | static void prepare_for_handover(struct usb_hcd *hcd) | ||
235 | { | ||
236 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | ||
237 | int port; | ||
238 | |||
239 | /* Here we "know" root ports should always stay powered */ | ||
240 | ohci_dbg(ohci, "powerup ports\n"); | ||
241 | for (port = 0; port < ohci->num_ports; port++) | ||
242 | ohci_writel(ohci, RH_PS_PPS, | ||
243 | &ohci->regs->roothub.portstatus[port]); | ||
244 | |||
245 | /* Flush those writes */ | ||
246 | ohci_readl(ohci, &ohci->regs->control); | ||
247 | msleep(20); | ||
248 | } | ||
249 | |||
250 | #else | ||
251 | |||
252 | static inline void prepare_for_handover(struct usb_hcd *hcd) | ||
253 | { } | ||
254 | |||
255 | #endif /* CONFIG_USB_PERSIST etc. */ | ||
256 | |||
205 | #ifdef CONFIG_PM | 257 | #ifdef CONFIG_PM |
206 | 258 | ||
207 | static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | 259 | static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) |
@@ -241,7 +293,10 @@ static int ohci_pci_suspend (struct usb_hcd *hcd, pm_message_t message) | |||
241 | static int ohci_pci_resume (struct usb_hcd *hcd) | 293 | static int ohci_pci_resume (struct usb_hcd *hcd) |
242 | { | 294 | { |
243 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 295 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
244 | usb_hcd_resume_root_hub(hcd); | 296 | |
297 | /* FIXME: we should try to detect loss of VBUS power here */ | ||
298 | prepare_for_handover(hcd); | ||
299 | |||
245 | return 0; | 300 | return 0; |
246 | } | 301 | } |
247 | 302 | ||
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index d601bbb9387b..ca2a6abbc117 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c | |||
@@ -134,7 +134,7 @@ static int isp1301_attach(struct i2c_adapter *adap, int addr, int kind) | |||
134 | { | 134 | { |
135 | struct i2c_client *c; | 135 | struct i2c_client *c; |
136 | 136 | ||
137 | c = (struct i2c_client *)kzalloc(sizeof(*c), GFP_KERNEL); | 137 | c = kzalloc(sizeof(*c), GFP_KERNEL); |
138 | 138 | ||
139 | if (!c) | 139 | if (!c) |
140 | return -ENOMEM; | 140 | return -ENOMEM; |
diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index d7cf07288b0b..01a0caeaa6bc 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c | |||
@@ -18,6 +18,7 @@ | |||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <asm/firmware.h> | ||
21 | #include <asm/ps3.h> | 22 | #include <asm/ps3.h> |
22 | 23 | ||
23 | static int ps3_ohci_hc_reset(struct usb_hcd *hcd) | 24 | static int ps3_ohci_hc_reset(struct usb_hcd *hcd) |
@@ -75,7 +76,7 @@ static const struct hc_driver ps3_ohci_hc_driver = { | |||
75 | #endif | 76 | #endif |
76 | }; | 77 | }; |
77 | 78 | ||
78 | static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev) | 79 | static int ps3_ohci_probe(struct ps3_system_bus_device *dev) |
79 | { | 80 | { |
80 | int result; | 81 | int result; |
81 | struct usb_hcd *hcd; | 82 | struct usb_hcd *hcd; |
@@ -87,13 +88,31 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev) | |||
87 | goto fail_start; | 88 | goto fail_start; |
88 | } | 89 | } |
89 | 90 | ||
91 | result = ps3_open_hv_device(dev); | ||
92 | |||
93 | if (result) { | ||
94 | dev_dbg(&dev->core, "%s:%d: ps3_open_hv_device failed: %s\n", | ||
95 | __func__, __LINE__, ps3_result(result)); | ||
96 | result = -EPERM; | ||
97 | goto fail_open; | ||
98 | } | ||
99 | |||
100 | result = ps3_dma_region_create(dev->d_region); | ||
101 | |||
102 | if (result) { | ||
103 | dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: " | ||
104 | "(%d)\n", __func__, __LINE__, result); | ||
105 | BUG_ON("check region type"); | ||
106 | goto fail_dma_region; | ||
107 | } | ||
108 | |||
90 | result = ps3_mmio_region_create(dev->m_region); | 109 | result = ps3_mmio_region_create(dev->m_region); |
91 | 110 | ||
92 | if (result) { | 111 | if (result) { |
93 | dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", | 112 | dev_dbg(&dev->core, "%s:%d: ps3_map_mmio_region failed\n", |
94 | __func__, __LINE__); | 113 | __func__, __LINE__); |
95 | result = -EPERM; | 114 | result = -EPERM; |
96 | goto fail_mmio; | 115 | goto fail_mmio_region; |
97 | } | 116 | } |
98 | 117 | ||
99 | dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, | 118 | dev_dbg(&dev->core, "%s:%d: mmio mapped_addr %lxh\n", __func__, |
@@ -122,6 +141,11 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev) | |||
122 | 141 | ||
123 | hcd->rsrc_start = dev->m_region->lpar_addr; | 142 | hcd->rsrc_start = dev->m_region->lpar_addr; |
124 | hcd->rsrc_len = dev->m_region->len; | 143 | hcd->rsrc_len = dev->m_region->len; |
144 | |||
145 | if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) | ||
146 | dev_dbg(&dev->core, "%s:%d: request_mem_region failed\n", | ||
147 | __func__, __LINE__); | ||
148 | |||
125 | hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); | 149 | hcd->regs = ioremap(dev->m_region->lpar_addr, dev->m_region->len); |
126 | 150 | ||
127 | if (!hcd->regs) { | 151 | if (!hcd->regs) { |
@@ -155,34 +179,73 @@ static int ps3_ohci_sb_probe(struct ps3_system_bus_device *dev) | |||
155 | fail_add_hcd: | 179 | fail_add_hcd: |
156 | iounmap(hcd->regs); | 180 | iounmap(hcd->regs); |
157 | fail_ioremap: | 181 | fail_ioremap: |
182 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
158 | usb_put_hcd(hcd); | 183 | usb_put_hcd(hcd); |
159 | fail_create_hcd: | 184 | fail_create_hcd: |
160 | ps3_io_irq_destroy(virq); | 185 | ps3_io_irq_destroy(virq); |
161 | fail_irq: | 186 | fail_irq: |
162 | ps3_free_mmio_region(dev->m_region); | 187 | ps3_free_mmio_region(dev->m_region); |
163 | fail_mmio: | 188 | fail_mmio_region: |
189 | ps3_dma_region_free(dev->d_region); | ||
190 | fail_dma_region: | ||
191 | ps3_close_hv_device(dev); | ||
192 | fail_open: | ||
164 | fail_start: | 193 | fail_start: |
165 | return result; | 194 | return result; |
166 | } | 195 | } |
167 | 196 | ||
168 | static int ps3_ohci_sb_remove (struct ps3_system_bus_device *dev) | 197 | static int ps3_ohci_remove (struct ps3_system_bus_device *dev) |
169 | { | 198 | { |
199 | unsigned int tmp; | ||
170 | struct usb_hcd *hcd = | 200 | struct usb_hcd *hcd = |
171 | (struct usb_hcd *)ps3_system_bus_get_driver_data(dev); | 201 | (struct usb_hcd *)ps3_system_bus_get_driver_data(dev); |
172 | 202 | ||
173 | usb_put_hcd(hcd); | 203 | BUG_ON(!hcd); |
204 | |||
205 | dev_dbg(&dev->core, "%s:%d: regs %p\n", __func__, __LINE__, hcd->regs); | ||
206 | dev_dbg(&dev->core, "%s:%d: irq %u\n", __func__, __LINE__, hcd->irq); | ||
207 | |||
208 | tmp = hcd->irq; | ||
209 | |||
210 | usb_remove_hcd(hcd); | ||
211 | |||
174 | ps3_system_bus_set_driver_data(dev, NULL); | 212 | ps3_system_bus_set_driver_data(dev, NULL); |
175 | 213 | ||
214 | BUG_ON(!hcd->regs); | ||
215 | iounmap(hcd->regs); | ||
216 | |||
217 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | ||
218 | usb_put_hcd(hcd); | ||
219 | |||
220 | ps3_io_irq_destroy(tmp); | ||
221 | ps3_free_mmio_region(dev->m_region); | ||
222 | |||
223 | ps3_dma_region_free(dev->d_region); | ||
224 | ps3_close_hv_device(dev); | ||
225 | |||
176 | return 0; | 226 | return 0; |
177 | } | 227 | } |
178 | 228 | ||
179 | MODULE_ALIAS("ps3-ohci"); | 229 | static int ps3_ohci_driver_register(struct ps3_system_bus_driver *drv) |
230 | { | ||
231 | return firmware_has_feature(FW_FEATURE_PS3_LV1) | ||
232 | ? ps3_system_bus_driver_register(drv) | ||
233 | : 0; | ||
234 | } | ||
235 | |||
236 | static void ps3_ohci_driver_unregister(struct ps3_system_bus_driver *drv) | ||
237 | { | ||
238 | if (firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
239 | ps3_system_bus_driver_unregister(drv); | ||
240 | } | ||
241 | |||
242 | MODULE_ALIAS(PS3_MODULE_ALIAS_OHCI); | ||
180 | 243 | ||
181 | static struct ps3_system_bus_driver ps3_ohci_sb_driver = { | 244 | static struct ps3_system_bus_driver ps3_ohci_driver = { |
245 | .core.name = "ps3-ohci-driver", | ||
246 | .core.owner = THIS_MODULE, | ||
182 | .match_id = PS3_MATCH_ID_OHCI, | 247 | .match_id = PS3_MATCH_ID_OHCI, |
183 | .core = { | 248 | .probe = ps3_ohci_probe, |
184 | .name = "ps3-ohci-driver", | 249 | .remove = ps3_ohci_remove, |
185 | }, | 250 | .shutdown = ps3_ohci_remove, |
186 | .probe = ps3_ohci_sb_probe, | ||
187 | .remove = ps3_ohci_sb_remove, | ||
188 | }; | 251 | }; |
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index c2b5ecfe5e9f..4ada43cf1387 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h | |||
@@ -397,8 +397,10 @@ struct ohci_hcd { | |||
397 | #define OHCI_QUIRK_BE_DESC 0x08 /* BE descriptors */ | 397 | #define OHCI_QUIRK_BE_DESC 0x08 /* BE descriptors */ |
398 | #define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */ | 398 | #define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */ |
399 | #define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ | 399 | #define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ |
400 | #define OHCI_QUIRK_NEC 0x40 /* lost interrupts */ | ||
400 | // there are also chip quirks/bugs in init logic | 401 | // there are also chip quirks/bugs in init logic |
401 | 402 | ||
403 | struct work_struct nec_work; /* Worker for NEC quirk */ | ||
402 | }; | 404 | }; |
403 | 405 | ||
404 | /* convert between an hcd pointer and the corresponding ohci_hcd */ | 406 | /* convert between an hcd pointer and the corresponding ohci_hcd */ |
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c new file mode 100644 index 000000000000..a7a7070c6e2a --- /dev/null +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -0,0 +1,2244 @@ | |||
1 | /* | ||
2 | * R8A66597 HCD (Host Controller Driver) | ||
3 | * | ||
4 | * Copyright (C) 2006-2007 Renesas Solutions Corp. | ||
5 | * Portions Copyright (C) 2004 Psion Teklogix (for NetBook PRO) | ||
6 | * Portions Copyright (C) 2004-2005 David Brownell | ||
7 | * Portions Copyright (C) 1999 Roman Weissgaerber | ||
8 | * | ||
9 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; version 2 of the License. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/smp_lock.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/timer.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/list.h> | ||
35 | #include <linux/interrupt.h> | ||
36 | #include <linux/usb.h> | ||
37 | #include <linux/platform_device.h> | ||
38 | |||
39 | #include <asm/io.h> | ||
40 | #include <asm/irq.h> | ||
41 | #include <asm/system.h> | ||
42 | |||
43 | #include "../core/hcd.h" | ||
44 | #include "r8a66597.h" | ||
45 | |||
46 | MODULE_DESCRIPTION("R8A66597 USB Host Controller Driver"); | ||
47 | MODULE_LICENSE("GPL"); | ||
48 | MODULE_AUTHOR("Yoshihiro Shimoda"); | ||
49 | |||
50 | #define DRIVER_VERSION "29 May 2007" | ||
51 | |||
52 | static const char hcd_name[] = "r8a66597_hcd"; | ||
53 | |||
54 | /* module parameters */ | ||
55 | static unsigned short clock = XTAL12; | ||
56 | module_param(clock, ushort, 0644); | ||
57 | MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0(default=0)"); | ||
58 | static unsigned short vif = LDRV; | ||
59 | module_param(vif, ushort, 0644); | ||
60 | MODULE_PARM_DESC(vif, "input VIF: 3.3V=32768, 1.5V=0(default=32768)"); | ||
61 | static unsigned short endian = 0; | ||
62 | module_param(endian, ushort, 0644); | ||
63 | MODULE_PARM_DESC(endian, "data endian: big=256, little=0(default=0)"); | ||
64 | static unsigned short irq_sense = INTL; | ||
65 | module_param(irq_sense, ushort, 0644); | ||
66 | MODULE_PARM_DESC(irq_sense, "IRQ sense: low level=32, falling edge=0(default=32)"); | ||
67 | |||
68 | static void packet_write(struct r8a66597 *r8a66597, u16 pipenum); | ||
69 | static int r8a66597_get_frame(struct usb_hcd *hcd); | ||
70 | |||
71 | /* this function must be called with interrupt disabled */ | ||
72 | static void enable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum, | ||
73 | unsigned long reg) | ||
74 | { | ||
75 | u16 tmp; | ||
76 | |||
77 | tmp = r8a66597_read(r8a66597, INTENB0); | ||
78 | r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0); | ||
79 | r8a66597_bset(r8a66597, 1 << pipenum, reg); | ||
80 | r8a66597_write(r8a66597, tmp, INTENB0); | ||
81 | } | ||
82 | |||
83 | /* this function must be called with interrupt disabled */ | ||
84 | static void disable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum, | ||
85 | unsigned long reg) | ||
86 | { | ||
87 | u16 tmp; | ||
88 | |||
89 | tmp = r8a66597_read(r8a66597, INTENB0); | ||
90 | r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0); | ||
91 | r8a66597_bclr(r8a66597, 1 << pipenum, reg); | ||
92 | r8a66597_write(r8a66597, tmp, INTENB0); | ||
93 | } | ||
94 | |||
95 | static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address, | ||
96 | u16 usbspd, u8 upphub, u8 hubport, int port) | ||
97 | { | ||
98 | u16 val; | ||
99 | unsigned long devadd_reg = get_devadd_addr(r8a66597_address); | ||
100 | |||
101 | val = (upphub << 11) | (hubport << 8) | (usbspd << 6) | (port & 0x0001); | ||
102 | r8a66597_write(r8a66597, val, devadd_reg); | ||
103 | } | ||
104 | |||
105 | static int enable_controller(struct r8a66597 *r8a66597) | ||
106 | { | ||
107 | u16 tmp; | ||
108 | int i = 0; | ||
109 | |||
110 | do { | ||
111 | r8a66597_write(r8a66597, USBE, SYSCFG0); | ||
112 | tmp = r8a66597_read(r8a66597, SYSCFG0); | ||
113 | if (i++ > 1000) { | ||
114 | err("register access fail."); | ||
115 | return -ENXIO; | ||
116 | } | ||
117 | } while ((tmp & USBE) != USBE); | ||
118 | r8a66597_bclr(r8a66597, USBE, SYSCFG0); | ||
119 | r8a66597_mdfy(r8a66597, clock, XTAL, SYSCFG0); | ||
120 | |||
121 | i = 0; | ||
122 | r8a66597_bset(r8a66597, XCKE, SYSCFG0); | ||
123 | do { | ||
124 | msleep(1); | ||
125 | tmp = r8a66597_read(r8a66597, SYSCFG0); | ||
126 | if (i++ > 500) { | ||
127 | err("register access fail."); | ||
128 | return -ENXIO; | ||
129 | } | ||
130 | } while ((tmp & SCKE) != SCKE); | ||
131 | |||
132 | r8a66597_bset(r8a66597, DCFM | DRPD, SYSCFG0); | ||
133 | r8a66597_bset(r8a66597, DRPD, SYSCFG1); | ||
134 | |||
135 | r8a66597_bset(r8a66597, vif & LDRV, PINCFG); | ||
136 | r8a66597_bset(r8a66597, HSE, SYSCFG0); | ||
137 | r8a66597_bset(r8a66597, HSE, SYSCFG1); | ||
138 | r8a66597_bset(r8a66597, USBE, SYSCFG0); | ||
139 | |||
140 | r8a66597_bset(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0); | ||
141 | r8a66597_bset(r8a66597, irq_sense & INTL, SOFCFG); | ||
142 | r8a66597_bset(r8a66597, BRDY0, BRDYENB); | ||
143 | r8a66597_bset(r8a66597, BEMP0, BEMPENB); | ||
144 | |||
145 | r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA0CFG); | ||
146 | r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA1CFG); | ||
147 | |||
148 | r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL); | ||
149 | r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL); | ||
150 | r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL); | ||
151 | |||
152 | r8a66597_bset(r8a66597, TRNENSEL, SOFCFG); | ||
153 | |||
154 | r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1); | ||
155 | r8a66597_bclr(r8a66597, DTCHE, INTENB1); | ||
156 | r8a66597_bset(r8a66597, ATTCHE, INTENB1); | ||
157 | r8a66597_bclr(r8a66597, DTCHE, INTENB2); | ||
158 | r8a66597_bset(r8a66597, ATTCHE, INTENB2); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | static void disable_controller(struct r8a66597 *r8a66597) | ||
164 | { | ||
165 | u16 tmp; | ||
166 | |||
167 | r8a66597_write(r8a66597, 0, INTENB0); | ||
168 | r8a66597_write(r8a66597, 0, INTENB1); | ||
169 | r8a66597_write(r8a66597, 0, INTENB2); | ||
170 | r8a66597_write(r8a66597, 0, INTSTS0); | ||
171 | r8a66597_write(r8a66597, 0, INTSTS1); | ||
172 | r8a66597_write(r8a66597, 0, INTSTS2); | ||
173 | |||
174 | r8a66597_port_power(r8a66597, 0, 0); | ||
175 | r8a66597_port_power(r8a66597, 1, 0); | ||
176 | |||
177 | do { | ||
178 | tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS; | ||
179 | udelay(640); | ||
180 | } while (tmp == EDGESTS); | ||
181 | |||
182 | r8a66597_bclr(r8a66597, DCFM | DRPD, SYSCFG0); | ||
183 | r8a66597_bclr(r8a66597, DRPD, SYSCFG1); | ||
184 | r8a66597_bclr(r8a66597, HSE, SYSCFG0); | ||
185 | r8a66597_bclr(r8a66597, HSE, SYSCFG1); | ||
186 | |||
187 | r8a66597_bclr(r8a66597, SCKE, SYSCFG0); | ||
188 | udelay(1); | ||
189 | r8a66597_bclr(r8a66597, PLLC, SYSCFG0); | ||
190 | r8a66597_bclr(r8a66597, XCKE, SYSCFG0); | ||
191 | r8a66597_bclr(r8a66597, USBE, SYSCFG0); | ||
192 | } | ||
193 | |||
194 | static int get_parent_r8a66597_address(struct r8a66597 *r8a66597, | ||
195 | struct usb_device *udev) | ||
196 | { | ||
197 | struct r8a66597_device *dev; | ||
198 | |||
199 | if (udev->parent && udev->parent->devnum != 1) | ||
200 | udev = udev->parent; | ||
201 | |||
202 | dev = dev_get_drvdata(&udev->dev); | ||
203 | if (dev) | ||
204 | return dev->address; | ||
205 | else | ||
206 | return 0; | ||
207 | } | ||
208 | |||
209 | static int is_child_device(char *devpath) | ||
210 | { | ||
211 | return (devpath[2] ? 1 : 0); | ||
212 | } | ||
213 | |||
214 | static int is_hub_limit(char *devpath) | ||
215 | { | ||
216 | return ((strlen(devpath) >= 4) ? 1 : 0); | ||
217 | } | ||
218 | |||
219 | static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port) | ||
220 | { | ||
221 | if (root_port) { | ||
222 | *root_port = (devpath[0] & 0x0F) - 1; | ||
223 | if (*root_port >= R8A66597_MAX_ROOT_HUB) | ||
224 | err("illegal root port number"); | ||
225 | } | ||
226 | if (hub_port) | ||
227 | *hub_port = devpath[2] & 0x0F; | ||
228 | } | ||
229 | |||
230 | static u16 get_r8a66597_usb_speed(enum usb_device_speed speed) | ||
231 | { | ||
232 | u16 usbspd = 0; | ||
233 | |||
234 | switch (speed) { | ||
235 | case USB_SPEED_LOW: | ||
236 | usbspd = LSMODE; | ||
237 | break; | ||
238 | case USB_SPEED_FULL: | ||
239 | usbspd = FSMODE; | ||
240 | break; | ||
241 | case USB_SPEED_HIGH: | ||
242 | usbspd = HSMODE; | ||
243 | break; | ||
244 | default: | ||
245 | err("unknown speed"); | ||
246 | break; | ||
247 | } | ||
248 | |||
249 | return usbspd; | ||
250 | } | ||
251 | |||
252 | static void set_child_connect_map(struct r8a66597 *r8a66597, int address) | ||
253 | { | ||
254 | int idx; | ||
255 | |||
256 | idx = address / 32; | ||
257 | r8a66597->child_connect_map[idx] |= 1 << (address % 32); | ||
258 | } | ||
259 | |||
260 | static void put_child_connect_map(struct r8a66597 *r8a66597, int address) | ||
261 | { | ||
262 | int idx; | ||
263 | |||
264 | idx = address / 32; | ||
265 | r8a66597->child_connect_map[idx] &= ~(1 << (address % 32)); | ||
266 | } | ||
267 | |||
268 | static void set_pipe_reg_addr(struct r8a66597_pipe *pipe, u8 dma_ch) | ||
269 | { | ||
270 | u16 pipenum = pipe->info.pipenum; | ||
271 | unsigned long fifoaddr[] = {D0FIFO, D1FIFO, CFIFO}; | ||
272 | unsigned long fifosel[] = {D0FIFOSEL, D1FIFOSEL, CFIFOSEL}; | ||
273 | unsigned long fifoctr[] = {D0FIFOCTR, D1FIFOCTR, CFIFOCTR}; | ||
274 | |||
275 | if (dma_ch > R8A66597_PIPE_NO_DMA) /* dma fifo not use? */ | ||
276 | dma_ch = R8A66597_PIPE_NO_DMA; | ||
277 | |||
278 | pipe->fifoaddr = fifoaddr[dma_ch]; | ||
279 | pipe->fifosel = fifosel[dma_ch]; | ||
280 | pipe->fifoctr = fifoctr[dma_ch]; | ||
281 | |||
282 | if (pipenum == 0) | ||
283 | pipe->pipectr = DCPCTR; | ||
284 | else | ||
285 | pipe->pipectr = get_pipectr_addr(pipenum); | ||
286 | |||
287 | if (check_bulk_or_isoc(pipenum)) { | ||
288 | pipe->pipetre = get_pipetre_addr(pipenum); | ||
289 | pipe->pipetrn = get_pipetrn_addr(pipenum); | ||
290 | } else { | ||
291 | pipe->pipetre = 0; | ||
292 | pipe->pipetrn = 0; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static struct r8a66597_device * | ||
297 | get_urb_to_r8a66597_dev(struct r8a66597 *r8a66597, struct urb *urb) | ||
298 | { | ||
299 | if (usb_pipedevice(urb->pipe) == 0) | ||
300 | return &r8a66597->device0; | ||
301 | |||
302 | return dev_get_drvdata(&urb->dev->dev); | ||
303 | } | ||
304 | |||
305 | static int make_r8a66597_device(struct r8a66597 *r8a66597, | ||
306 | struct urb *urb, u8 addr) | ||
307 | { | ||
308 | struct r8a66597_device *dev; | ||
309 | int usb_address = urb->setup_packet[2]; /* urb->pipe is address 0 */ | ||
310 | |||
311 | dev = kzalloc(sizeof(struct r8a66597_device), GFP_KERNEL); | ||
312 | if (dev == NULL) | ||
313 | return -ENOMEM; | ||
314 | |||
315 | dev_set_drvdata(&urb->dev->dev, dev); | ||
316 | dev->udev = urb->dev; | ||
317 | dev->address = addr; | ||
318 | dev->usb_address = usb_address; | ||
319 | dev->state = USB_STATE_ADDRESS; | ||
320 | dev->ep_in_toggle = 0; | ||
321 | dev->ep_out_toggle = 0; | ||
322 | INIT_LIST_HEAD(&dev->device_list); | ||
323 | list_add_tail(&dev->device_list, &r8a66597->child_device); | ||
324 | |||
325 | get_port_number(urb->dev->devpath, &dev->root_port, &dev->hub_port); | ||
326 | if (!is_child_device(urb->dev->devpath)) | ||
327 | r8a66597->root_hub[dev->root_port].dev = dev; | ||
328 | |||
329 | set_devadd_reg(r8a66597, dev->address, | ||
330 | get_r8a66597_usb_speed(urb->dev->speed), | ||
331 | get_parent_r8a66597_address(r8a66597, urb->dev), | ||
332 | dev->hub_port, dev->root_port); | ||
333 | |||
334 | return 0; | ||
335 | } | ||
336 | |||
337 | /* this function must be called with interrupt disabled */ | ||
338 | static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb) | ||
339 | { | ||
340 | u8 addr; /* R8A66597's address */ | ||
341 | struct r8a66597_device *dev; | ||
342 | |||
343 | if (is_hub_limit(urb->dev->devpath)) { | ||
344 | err("Externel hub limit reached."); | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | dev = get_urb_to_r8a66597_dev(r8a66597, urb); | ||
349 | if (dev && dev->state >= USB_STATE_ADDRESS) | ||
350 | return dev->address; | ||
351 | |||
352 | for (addr = 1; addr <= R8A66597_MAX_DEVICE; addr++) { | ||
353 | if (r8a66597->address_map & (1 << addr)) | ||
354 | continue; | ||
355 | |||
356 | dbg("alloc_address: r8a66597_addr=%d", addr); | ||
357 | r8a66597->address_map |= 1 << addr; | ||
358 | |||
359 | if (make_r8a66597_device(r8a66597, urb, addr) < 0) | ||
360 | return 0; | ||
361 | |||
362 | return addr; | ||
363 | } | ||
364 | |||
365 | err("cannot communicate with a USB device more than 10.(%x)", | ||
366 | r8a66597->address_map); | ||
367 | |||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | /* this function must be called with interrupt disabled */ | ||
372 | static void free_usb_address(struct r8a66597 *r8a66597, | ||
373 | struct r8a66597_device *dev) | ||
374 | { | ||
375 | int port; | ||
376 | |||
377 | if (!dev) | ||
378 | return; | ||
379 | |||
380 | dbg("free_addr: addr=%d", dev->address); | ||
381 | |||
382 | dev->state = USB_STATE_DEFAULT; | ||
383 | r8a66597->address_map &= ~(1 << dev->address); | ||
384 | dev->address = 0; | ||
385 | dev_set_drvdata(&dev->udev->dev, NULL); | ||
386 | list_del(&dev->device_list); | ||
387 | kfree(dev); | ||
388 | |||
389 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { | ||
390 | if (r8a66597->root_hub[port].dev == dev) { | ||
391 | r8a66597->root_hub[port].dev = NULL; | ||
392 | break; | ||
393 | } | ||
394 | } | ||
395 | } | ||
396 | |||
397 | static void r8a66597_reg_wait(struct r8a66597 *r8a66597, unsigned long reg, | ||
398 | u16 mask, u16 loop) | ||
399 | { | ||
400 | u16 tmp; | ||
401 | int i = 0; | ||
402 | |||
403 | do { | ||
404 | tmp = r8a66597_read(r8a66597, reg); | ||
405 | if (i++ > 1000000) { | ||
406 | err("register%lx, loop %x is timeout", reg, loop); | ||
407 | break; | ||
408 | } | ||
409 | ndelay(1); | ||
410 | } while ((tmp & mask) != loop); | ||
411 | } | ||
412 | |||
413 | /* this function must be called with interrupt disabled */ | ||
414 | static void pipe_start(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe) | ||
415 | { | ||
416 | u16 tmp; | ||
417 | |||
418 | tmp = r8a66597_read(r8a66597, pipe->pipectr) & PID; | ||
419 | if ((pipe->info.pipenum != 0) & ((tmp & PID_STALL) != 0)) /* stall? */ | ||
420 | r8a66597_mdfy(r8a66597, PID_NAK, PID, pipe->pipectr); | ||
421 | r8a66597_mdfy(r8a66597, PID_BUF, PID, pipe->pipectr); | ||
422 | } | ||
423 | |||
424 | /* this function must be called with interrupt disabled */ | ||
425 | static void pipe_stop(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe) | ||
426 | { | ||
427 | u16 tmp; | ||
428 | |||
429 | tmp = r8a66597_read(r8a66597, pipe->pipectr) & PID; | ||
430 | if ((tmp & PID_STALL11) != PID_STALL11) /* force stall? */ | ||
431 | r8a66597_mdfy(r8a66597, PID_STALL, PID, pipe->pipectr); | ||
432 | r8a66597_mdfy(r8a66597, PID_NAK, PID, pipe->pipectr); | ||
433 | r8a66597_reg_wait(r8a66597, pipe->pipectr, PBUSY, 0); | ||
434 | } | ||
435 | |||
436 | /* this function must be called with interrupt disabled */ | ||
437 | static void clear_all_buffer(struct r8a66597 *r8a66597, | ||
438 | struct r8a66597_pipe *pipe) | ||
439 | { | ||
440 | u16 tmp; | ||
441 | |||
442 | if (!pipe || pipe->info.pipenum == 0) | ||
443 | return; | ||
444 | |||
445 | pipe_stop(r8a66597, pipe); | ||
446 | r8a66597_bset(r8a66597, ACLRM, pipe->pipectr); | ||
447 | tmp = r8a66597_read(r8a66597, pipe->pipectr); | ||
448 | tmp = r8a66597_read(r8a66597, pipe->pipectr); | ||
449 | tmp = r8a66597_read(r8a66597, pipe->pipectr); | ||
450 | r8a66597_bclr(r8a66597, ACLRM, pipe->pipectr); | ||
451 | } | ||
452 | |||
453 | /* this function must be called with interrupt disabled */ | ||
454 | static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597, | ||
455 | struct r8a66597_pipe *pipe, int toggle) | ||
456 | { | ||
457 | if (toggle) | ||
458 | r8a66597_bset(r8a66597, SQSET, pipe->pipectr); | ||
459 | else | ||
460 | r8a66597_bset(r8a66597, SQCLR, pipe->pipectr); | ||
461 | } | ||
462 | |||
463 | /* this function must be called with interrupt disabled */ | ||
464 | static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum) | ||
465 | { | ||
466 | r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL); | ||
467 | r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum); | ||
468 | } | ||
469 | |||
470 | /* this function must be called with interrupt disabled */ | ||
471 | static inline void fifo_change_from_pipe(struct r8a66597 *r8a66597, | ||
472 | struct r8a66597_pipe *pipe) | ||
473 | { | ||
474 | cfifo_change(r8a66597, 0); | ||
475 | r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL); | ||
476 | r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL); | ||
477 | |||
478 | r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE, | ||
479 | pipe->fifosel); | ||
480 | r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum); | ||
481 | } | ||
482 | |||
483 | static u16 r8a66597_get_pipenum(struct urb *urb, struct usb_host_endpoint *hep) | ||
484 | { | ||
485 | struct r8a66597_pipe *pipe = hep->hcpriv; | ||
486 | |||
487 | if (usb_pipeendpoint(urb->pipe) == 0) | ||
488 | return 0; | ||
489 | else | ||
490 | return pipe->info.pipenum; | ||
491 | } | ||
492 | |||
493 | static u16 get_urb_to_r8a66597_addr(struct r8a66597 *r8a66597, struct urb *urb) | ||
494 | { | ||
495 | struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb); | ||
496 | |||
497 | return (usb_pipedevice(urb->pipe) == 0) ? 0 : dev->address; | ||
498 | } | ||
499 | |||
500 | static unsigned short *get_toggle_pointer(struct r8a66597_device *dev, | ||
501 | int urb_pipe) | ||
502 | { | ||
503 | if (!dev) | ||
504 | return NULL; | ||
505 | |||
506 | return usb_pipein(urb_pipe) ? &dev->ep_in_toggle : &dev->ep_out_toggle; | ||
507 | } | ||
508 | |||
509 | /* this function must be called with interrupt disabled */ | ||
510 | static void pipe_toggle_set(struct r8a66597 *r8a66597, | ||
511 | struct r8a66597_pipe *pipe, | ||
512 | struct urb *urb, int set) | ||
513 | { | ||
514 | struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb); | ||
515 | unsigned char endpoint = usb_pipeendpoint(urb->pipe); | ||
516 | unsigned short *toggle = get_toggle_pointer(dev, urb->pipe); | ||
517 | |||
518 | if (!toggle) | ||
519 | return; | ||
520 | |||
521 | if (set) | ||
522 | *toggle |= 1 << endpoint; | ||
523 | else | ||
524 | *toggle &= ~(1 << endpoint); | ||
525 | } | ||
526 | |||
527 | /* this function must be called with interrupt disabled */ | ||
528 | static void pipe_toggle_save(struct r8a66597 *r8a66597, | ||
529 | struct r8a66597_pipe *pipe, | ||
530 | struct urb *urb) | ||
531 | { | ||
532 | if (r8a66597_read(r8a66597, pipe->pipectr) & SQMON) | ||
533 | pipe_toggle_set(r8a66597, pipe, urb, 1); | ||
534 | else | ||
535 | pipe_toggle_set(r8a66597, pipe, urb, 0); | ||
536 | } | ||
537 | |||
538 | /* this function must be called with interrupt disabled */ | ||
539 | static void pipe_toggle_restore(struct r8a66597 *r8a66597, | ||
540 | struct r8a66597_pipe *pipe, | ||
541 | struct urb *urb) | ||
542 | { | ||
543 | struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb); | ||
544 | unsigned char endpoint = usb_pipeendpoint(urb->pipe); | ||
545 | unsigned short *toggle = get_toggle_pointer(dev, urb->pipe); | ||
546 | |||
547 | if (!toggle) | ||
548 | return; | ||
549 | |||
550 | r8a66597_pipe_toggle(r8a66597, pipe, *toggle & (1 << endpoint)); | ||
551 | } | ||
552 | |||
553 | /* this function must be called with interrupt disabled */ | ||
554 | static void pipe_buffer_setting(struct r8a66597 *r8a66597, | ||
555 | struct r8a66597_pipe_info *info) | ||
556 | { | ||
557 | u16 val = 0; | ||
558 | |||
559 | if (info->pipenum == 0) | ||
560 | return; | ||
561 | |||
562 | r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(info->pipenum)); | ||
563 | r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(info->pipenum)); | ||
564 | r8a66597_write(r8a66597, info->pipenum, PIPESEL); | ||
565 | if (!info->dir_in) | ||
566 | val |= R8A66597_DIR; | ||
567 | if (info->type == R8A66597_BULK && info->dir_in) | ||
568 | val |= R8A66597_DBLB | R8A66597_SHTNAK; | ||
569 | val |= info->type | info->epnum; | ||
570 | r8a66597_write(r8a66597, val, PIPECFG); | ||
571 | |||
572 | r8a66597_write(r8a66597, (info->buf_bsize << 10) | (info->bufnum), | ||
573 | PIPEBUF); | ||
574 | r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket, | ||
575 | PIPEMAXP); | ||
576 | if (info->interval) | ||
577 | info->interval--; | ||
578 | r8a66597_write(r8a66597, info->interval, PIPEPERI); | ||
579 | } | ||
580 | |||
581 | |||
582 | |||
583 | /* this function must be called with interrupt disabled */ | ||
584 | static void pipe_setting(struct r8a66597 *r8a66597, struct r8a66597_td *td) | ||
585 | { | ||
586 | struct r8a66597_pipe_info *info; | ||
587 | struct urb *urb = td->urb; | ||
588 | |||
589 | if (td->pipenum > 0) { | ||
590 | info = &td->pipe->info; | ||
591 | cfifo_change(r8a66597, 0); | ||
592 | pipe_buffer_setting(r8a66597, info); | ||
593 | |||
594 | if (!usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
595 | usb_pipeout(urb->pipe)) && | ||
596 | !usb_pipecontrol(urb->pipe)) { | ||
597 | r8a66597_pipe_toggle(r8a66597, td->pipe, 0); | ||
598 | pipe_toggle_set(r8a66597, td->pipe, urb, 0); | ||
599 | clear_all_buffer(r8a66597, td->pipe); | ||
600 | usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
601 | usb_pipeout(urb->pipe), 1); | ||
602 | } | ||
603 | pipe_toggle_restore(r8a66597, td->pipe, urb); | ||
604 | } | ||
605 | } | ||
606 | |||
607 | /* this function must be called with interrupt disabled */ | ||
608 | static u16 get_empty_pipenum(struct r8a66597 *r8a66597, | ||
609 | struct usb_endpoint_descriptor *ep) | ||
610 | { | ||
611 | u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; | ||
612 | |||
613 | memset(array, 0, sizeof(array)); | ||
614 | switch(ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { | ||
615 | case USB_ENDPOINT_XFER_BULK: | ||
616 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | ||
617 | array[i++] = 4; | ||
618 | else { | ||
619 | array[i++] = 3; | ||
620 | array[i++] = 5; | ||
621 | } | ||
622 | break; | ||
623 | case USB_ENDPOINT_XFER_INT: | ||
624 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { | ||
625 | array[i++] = 6; | ||
626 | array[i++] = 7; | ||
627 | array[i++] = 8; | ||
628 | } else | ||
629 | array[i++] = 9; | ||
630 | break; | ||
631 | case USB_ENDPOINT_XFER_ISOC: | ||
632 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | ||
633 | array[i++] = 2; | ||
634 | else | ||
635 | array[i++] = 1; | ||
636 | break; | ||
637 | default: | ||
638 | err("Illegal type"); | ||
639 | return 0; | ||
640 | } | ||
641 | |||
642 | i = 1; | ||
643 | min = array[0]; | ||
644 | while (array[i] != 0) { | ||
645 | if (r8a66597->pipe_cnt[min] > r8a66597->pipe_cnt[array[i]]) | ||
646 | min = array[i]; | ||
647 | i++; | ||
648 | } | ||
649 | |||
650 | return min; | ||
651 | } | ||
652 | |||
653 | static u16 get_r8a66597_type(__u8 type) | ||
654 | { | ||
655 | u16 r8a66597_type; | ||
656 | |||
657 | switch(type) { | ||
658 | case USB_ENDPOINT_XFER_BULK: | ||
659 | r8a66597_type = R8A66597_BULK; | ||
660 | break; | ||
661 | case USB_ENDPOINT_XFER_INT: | ||
662 | r8a66597_type = R8A66597_INT; | ||
663 | break; | ||
664 | case USB_ENDPOINT_XFER_ISOC: | ||
665 | r8a66597_type = R8A66597_ISO; | ||
666 | break; | ||
667 | default: | ||
668 | err("Illegal type"); | ||
669 | r8a66597_type = 0x0000; | ||
670 | break; | ||
671 | } | ||
672 | |||
673 | return r8a66597_type; | ||
674 | } | ||
675 | |||
676 | static u16 get_bufnum(u16 pipenum) | ||
677 | { | ||
678 | u16 bufnum = 0; | ||
679 | |||
680 | if (pipenum == 0) | ||
681 | bufnum = 0; | ||
682 | else if (check_bulk_or_isoc(pipenum)) | ||
683 | bufnum = 8 + (pipenum - 1) * R8A66597_BUF_BSIZE*2; | ||
684 | else if (check_interrupt(pipenum)) | ||
685 | bufnum = 4 + (pipenum - 6); | ||
686 | else | ||
687 | err("Illegal pipenum (%d)", pipenum); | ||
688 | |||
689 | return bufnum; | ||
690 | } | ||
691 | |||
692 | static u16 get_buf_bsize(u16 pipenum) | ||
693 | { | ||
694 | u16 buf_bsize = 0; | ||
695 | |||
696 | if (pipenum == 0) | ||
697 | buf_bsize = 3; | ||
698 | else if (check_bulk_or_isoc(pipenum)) | ||
699 | buf_bsize = R8A66597_BUF_BSIZE - 1; | ||
700 | else if (check_interrupt(pipenum)) | ||
701 | buf_bsize = 0; | ||
702 | else | ||
703 | err("Illegal pipenum (%d)", pipenum); | ||
704 | |||
705 | return buf_bsize; | ||
706 | } | ||
707 | |||
708 | /* this function must be called with interrupt disabled */ | ||
709 | static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597, | ||
710 | struct r8a66597_device *dev, | ||
711 | struct r8a66597_pipe *pipe, | ||
712 | struct urb *urb) | ||
713 | { | ||
714 | int i; | ||
715 | struct r8a66597_pipe_info *info = &pipe->info; | ||
716 | |||
717 | if ((pipe->info.pipenum != 0) && (info->type != R8A66597_INT)) { | ||
718 | for (i = 0; i < R8A66597_MAX_DMA_CHANNEL; i++) { | ||
719 | if ((r8a66597->dma_map & (1 << i)) != 0) | ||
720 | continue; | ||
721 | |||
722 | info("address %d, EndpointAddress 0x%02x use DMA FIFO", | ||
723 | usb_pipedevice(urb->pipe), | ||
724 | info->dir_in ? USB_ENDPOINT_DIR_MASK + info->epnum | ||
725 | : info->epnum); | ||
726 | |||
727 | r8a66597->dma_map |= 1 << i; | ||
728 | dev->dma_map |= 1 << i; | ||
729 | set_pipe_reg_addr(pipe, i); | ||
730 | |||
731 | cfifo_change(r8a66597, 0); | ||
732 | r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, | ||
733 | MBW | CURPIPE, pipe->fifosel); | ||
734 | |||
735 | r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, | ||
736 | pipe->info.pipenum); | ||
737 | r8a66597_bset(r8a66597, BCLR, pipe->fifoctr); | ||
738 | break; | ||
739 | } | ||
740 | } | ||
741 | } | ||
742 | |||
743 | /* this function must be called with interrupt disabled */ | ||
744 | static void enable_r8a66597_pipe(struct r8a66597 *r8a66597, struct urb *urb, | ||
745 | struct usb_host_endpoint *hep, | ||
746 | struct r8a66597_pipe_info *info) | ||
747 | { | ||
748 | struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb); | ||
749 | struct r8a66597_pipe *pipe = hep->hcpriv; | ||
750 | |||
751 | dbg("enable_pipe:"); | ||
752 | |||
753 | pipe->info = *info; | ||
754 | set_pipe_reg_addr(pipe, R8A66597_PIPE_NO_DMA); | ||
755 | r8a66597->pipe_cnt[pipe->info.pipenum]++; | ||
756 | dev->pipe_cnt[pipe->info.pipenum]++; | ||
757 | |||
758 | enable_r8a66597_pipe_dma(r8a66597, dev, pipe, urb); | ||
759 | } | ||
760 | |||
761 | /* this function must be called with interrupt disabled */ | ||
762 | static void force_dequeue(struct r8a66597 *r8a66597, u16 pipenum, u16 address) | ||
763 | { | ||
764 | struct r8a66597_td *td, *next; | ||
765 | struct urb *urb; | ||
766 | struct list_head *list = &r8a66597->pipe_queue[pipenum]; | ||
767 | |||
768 | if (list_empty(list)) | ||
769 | return; | ||
770 | |||
771 | list_for_each_entry_safe(td, next, list, queue) { | ||
772 | if (!td) | ||
773 | continue; | ||
774 | if (td->address != address) | ||
775 | continue; | ||
776 | |||
777 | urb = td->urb; | ||
778 | list_del(&td->queue); | ||
779 | kfree(td); | ||
780 | |||
781 | if (urb) { | ||
782 | urb->status = -ENODEV; | ||
783 | urb->hcpriv = NULL; | ||
784 | spin_unlock(&r8a66597->lock); | ||
785 | usb_hcd_giveback_urb(r8a66597_to_hcd(r8a66597), urb); | ||
786 | spin_lock(&r8a66597->lock); | ||
787 | } | ||
788 | break; | ||
789 | } | ||
790 | } | ||
791 | |||
792 | /* this function must be called with interrupt disabled */ | ||
793 | static void disable_r8a66597_pipe_all(struct r8a66597 *r8a66597, | ||
794 | struct r8a66597_device *dev) | ||
795 | { | ||
796 | int check_ep0 = 0; | ||
797 | u16 pipenum; | ||
798 | |||
799 | if (!dev) | ||
800 | return; | ||
801 | |||
802 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | ||
803 | if (!dev->pipe_cnt[pipenum]) | ||
804 | continue; | ||
805 | |||
806 | if (!check_ep0) { | ||
807 | check_ep0 = 1; | ||
808 | force_dequeue(r8a66597, 0, dev->address); | ||
809 | } | ||
810 | |||
811 | r8a66597->pipe_cnt[pipenum] -= dev->pipe_cnt[pipenum]; | ||
812 | dev->pipe_cnt[pipenum] = 0; | ||
813 | force_dequeue(r8a66597, pipenum, dev->address); | ||
814 | } | ||
815 | |||
816 | dbg("disable_pipe"); | ||
817 | |||
818 | r8a66597->dma_map &= ~(dev->dma_map); | ||
819 | dev->dma_map = 0; | ||
820 | } | ||
821 | |||
822 | /* this function must be called with interrupt disabled */ | ||
823 | static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, | ||
824 | struct usb_host_endpoint *hep, | ||
825 | struct usb_endpoint_descriptor *ep) | ||
826 | { | ||
827 | struct r8a66597_pipe_info info; | ||
828 | |||
829 | info.pipenum = get_empty_pipenum(r8a66597, ep); | ||
830 | info.address = get_urb_to_r8a66597_addr(r8a66597, urb); | ||
831 | info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | ||
832 | info.maxpacket = ep->wMaxPacketSize; | ||
833 | info.type = get_r8a66597_type(ep->bmAttributes | ||
834 | & USB_ENDPOINT_XFERTYPE_MASK); | ||
835 | info.bufnum = get_bufnum(info.pipenum); | ||
836 | info.buf_bsize = get_buf_bsize(info.pipenum); | ||
837 | info.interval = ep->bInterval; | ||
838 | if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) | ||
839 | info.dir_in = 1; | ||
840 | else | ||
841 | info.dir_in = 0; | ||
842 | |||
843 | enable_r8a66597_pipe(r8a66597, urb, hep, &info); | ||
844 | } | ||
845 | |||
846 | static void init_pipe_config(struct r8a66597 *r8a66597, struct urb *urb) | ||
847 | { | ||
848 | struct r8a66597_device *dev; | ||
849 | |||
850 | dev = get_urb_to_r8a66597_dev(r8a66597, urb); | ||
851 | dev->state = USB_STATE_CONFIGURED; | ||
852 | } | ||
853 | |||
854 | static void pipe_irq_enable(struct r8a66597 *r8a66597, struct urb *urb, | ||
855 | u16 pipenum) | ||
856 | { | ||
857 | if (pipenum == 0 && usb_pipeout(urb->pipe)) | ||
858 | enable_irq_empty(r8a66597, pipenum); | ||
859 | else | ||
860 | enable_irq_ready(r8a66597, pipenum); | ||
861 | |||
862 | if (!usb_pipeisoc(urb->pipe)) | ||
863 | enable_irq_nrdy(r8a66597, pipenum); | ||
864 | } | ||
865 | |||
866 | static void pipe_irq_disable(struct r8a66597 *r8a66597, u16 pipenum) | ||
867 | { | ||
868 | disable_irq_ready(r8a66597, pipenum); | ||
869 | disable_irq_nrdy(r8a66597, pipenum); | ||
870 | } | ||
871 | |||
872 | /* this function must be called with interrupt disabled */ | ||
873 | static void r8a66597_usb_preconnect(struct r8a66597 *r8a66597, int port) | ||
874 | { | ||
875 | r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_CONNECTION) | ||
876 | | (1 << USB_PORT_FEAT_C_CONNECTION); | ||
877 | r8a66597_write(r8a66597, (u16)~DTCH, get_intsts_reg(port)); | ||
878 | r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); | ||
879 | } | ||
880 | |||
881 | /* this function must be called with interrupt disabled */ | ||
882 | static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port) | ||
883 | { | ||
884 | u16 speed = get_rh_usb_speed(r8a66597, port); | ||
885 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
886 | |||
887 | if (speed == HSMODE) | ||
888 | rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED); | ||
889 | else if (speed == LSMODE) | ||
890 | rh->port |= (1 << USB_PORT_FEAT_LOWSPEED); | ||
891 | |||
892 | rh->port &= ~(1 << USB_PORT_FEAT_RESET); | ||
893 | rh->port |= 1 << USB_PORT_FEAT_ENABLE; | ||
894 | } | ||
895 | |||
896 | /* this function must be called with interrupt disabled */ | ||
897 | static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port) | ||
898 | { | ||
899 | struct r8a66597_device *dev = r8a66597->root_hub[port].dev; | ||
900 | |||
901 | r8a66597->root_hub[port].port &= ~(1 << USB_PORT_FEAT_CONNECTION); | ||
902 | r8a66597->root_hub[port].port |= (1 << USB_PORT_FEAT_C_CONNECTION); | ||
903 | |||
904 | disable_r8a66597_pipe_all(r8a66597, dev); | ||
905 | free_usb_address(r8a66597, dev); | ||
906 | |||
907 | r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port)); | ||
908 | } | ||
909 | |||
910 | /* this function must be called with interrupt disabled */ | ||
911 | static void prepare_setup_packet(struct r8a66597 *r8a66597, | ||
912 | struct r8a66597_td *td) | ||
913 | { | ||
914 | int i; | ||
915 | u16 *p = (u16 *)td->urb->setup_packet; | ||
916 | unsigned long setup_addr = USBREQ; | ||
917 | |||
918 | r8a66597_write(r8a66597, make_devsel(td->address) | td->maxpacket, | ||
919 | DCPMAXP); | ||
920 | r8a66597_write(r8a66597, (u16)~(SIGN | SACK), INTSTS1); | ||
921 | |||
922 | for (i = 0; i < 4; i++) { | ||
923 | r8a66597_write(r8a66597, p[i], setup_addr); | ||
924 | setup_addr += 2; | ||
925 | } | ||
926 | r8a66597_write(r8a66597, SUREQ, DCPCTR); | ||
927 | } | ||
928 | |||
929 | /* this function must be called with interrupt disabled */ | ||
930 | static void prepare_packet_read(struct r8a66597 *r8a66597, | ||
931 | struct r8a66597_td *td) | ||
932 | { | ||
933 | struct urb *urb = td->urb; | ||
934 | |||
935 | if (usb_pipecontrol(urb->pipe)) { | ||
936 | r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); | ||
937 | r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); | ||
938 | r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); | ||
939 | if (urb->actual_length == 0) { | ||
940 | r8a66597_pipe_toggle(r8a66597, td->pipe, 1); | ||
941 | r8a66597_write(r8a66597, BCLR, CFIFOCTR); | ||
942 | } | ||
943 | pipe_irq_disable(r8a66597, td->pipenum); | ||
944 | pipe_start(r8a66597, td->pipe); | ||
945 | pipe_irq_enable(r8a66597, urb, td->pipenum); | ||
946 | } else { | ||
947 | if (urb->actual_length == 0) { | ||
948 | pipe_irq_disable(r8a66597, td->pipenum); | ||
949 | pipe_setting(r8a66597, td); | ||
950 | pipe_stop(r8a66597, td->pipe); | ||
951 | r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), | ||
952 | BRDYSTS); | ||
953 | |||
954 | if (td->pipe->pipetre) { | ||
955 | r8a66597_write(r8a66597, TRCLR, | ||
956 | td->pipe->pipetre); | ||
957 | r8a66597_write(r8a66597, | ||
958 | (urb->transfer_buffer_length | ||
959 | + td->maxpacket - 1) | ||
960 | / td->maxpacket, | ||
961 | td->pipe->pipetrn); | ||
962 | r8a66597_bset(r8a66597, TRENB, | ||
963 | td->pipe->pipetre); | ||
964 | } | ||
965 | |||
966 | pipe_start(r8a66597, td->pipe); | ||
967 | pipe_irq_enable(r8a66597, urb, td->pipenum); | ||
968 | } | ||
969 | } | ||
970 | } | ||
971 | |||
972 | /* this function must be called with interrupt disabled */ | ||
973 | static void prepare_packet_write(struct r8a66597 *r8a66597, | ||
974 | struct r8a66597_td *td) | ||
975 | { | ||
976 | u16 tmp; | ||
977 | struct urb *urb = td->urb; | ||
978 | |||
979 | if (usb_pipecontrol(urb->pipe)) { | ||
980 | pipe_stop(r8a66597, td->pipe); | ||
981 | r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG); | ||
982 | r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL); | ||
983 | r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); | ||
984 | if (urb->actual_length == 0) { | ||
985 | r8a66597_pipe_toggle(r8a66597, td->pipe, 1); | ||
986 | r8a66597_write(r8a66597, BCLR, CFIFOCTR); | ||
987 | } | ||
988 | } else { | ||
989 | if (urb->actual_length == 0) | ||
990 | pipe_setting(r8a66597, td); | ||
991 | if (td->pipe->pipetre) | ||
992 | r8a66597_bclr(r8a66597, TRENB, td->pipe->pipetre); | ||
993 | } | ||
994 | r8a66597_write(r8a66597, (u16)~(1 << td->pipenum), BRDYSTS); | ||
995 | |||
996 | fifo_change_from_pipe(r8a66597, td->pipe); | ||
997 | tmp = r8a66597_read(r8a66597, td->pipe->fifoctr); | ||
998 | if (unlikely((tmp & FRDY) == 0)) | ||
999 | pipe_irq_enable(r8a66597, urb, td->pipenum); | ||
1000 | else | ||
1001 | packet_write(r8a66597, td->pipenum); | ||
1002 | pipe_start(r8a66597, td->pipe); | ||
1003 | } | ||
1004 | |||
1005 | /* this function must be called with interrupt disabled */ | ||
1006 | static void prepare_status_packet(struct r8a66597 *r8a66597, | ||
1007 | struct r8a66597_td *td) | ||
1008 | { | ||
1009 | struct urb *urb = td->urb; | ||
1010 | |||
1011 | r8a66597_pipe_toggle(r8a66597, td->pipe, 1); | ||
1012 | |||
1013 | if (urb->setup_packet[0] & USB_ENDPOINT_DIR_MASK) { | ||
1014 | r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG); | ||
1015 | r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL); | ||
1016 | r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); | ||
1017 | r8a66597_write(r8a66597, BVAL | BCLR, CFIFOCTR); | ||
1018 | r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS); | ||
1019 | enable_irq_empty(r8a66597, 0); | ||
1020 | } else { | ||
1021 | r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); | ||
1022 | r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); | ||
1023 | r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); | ||
1024 | r8a66597_write(r8a66597, BCLR, CFIFOCTR); | ||
1025 | r8a66597_write(r8a66597, (u16)~BRDY0, BRDYSTS); | ||
1026 | r8a66597_write(r8a66597, (u16)~BEMP0, BEMPSTS); | ||
1027 | enable_irq_ready(r8a66597, 0); | ||
1028 | } | ||
1029 | enable_irq_nrdy(r8a66597, 0); | ||
1030 | pipe_start(r8a66597, td->pipe); | ||
1031 | } | ||
1032 | |||
1033 | /* this function must be called with interrupt disabled */ | ||
1034 | static int start_transfer(struct r8a66597 *r8a66597, struct r8a66597_td *td) | ||
1035 | { | ||
1036 | BUG_ON(!td); | ||
1037 | |||
1038 | switch (td->type) { | ||
1039 | case USB_PID_SETUP: | ||
1040 | if (td->urb->setup_packet[1] == USB_REQ_SET_ADDRESS) { | ||
1041 | td->set_address = 1; | ||
1042 | td->urb->setup_packet[2] = alloc_usb_address(r8a66597, | ||
1043 | td->urb); | ||
1044 | if (td->urb->setup_packet[2] == 0) | ||
1045 | return -EPIPE; | ||
1046 | } | ||
1047 | prepare_setup_packet(r8a66597, td); | ||
1048 | break; | ||
1049 | case USB_PID_IN: | ||
1050 | prepare_packet_read(r8a66597, td); | ||
1051 | break; | ||
1052 | case USB_PID_OUT: | ||
1053 | prepare_packet_write(r8a66597, td); | ||
1054 | break; | ||
1055 | case USB_PID_ACK: | ||
1056 | prepare_status_packet(r8a66597, td); | ||
1057 | break; | ||
1058 | default: | ||
1059 | err("invalid type."); | ||
1060 | break; | ||
1061 | } | ||
1062 | |||
1063 | return 0; | ||
1064 | } | ||
1065 | |||
1066 | static int check_transfer_finish(struct r8a66597_td *td, struct urb *urb) | ||
1067 | { | ||
1068 | if (usb_pipeisoc(urb->pipe)) { | ||
1069 | if (urb->number_of_packets == td->iso_cnt) | ||
1070 | return 1; | ||
1071 | } | ||
1072 | |||
1073 | /* control or bulk or interrupt */ | ||
1074 | if ((urb->transfer_buffer_length <= urb->actual_length) || | ||
1075 | (td->short_packet) || (td->zero_packet)) | ||
1076 | return 1; | ||
1077 | |||
1078 | return 0; | ||
1079 | } | ||
1080 | |||
1081 | /* this function must be called with interrupt disabled */ | ||
1082 | static void set_td_timer(struct r8a66597 *r8a66597, struct r8a66597_td *td) | ||
1083 | { | ||
1084 | unsigned long time; | ||
1085 | |||
1086 | BUG_ON(!td); | ||
1087 | |||
1088 | if (!list_empty(&r8a66597->pipe_queue[td->pipenum]) && | ||
1089 | !usb_pipecontrol(td->urb->pipe) && usb_pipein(td->urb->pipe)) { | ||
1090 | r8a66597->timeout_map |= 1 << td->pipenum; | ||
1091 | switch (usb_pipetype(td->urb->pipe)) { | ||
1092 | case PIPE_INTERRUPT: | ||
1093 | case PIPE_ISOCHRONOUS: | ||
1094 | time = 30; | ||
1095 | break; | ||
1096 | default: | ||
1097 | time = 300; | ||
1098 | break; | ||
1099 | } | ||
1100 | |||
1101 | mod_timer(&r8a66597->td_timer[td->pipenum], | ||
1102 | jiffies + msecs_to_jiffies(time)); | ||
1103 | } | ||
1104 | } | ||
1105 | |||
1106 | /* this function must be called with interrupt disabled */ | ||
1107 | static void done(struct r8a66597 *r8a66597, struct r8a66597_td *td, | ||
1108 | u16 pipenum, struct urb *urb) | ||
1109 | { | ||
1110 | int restart = 0; | ||
1111 | struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); | ||
1112 | |||
1113 | r8a66597->timeout_map &= ~(1 << pipenum); | ||
1114 | |||
1115 | if (likely(td)) { | ||
1116 | if (td->set_address && urb->status != 0) | ||
1117 | r8a66597->address_map &= ~(1 << urb->setup_packet[2]); | ||
1118 | |||
1119 | pipe_toggle_save(r8a66597, td->pipe, urb); | ||
1120 | list_del(&td->queue); | ||
1121 | kfree(td); | ||
1122 | } | ||
1123 | |||
1124 | if (!list_empty(&r8a66597->pipe_queue[pipenum])) | ||
1125 | restart = 1; | ||
1126 | |||
1127 | if (likely(urb)) { | ||
1128 | if (usb_pipeisoc(urb->pipe)) | ||
1129 | urb->start_frame = r8a66597_get_frame(hcd); | ||
1130 | |||
1131 | urb->hcpriv = NULL; | ||
1132 | spin_unlock(&r8a66597->lock); | ||
1133 | usb_hcd_giveback_urb(hcd, urb); | ||
1134 | spin_lock(&r8a66597->lock); | ||
1135 | } | ||
1136 | |||
1137 | if (restart) { | ||
1138 | td = r8a66597_get_td(r8a66597, pipenum); | ||
1139 | if (unlikely(!td)) | ||
1140 | return; | ||
1141 | |||
1142 | start_transfer(r8a66597, td); | ||
1143 | set_td_timer(r8a66597, td); | ||
1144 | } | ||
1145 | } | ||
1146 | |||
1147 | /* this function must be called with interrupt disabled */ | ||
1148 | static void finish_request(struct r8a66597 *r8a66597, struct r8a66597_td *td, | ||
1149 | u16 pipenum, struct urb *urb) | ||
1150 | __releases(r8a66597->lock) __acquires(r8a66597->lock) | ||
1151 | { | ||
1152 | done(r8a66597, td, pipenum, urb); | ||
1153 | } | ||
1154 | |||
1155 | static void packet_read(struct r8a66597 *r8a66597, u16 pipenum) | ||
1156 | { | ||
1157 | u16 tmp; | ||
1158 | int rcv_len, bufsize, urb_len, size; | ||
1159 | u16 *buf; | ||
1160 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum); | ||
1161 | struct urb *urb; | ||
1162 | int finish = 0; | ||
1163 | |||
1164 | if (unlikely(!td)) | ||
1165 | return; | ||
1166 | urb = td->urb; | ||
1167 | |||
1168 | fifo_change_from_pipe(r8a66597, td->pipe); | ||
1169 | tmp = r8a66597_read(r8a66597, td->pipe->fifoctr); | ||
1170 | if (unlikely((tmp & FRDY) == 0)) { | ||
1171 | urb->status = -EPIPE; | ||
1172 | pipe_stop(r8a66597, td->pipe); | ||
1173 | pipe_irq_disable(r8a66597, pipenum); | ||
1174 | err("in fifo not ready (%d)", pipenum); | ||
1175 | finish_request(r8a66597, td, pipenum, td->urb); | ||
1176 | return; | ||
1177 | } | ||
1178 | |||
1179 | /* prepare parameters */ | ||
1180 | rcv_len = tmp & DTLN; | ||
1181 | bufsize = td->maxpacket; | ||
1182 | if (usb_pipeisoc(urb->pipe)) { | ||
1183 | buf = (u16 *)(urb->transfer_buffer + | ||
1184 | urb->iso_frame_desc[td->iso_cnt].offset); | ||
1185 | urb_len = urb->iso_frame_desc[td->iso_cnt].length; | ||
1186 | } else { | ||
1187 | buf = (void *)urb->transfer_buffer + urb->actual_length; | ||
1188 | urb_len = urb->transfer_buffer_length - urb->actual_length; | ||
1189 | } | ||
1190 | if (rcv_len < bufsize) | ||
1191 | size = min(rcv_len, urb_len); | ||
1192 | else | ||
1193 | size = min(bufsize, urb_len); | ||
1194 | |||
1195 | /* update parameters */ | ||
1196 | urb->actual_length += size; | ||
1197 | if (rcv_len == 0) | ||
1198 | td->zero_packet = 1; | ||
1199 | if ((size % td->maxpacket) > 0) { | ||
1200 | td->short_packet = 1; | ||
1201 | if (urb->transfer_buffer_length != urb->actual_length && | ||
1202 | urb->transfer_flags & URB_SHORT_NOT_OK) | ||
1203 | td->urb->status = -EREMOTEIO; | ||
1204 | } | ||
1205 | if (usb_pipeisoc(urb->pipe)) { | ||
1206 | urb->iso_frame_desc[td->iso_cnt].actual_length = size; | ||
1207 | urb->iso_frame_desc[td->iso_cnt].status = 0; | ||
1208 | td->iso_cnt++; | ||
1209 | } | ||
1210 | |||
1211 | /* check transfer finish */ | ||
1212 | if (check_transfer_finish(td, urb)) { | ||
1213 | pipe_stop(r8a66597, td->pipe); | ||
1214 | pipe_irq_disable(r8a66597, pipenum); | ||
1215 | finish = 1; | ||
1216 | } | ||
1217 | |||
1218 | /* read fifo */ | ||
1219 | if (urb->transfer_buffer) { | ||
1220 | if (size == 0) | ||
1221 | r8a66597_write(r8a66597, BCLR, td->pipe->fifoctr); | ||
1222 | else | ||
1223 | r8a66597_read_fifo(r8a66597, td->pipe->fifoaddr, | ||
1224 | buf, size); | ||
1225 | } | ||
1226 | |||
1227 | if (finish && pipenum != 0) { | ||
1228 | if (td->urb->status == -EINPROGRESS) | ||
1229 | td->urb->status = 0; | ||
1230 | finish_request(r8a66597, td, pipenum, urb); | ||
1231 | } | ||
1232 | } | ||
1233 | |||
1234 | static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) | ||
1235 | { | ||
1236 | u16 tmp; | ||
1237 | int bufsize, size; | ||
1238 | u16 *buf; | ||
1239 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum); | ||
1240 | struct urb *urb; | ||
1241 | |||
1242 | if (unlikely(!td)) | ||
1243 | return; | ||
1244 | urb = td->urb; | ||
1245 | |||
1246 | fifo_change_from_pipe(r8a66597, td->pipe); | ||
1247 | tmp = r8a66597_read(r8a66597, td->pipe->fifoctr); | ||
1248 | if (unlikely((tmp & FRDY) == 0)) { | ||
1249 | urb->status = -EPIPE; | ||
1250 | pipe_stop(r8a66597, td->pipe); | ||
1251 | pipe_irq_disable(r8a66597, pipenum); | ||
1252 | err("out write fifo not ready. (%d)", pipenum); | ||
1253 | finish_request(r8a66597, td, pipenum, td->urb); | ||
1254 | return; | ||
1255 | } | ||
1256 | |||
1257 | /* prepare parameters */ | ||
1258 | bufsize = td->maxpacket; | ||
1259 | if (usb_pipeisoc(urb->pipe)) { | ||
1260 | buf = (u16 *)(urb->transfer_buffer + | ||
1261 | urb->iso_frame_desc[td->iso_cnt].offset); | ||
1262 | size = min(bufsize, | ||
1263 | (int)urb->iso_frame_desc[td->iso_cnt].length); | ||
1264 | } else { | ||
1265 | buf = (u16 *)(urb->transfer_buffer + urb->actual_length); | ||
1266 | size = min((int)bufsize, | ||
1267 | urb->transfer_buffer_length - urb->actual_length); | ||
1268 | } | ||
1269 | |||
1270 | /* write fifo */ | ||
1271 | if (pipenum > 0) | ||
1272 | r8a66597_write(r8a66597, (u16)~(1 << pipenum), BEMPSTS); | ||
1273 | if (urb->transfer_buffer) { | ||
1274 | r8a66597_write_fifo(r8a66597, td->pipe->fifoaddr, buf, size); | ||
1275 | if (!usb_pipebulk(urb->pipe) || td->maxpacket != size) | ||
1276 | r8a66597_write(r8a66597, BVAL, td->pipe->fifoctr); | ||
1277 | } | ||
1278 | |||
1279 | /* update parameters */ | ||
1280 | urb->actual_length += size; | ||
1281 | if (usb_pipeisoc(urb->pipe)) { | ||
1282 | urb->iso_frame_desc[td->iso_cnt].actual_length = size; | ||
1283 | urb->iso_frame_desc[td->iso_cnt].status = 0; | ||
1284 | td->iso_cnt++; | ||
1285 | } | ||
1286 | |||
1287 | /* check transfer finish */ | ||
1288 | if (check_transfer_finish(td, urb)) { | ||
1289 | disable_irq_ready(r8a66597, pipenum); | ||
1290 | enable_irq_empty(r8a66597, pipenum); | ||
1291 | if (!usb_pipeisoc(urb->pipe)) | ||
1292 | enable_irq_nrdy(r8a66597, pipenum); | ||
1293 | } else | ||
1294 | pipe_irq_enable(r8a66597, urb, pipenum); | ||
1295 | } | ||
1296 | |||
1297 | |||
1298 | static void check_next_phase(struct r8a66597 *r8a66597) | ||
1299 | { | ||
1300 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, 0); | ||
1301 | struct urb *urb; | ||
1302 | u8 finish = 0; | ||
1303 | |||
1304 | if (unlikely(!td)) | ||
1305 | return; | ||
1306 | urb = td->urb; | ||
1307 | |||
1308 | switch (td->type) { | ||
1309 | case USB_PID_IN: | ||
1310 | case USB_PID_OUT: | ||
1311 | if (urb->status != -EINPROGRESS) { | ||
1312 | finish = 1; | ||
1313 | break; | ||
1314 | } | ||
1315 | if (check_transfer_finish(td, urb)) | ||
1316 | td->type = USB_PID_ACK; | ||
1317 | break; | ||
1318 | case USB_PID_SETUP: | ||
1319 | if (urb->status != -EINPROGRESS) | ||
1320 | finish = 1; | ||
1321 | else if (urb->transfer_buffer_length == urb->actual_length) { | ||
1322 | td->type = USB_PID_ACK; | ||
1323 | urb->status = 0; | ||
1324 | } else if (usb_pipeout(urb->pipe)) | ||
1325 | td->type = USB_PID_OUT; | ||
1326 | else | ||
1327 | td->type = USB_PID_IN; | ||
1328 | break; | ||
1329 | case USB_PID_ACK: | ||
1330 | finish = 1; | ||
1331 | if (urb->status == -EINPROGRESS) | ||
1332 | urb->status = 0; | ||
1333 | break; | ||
1334 | } | ||
1335 | |||
1336 | if (finish) | ||
1337 | finish_request(r8a66597, td, 0, urb); | ||
1338 | else | ||
1339 | start_transfer(r8a66597, td); | ||
1340 | } | ||
1341 | |||
1342 | static void set_urb_error(struct r8a66597 *r8a66597, u16 pipenum) | ||
1343 | { | ||
1344 | struct r8a66597_td *td = r8a66597_get_td(r8a66597, pipenum); | ||
1345 | |||
1346 | if (td && td->urb) { | ||
1347 | u16 pid = r8a66597_read(r8a66597, td->pipe->pipectr) & PID; | ||
1348 | |||
1349 | if (pid == PID_NAK) | ||
1350 | td->urb->status = -ECONNRESET; | ||
1351 | else | ||
1352 | td->urb->status = -EPIPE; | ||
1353 | } | ||
1354 | } | ||
1355 | |||
1356 | static void irq_pipe_ready(struct r8a66597 *r8a66597) | ||
1357 | { | ||
1358 | u16 check; | ||
1359 | u16 pipenum; | ||
1360 | u16 mask; | ||
1361 | struct r8a66597_td *td; | ||
1362 | |||
1363 | mask = r8a66597_read(r8a66597, BRDYSTS) | ||
1364 | & r8a66597_read(r8a66597, BRDYENB); | ||
1365 | r8a66597_write(r8a66597, (u16)~mask, BRDYSTS); | ||
1366 | if (mask & BRDY0) { | ||
1367 | td = r8a66597_get_td(r8a66597, 0); | ||
1368 | if (td && td->type == USB_PID_IN) | ||
1369 | packet_read(r8a66597, 0); | ||
1370 | else | ||
1371 | pipe_irq_disable(r8a66597, 0); | ||
1372 | check_next_phase(r8a66597); | ||
1373 | } | ||
1374 | |||
1375 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | ||
1376 | check = 1 << pipenum; | ||
1377 | if (mask & check) { | ||
1378 | td = r8a66597_get_td(r8a66597, pipenum); | ||
1379 | if (unlikely(!td)) | ||
1380 | continue; | ||
1381 | |||
1382 | if (td->type == USB_PID_IN) | ||
1383 | packet_read(r8a66597, pipenum); | ||
1384 | else if (td->type == USB_PID_OUT) | ||
1385 | packet_write(r8a66597, pipenum); | ||
1386 | } | ||
1387 | } | ||
1388 | } | ||
1389 | |||
1390 | static void irq_pipe_empty(struct r8a66597 *r8a66597) | ||
1391 | { | ||
1392 | u16 tmp; | ||
1393 | u16 check; | ||
1394 | u16 pipenum; | ||
1395 | u16 mask; | ||
1396 | struct r8a66597_td *td; | ||
1397 | |||
1398 | mask = r8a66597_read(r8a66597, BEMPSTS) | ||
1399 | & r8a66597_read(r8a66597, BEMPENB); | ||
1400 | r8a66597_write(r8a66597, (u16)~mask, BEMPSTS); | ||
1401 | if (mask & BEMP0) { | ||
1402 | cfifo_change(r8a66597, 0); | ||
1403 | td = r8a66597_get_td(r8a66597, 0); | ||
1404 | if (td && td->type != USB_PID_OUT) | ||
1405 | disable_irq_empty(r8a66597, 0); | ||
1406 | check_next_phase(r8a66597); | ||
1407 | } | ||
1408 | |||
1409 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | ||
1410 | check = 1 << pipenum; | ||
1411 | if (mask & check) { | ||
1412 | struct r8a66597_td *td; | ||
1413 | td = r8a66597_get_td(r8a66597, pipenum); | ||
1414 | if (unlikely(!td)) | ||
1415 | continue; | ||
1416 | |||
1417 | tmp = r8a66597_read(r8a66597, td->pipe->pipectr); | ||
1418 | if ((tmp & INBUFM) == 0) { | ||
1419 | disable_irq_empty(r8a66597, pipenum); | ||
1420 | pipe_irq_disable(r8a66597, pipenum); | ||
1421 | if (td->urb->status == -EINPROGRESS) | ||
1422 | td->urb->status = 0; | ||
1423 | finish_request(r8a66597, td, pipenum, td->urb); | ||
1424 | } | ||
1425 | } | ||
1426 | } | ||
1427 | } | ||
1428 | |||
1429 | static void irq_pipe_nrdy(struct r8a66597 *r8a66597) | ||
1430 | { | ||
1431 | u16 check; | ||
1432 | u16 pipenum; | ||
1433 | u16 mask; | ||
1434 | |||
1435 | mask = r8a66597_read(r8a66597, NRDYSTS) | ||
1436 | & r8a66597_read(r8a66597, NRDYENB); | ||
1437 | r8a66597_write(r8a66597, (u16)~mask, NRDYSTS); | ||
1438 | if (mask & NRDY0) { | ||
1439 | cfifo_change(r8a66597, 0); | ||
1440 | set_urb_error(r8a66597, 0); | ||
1441 | pipe_irq_disable(r8a66597, 0); | ||
1442 | check_next_phase(r8a66597); | ||
1443 | } | ||
1444 | |||
1445 | for (pipenum = 1; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | ||
1446 | check = 1 << pipenum; | ||
1447 | if (mask & check) { | ||
1448 | struct r8a66597_td *td; | ||
1449 | td = r8a66597_get_td(r8a66597, pipenum); | ||
1450 | if (unlikely(!td)) | ||
1451 | continue; | ||
1452 | |||
1453 | set_urb_error(r8a66597, pipenum); | ||
1454 | pipe_irq_disable(r8a66597, pipenum); | ||
1455 | pipe_stop(r8a66597, td->pipe); | ||
1456 | finish_request(r8a66597, td, pipenum, td->urb); | ||
1457 | } | ||
1458 | } | ||
1459 | } | ||
1460 | |||
1461 | static void start_root_hub_sampling(struct r8a66597 *r8a66597, int port) | ||
1462 | { | ||
1463 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
1464 | |||
1465 | rh->old_syssts = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST; | ||
1466 | rh->scount = R8A66597_MAX_SAMPLING; | ||
1467 | mod_timer(&r8a66597->rh_timer, jiffies + msecs_to_jiffies(50)); | ||
1468 | } | ||
1469 | |||
1470 | static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) | ||
1471 | { | ||
1472 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
1473 | u16 intsts0, intsts1, intsts2; | ||
1474 | u16 intenb0, intenb1, intenb2; | ||
1475 | u16 mask0, mask1, mask2; | ||
1476 | |||
1477 | spin_lock(&r8a66597->lock); | ||
1478 | |||
1479 | intsts0 = r8a66597_read(r8a66597, INTSTS0); | ||
1480 | intsts1 = r8a66597_read(r8a66597, INTSTS1); | ||
1481 | intsts2 = r8a66597_read(r8a66597, INTSTS2); | ||
1482 | intenb0 = r8a66597_read(r8a66597, INTENB0); | ||
1483 | intenb1 = r8a66597_read(r8a66597, INTENB1); | ||
1484 | intenb2 = r8a66597_read(r8a66597, INTENB2); | ||
1485 | |||
1486 | mask2 = intsts2 & intenb2; | ||
1487 | mask1 = intsts1 & intenb1; | ||
1488 | mask0 = intsts0 & intenb0 & (BEMP | NRDY | BRDY); | ||
1489 | if (mask2) { | ||
1490 | if (mask2 & ATTCH) { | ||
1491 | r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS2); | ||
1492 | r8a66597_bclr(r8a66597, ATTCHE, INTENB2); | ||
1493 | |||
1494 | /* start usb bus sampling */ | ||
1495 | start_root_hub_sampling(r8a66597, 1); | ||
1496 | } | ||
1497 | if (mask2 & DTCH) { | ||
1498 | r8a66597_write(r8a66597, (u16)~DTCH, INTSTS2); | ||
1499 | r8a66597_bclr(r8a66597, DTCHE, INTENB2); | ||
1500 | r8a66597_usb_disconnect(r8a66597, 1); | ||
1501 | } | ||
1502 | } | ||
1503 | |||
1504 | if (mask1) { | ||
1505 | if (mask1 & ATTCH) { | ||
1506 | r8a66597_write(r8a66597, (u16)~ATTCH, INTSTS1); | ||
1507 | r8a66597_bclr(r8a66597, ATTCHE, INTENB1); | ||
1508 | |||
1509 | /* start usb bus sampling */ | ||
1510 | start_root_hub_sampling(r8a66597, 0); | ||
1511 | } | ||
1512 | if (mask1 & DTCH) { | ||
1513 | r8a66597_write(r8a66597, (u16)~DTCH, INTSTS1); | ||
1514 | r8a66597_bclr(r8a66597, DTCHE, INTENB1); | ||
1515 | r8a66597_usb_disconnect(r8a66597, 0); | ||
1516 | } | ||
1517 | if (mask1 & SIGN) { | ||
1518 | r8a66597_write(r8a66597, (u16)~SIGN, INTSTS1); | ||
1519 | set_urb_error(r8a66597, 0); | ||
1520 | check_next_phase(r8a66597); | ||
1521 | } | ||
1522 | if (mask1 & SACK) { | ||
1523 | r8a66597_write(r8a66597, (u16)~SACK, INTSTS1); | ||
1524 | check_next_phase(r8a66597); | ||
1525 | } | ||
1526 | } | ||
1527 | if (mask0) { | ||
1528 | if (mask0 & BRDY) | ||
1529 | irq_pipe_ready(r8a66597); | ||
1530 | if (mask0 & BEMP) | ||
1531 | irq_pipe_empty(r8a66597); | ||
1532 | if (mask0 & NRDY) | ||
1533 | irq_pipe_nrdy(r8a66597); | ||
1534 | } | ||
1535 | |||
1536 | spin_unlock(&r8a66597->lock); | ||
1537 | return IRQ_HANDLED; | ||
1538 | } | ||
1539 | |||
1540 | /* this function must be called with interrupt disabled */ | ||
1541 | static void r8a66597_root_hub_control(struct r8a66597 *r8a66597, int port) | ||
1542 | { | ||
1543 | u16 tmp; | ||
1544 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
1545 | |||
1546 | if (rh->port & (1 << USB_PORT_FEAT_RESET)) { | ||
1547 | unsigned long dvstctr_reg = get_dvstctr_reg(port); | ||
1548 | |||
1549 | tmp = r8a66597_read(r8a66597, dvstctr_reg); | ||
1550 | if ((tmp & USBRST) == USBRST) { | ||
1551 | r8a66597_mdfy(r8a66597, UACT, USBRST | UACT, | ||
1552 | dvstctr_reg); | ||
1553 | mod_timer(&r8a66597->rh_timer, | ||
1554 | jiffies + msecs_to_jiffies(50)); | ||
1555 | } else | ||
1556 | r8a66597_usb_connect(r8a66597, port); | ||
1557 | } | ||
1558 | |||
1559 | if (rh->scount > 0) { | ||
1560 | tmp = r8a66597_read(r8a66597, get_syssts_reg(port)) & LNST; | ||
1561 | if (tmp == rh->old_syssts) { | ||
1562 | rh->scount--; | ||
1563 | if (rh->scount == 0) { | ||
1564 | if (tmp == FS_JSTS) { | ||
1565 | r8a66597_bset(r8a66597, HSE, | ||
1566 | get_syscfg_reg(port)); | ||
1567 | r8a66597_usb_preconnect(r8a66597, port); | ||
1568 | } else if (tmp == LS_JSTS) { | ||
1569 | r8a66597_bclr(r8a66597, HSE, | ||
1570 | get_syscfg_reg(port)); | ||
1571 | r8a66597_usb_preconnect(r8a66597, port); | ||
1572 | } else if (tmp == SE0) | ||
1573 | r8a66597_bset(r8a66597, ATTCHE, | ||
1574 | get_intenb_reg(port)); | ||
1575 | } else { | ||
1576 | mod_timer(&r8a66597->rh_timer, | ||
1577 | jiffies + msecs_to_jiffies(50)); | ||
1578 | } | ||
1579 | } else { | ||
1580 | rh->scount = R8A66597_MAX_SAMPLING; | ||
1581 | rh->old_syssts = tmp; | ||
1582 | mod_timer(&r8a66597->rh_timer, | ||
1583 | jiffies + msecs_to_jiffies(50)); | ||
1584 | } | ||
1585 | } | ||
1586 | } | ||
1587 | |||
1588 | static void r8a66597_td_timer(unsigned long _r8a66597) | ||
1589 | { | ||
1590 | struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; | ||
1591 | unsigned long flags; | ||
1592 | u16 pipenum; | ||
1593 | struct r8a66597_td *td, *new_td = NULL; | ||
1594 | struct r8a66597_pipe *pipe; | ||
1595 | |||
1596 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1597 | for (pipenum = 0; pipenum < R8A66597_MAX_NUM_PIPE; pipenum++) { | ||
1598 | if (!(r8a66597->timeout_map & (1 << pipenum))) | ||
1599 | continue; | ||
1600 | if (timer_pending(&r8a66597->td_timer[pipenum])) | ||
1601 | continue; | ||
1602 | |||
1603 | td = r8a66597_get_td(r8a66597, pipenum); | ||
1604 | if (!td) { | ||
1605 | r8a66597->timeout_map &= ~(1 << pipenum); | ||
1606 | continue; | ||
1607 | } | ||
1608 | |||
1609 | if (td->urb->actual_length) { | ||
1610 | set_td_timer(r8a66597, td); | ||
1611 | break; | ||
1612 | } | ||
1613 | |||
1614 | pipe = td->pipe; | ||
1615 | pipe_stop(r8a66597, pipe); | ||
1616 | |||
1617 | new_td = td; | ||
1618 | do { | ||
1619 | list_move_tail(&new_td->queue, | ||
1620 | &r8a66597->pipe_queue[pipenum]); | ||
1621 | new_td = r8a66597_get_td(r8a66597, pipenum); | ||
1622 | if (!new_td) { | ||
1623 | new_td = td; | ||
1624 | break; | ||
1625 | } | ||
1626 | } while (td != new_td && td->address == new_td->address); | ||
1627 | |||
1628 | start_transfer(r8a66597, new_td); | ||
1629 | |||
1630 | if (td == new_td) | ||
1631 | r8a66597->timeout_map &= ~(1 << pipenum); | ||
1632 | else | ||
1633 | set_td_timer(r8a66597, new_td); | ||
1634 | break; | ||
1635 | } | ||
1636 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1637 | } | ||
1638 | |||
1639 | static void r8a66597_timer(unsigned long _r8a66597) | ||
1640 | { | ||
1641 | struct r8a66597 *r8a66597 = (struct r8a66597 *)_r8a66597; | ||
1642 | unsigned long flags; | ||
1643 | |||
1644 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1645 | |||
1646 | r8a66597_root_hub_control(r8a66597, 0); | ||
1647 | r8a66597_root_hub_control(r8a66597, 1); | ||
1648 | |||
1649 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1650 | } | ||
1651 | |||
1652 | static int check_pipe_config(struct r8a66597 *r8a66597, struct urb *urb) | ||
1653 | { | ||
1654 | struct r8a66597_device *dev = get_urb_to_r8a66597_dev(r8a66597, urb); | ||
1655 | |||
1656 | if (dev && dev->address && dev->state != USB_STATE_CONFIGURED && | ||
1657 | (urb->dev->state == USB_STATE_CONFIGURED)) | ||
1658 | return 1; | ||
1659 | else | ||
1660 | return 0; | ||
1661 | } | ||
1662 | |||
1663 | static int r8a66597_start(struct usb_hcd *hcd) | ||
1664 | { | ||
1665 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
1666 | int ret; | ||
1667 | |||
1668 | hcd->state = HC_STATE_RUNNING; | ||
1669 | if ((ret = enable_controller(r8a66597)) < 0) | ||
1670 | return ret; | ||
1671 | |||
1672 | return 0; | ||
1673 | } | ||
1674 | |||
1675 | static void r8a66597_stop(struct usb_hcd *hcd) | ||
1676 | { | ||
1677 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
1678 | |||
1679 | disable_controller(r8a66597); | ||
1680 | } | ||
1681 | |||
1682 | static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb) | ||
1683 | { | ||
1684 | unsigned int usb_address = usb_pipedevice(urb->pipe); | ||
1685 | u16 root_port, hub_port; | ||
1686 | |||
1687 | if (usb_address == 0) { | ||
1688 | get_port_number(urb->dev->devpath, | ||
1689 | &root_port, &hub_port); | ||
1690 | set_devadd_reg(r8a66597, 0, | ||
1691 | get_r8a66597_usb_speed(urb->dev->speed), | ||
1692 | get_parent_r8a66597_address(r8a66597, urb->dev), | ||
1693 | hub_port, root_port); | ||
1694 | } | ||
1695 | } | ||
1696 | |||
1697 | static struct r8a66597_td *r8a66597_make_td(struct r8a66597 *r8a66597, | ||
1698 | struct urb *urb, | ||
1699 | struct usb_host_endpoint *hep, | ||
1700 | gfp_t mem_flags) | ||
1701 | { | ||
1702 | struct r8a66597_td *td; | ||
1703 | u16 pipenum; | ||
1704 | |||
1705 | td = kzalloc(sizeof(struct r8a66597_td), mem_flags); | ||
1706 | if (td == NULL) | ||
1707 | return NULL; | ||
1708 | |||
1709 | pipenum = r8a66597_get_pipenum(urb, hep); | ||
1710 | td->pipenum = pipenum; | ||
1711 | td->pipe = hep->hcpriv; | ||
1712 | td->urb = urb; | ||
1713 | td->address = get_urb_to_r8a66597_addr(r8a66597, urb); | ||
1714 | td->maxpacket = usb_maxpacket(urb->dev, urb->pipe, | ||
1715 | !usb_pipein(urb->pipe)); | ||
1716 | if (usb_pipecontrol(urb->pipe)) | ||
1717 | td->type = USB_PID_SETUP; | ||
1718 | else if (usb_pipein(urb->pipe)) | ||
1719 | td->type = USB_PID_IN; | ||
1720 | else | ||
1721 | td->type = USB_PID_OUT; | ||
1722 | INIT_LIST_HEAD(&td->queue); | ||
1723 | |||
1724 | return td; | ||
1725 | } | ||
1726 | |||
1727 | static int r8a66597_urb_enqueue(struct usb_hcd *hcd, | ||
1728 | struct usb_host_endpoint *hep, | ||
1729 | struct urb *urb, | ||
1730 | gfp_t mem_flags) | ||
1731 | { | ||
1732 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
1733 | struct r8a66597_td *td = NULL; | ||
1734 | int ret = 0, request = 0; | ||
1735 | unsigned long flags; | ||
1736 | |||
1737 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1738 | if (!get_urb_to_r8a66597_dev(r8a66597, urb)) { | ||
1739 | ret = -ENODEV; | ||
1740 | goto error; | ||
1741 | } | ||
1742 | |||
1743 | if (!hep->hcpriv) { | ||
1744 | hep->hcpriv = kzalloc(sizeof(struct r8a66597_pipe), mem_flags); | ||
1745 | if (!hep->hcpriv) { | ||
1746 | ret = -ENOMEM; | ||
1747 | goto error; | ||
1748 | } | ||
1749 | set_pipe_reg_addr(hep->hcpriv, R8A66597_PIPE_NO_DMA); | ||
1750 | if (usb_pipeendpoint(urb->pipe)) | ||
1751 | init_pipe_info(r8a66597, urb, hep, &hep->desc); | ||
1752 | } | ||
1753 | |||
1754 | if (unlikely(check_pipe_config(r8a66597, urb))) | ||
1755 | init_pipe_config(r8a66597, urb); | ||
1756 | |||
1757 | set_address_zero(r8a66597, urb); | ||
1758 | td = r8a66597_make_td(r8a66597, urb, hep, mem_flags); | ||
1759 | if (td == NULL) { | ||
1760 | ret = -ENOMEM; | ||
1761 | goto error; | ||
1762 | } | ||
1763 | if (list_empty(&r8a66597->pipe_queue[td->pipenum])) | ||
1764 | request = 1; | ||
1765 | list_add_tail(&td->queue, &r8a66597->pipe_queue[td->pipenum]); | ||
1766 | |||
1767 | spin_lock(&urb->lock); | ||
1768 | if (urb->status != -EINPROGRESS) { | ||
1769 | spin_unlock(&urb->lock); | ||
1770 | ret = -EPIPE; | ||
1771 | goto error; | ||
1772 | } | ||
1773 | urb->hcpriv = td; | ||
1774 | spin_unlock(&urb->lock); | ||
1775 | |||
1776 | if (request) { | ||
1777 | ret = start_transfer(r8a66597, td); | ||
1778 | if (ret < 0) { | ||
1779 | list_del(&td->queue); | ||
1780 | kfree(td); | ||
1781 | } | ||
1782 | } else | ||
1783 | set_td_timer(r8a66597, td); | ||
1784 | |||
1785 | error: | ||
1786 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1787 | return ret; | ||
1788 | } | ||
1789 | |||
1790 | static int r8a66597_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) | ||
1791 | { | ||
1792 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
1793 | struct r8a66597_td *td; | ||
1794 | unsigned long flags; | ||
1795 | |||
1796 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1797 | if (urb->hcpriv) { | ||
1798 | td = urb->hcpriv; | ||
1799 | pipe_stop(r8a66597, td->pipe); | ||
1800 | pipe_irq_disable(r8a66597, td->pipenum); | ||
1801 | disable_irq_empty(r8a66597, td->pipenum); | ||
1802 | done(r8a66597, td, td->pipenum, urb); | ||
1803 | } | ||
1804 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1805 | return 0; | ||
1806 | } | ||
1807 | |||
1808 | static void r8a66597_endpoint_disable(struct usb_hcd *hcd, | ||
1809 | struct usb_host_endpoint *hep) | ||
1810 | { | ||
1811 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
1812 | struct r8a66597_pipe *pipe = (struct r8a66597_pipe *)hep->hcpriv; | ||
1813 | struct r8a66597_td *td; | ||
1814 | struct urb *urb = NULL; | ||
1815 | u16 pipenum; | ||
1816 | unsigned long flags; | ||
1817 | |||
1818 | if (pipe == NULL) | ||
1819 | return; | ||
1820 | pipenum = pipe->info.pipenum; | ||
1821 | |||
1822 | if (pipenum == 0) { | ||
1823 | kfree(hep->hcpriv); | ||
1824 | hep->hcpriv = NULL; | ||
1825 | return; | ||
1826 | } | ||
1827 | |||
1828 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1829 | pipe_stop(r8a66597, pipe); | ||
1830 | pipe_irq_disable(r8a66597, pipenum); | ||
1831 | disable_irq_empty(r8a66597, pipenum); | ||
1832 | td = r8a66597_get_td(r8a66597, pipenum); | ||
1833 | if (td) | ||
1834 | urb = td->urb; | ||
1835 | done(r8a66597, td, pipenum, urb); | ||
1836 | kfree(hep->hcpriv); | ||
1837 | hep->hcpriv = NULL; | ||
1838 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1839 | } | ||
1840 | |||
1841 | static int r8a66597_get_frame(struct usb_hcd *hcd) | ||
1842 | { | ||
1843 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
1844 | return r8a66597_read(r8a66597, FRMNUM) & 0x03FF; | ||
1845 | } | ||
1846 | |||
1847 | static void collect_usb_address_map(struct usb_device *udev, unsigned long *map) | ||
1848 | { | ||
1849 | int chix; | ||
1850 | |||
1851 | if (udev->state == USB_STATE_CONFIGURED && | ||
1852 | udev->parent && udev->parent->devnum > 1 && | ||
1853 | udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB) | ||
1854 | map[udev->devnum/32] |= (1 << (udev->devnum % 32)); | ||
1855 | |||
1856 | for (chix = 0; chix < udev->maxchild; chix++) { | ||
1857 | struct usb_device *childdev = udev->children[chix]; | ||
1858 | |||
1859 | if (childdev) | ||
1860 | collect_usb_address_map(childdev, map); | ||
1861 | } | ||
1862 | } | ||
1863 | |||
1864 | /* this function must be called with interrupt disabled */ | ||
1865 | static struct r8a66597_device *get_r8a66597_device(struct r8a66597 *r8a66597, | ||
1866 | int addr) | ||
1867 | { | ||
1868 | struct r8a66597_device *dev; | ||
1869 | struct list_head *list = &r8a66597->child_device; | ||
1870 | |||
1871 | list_for_each_entry(dev, list, device_list) { | ||
1872 | if (!dev) | ||
1873 | continue; | ||
1874 | if (dev->usb_address != addr) | ||
1875 | continue; | ||
1876 | |||
1877 | return dev; | ||
1878 | } | ||
1879 | |||
1880 | err("get_r8a66597_device fail.(%d)\n", addr); | ||
1881 | return NULL; | ||
1882 | } | ||
1883 | |||
1884 | static void update_usb_address_map(struct r8a66597 *r8a66597, | ||
1885 | struct usb_device *root_hub, | ||
1886 | unsigned long *map) | ||
1887 | { | ||
1888 | int i, j, addr; | ||
1889 | unsigned long diff; | ||
1890 | unsigned long flags; | ||
1891 | |||
1892 | for (i = 0; i < 4; i++) { | ||
1893 | diff = r8a66597->child_connect_map[i] ^ map[i]; | ||
1894 | if (!diff) | ||
1895 | continue; | ||
1896 | |||
1897 | for (j = 0; j < 32; j++) { | ||
1898 | if (!(diff & (1 << j))) | ||
1899 | continue; | ||
1900 | |||
1901 | addr = i * 32 + j; | ||
1902 | if (map[i] & (1 << j)) | ||
1903 | set_child_connect_map(r8a66597, addr); | ||
1904 | else { | ||
1905 | struct r8a66597_device *dev; | ||
1906 | |||
1907 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1908 | dev = get_r8a66597_device(r8a66597, addr); | ||
1909 | disable_r8a66597_pipe_all(r8a66597, dev); | ||
1910 | free_usb_address(r8a66597, dev); | ||
1911 | put_child_connect_map(r8a66597, addr); | ||
1912 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1913 | } | ||
1914 | } | ||
1915 | } | ||
1916 | } | ||
1917 | |||
1918 | static void r8a66597_check_detect_child(struct r8a66597 *r8a66597, | ||
1919 | struct usb_hcd *hcd) | ||
1920 | { | ||
1921 | struct usb_bus *bus; | ||
1922 | unsigned long now_map[4]; | ||
1923 | |||
1924 | memset(now_map, 0, sizeof(now_map)); | ||
1925 | |||
1926 | list_for_each_entry(bus, &usb_bus_list, bus_list) { | ||
1927 | if (!bus->root_hub) | ||
1928 | continue; | ||
1929 | |||
1930 | if (bus->busnum != hcd->self.busnum) | ||
1931 | continue; | ||
1932 | |||
1933 | collect_usb_address_map(bus->root_hub, now_map); | ||
1934 | update_usb_address_map(r8a66597, bus->root_hub, now_map); | ||
1935 | } | ||
1936 | } | ||
1937 | |||
1938 | static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf) | ||
1939 | { | ||
1940 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
1941 | unsigned long flags; | ||
1942 | int i; | ||
1943 | |||
1944 | r8a66597_check_detect_child(r8a66597, hcd); | ||
1945 | |||
1946 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1947 | |||
1948 | *buf = 0; /* initialize (no change) */ | ||
1949 | |||
1950 | for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) { | ||
1951 | if (r8a66597->root_hub[i].port & 0xffff0000) | ||
1952 | *buf |= 1 << (i + 1); | ||
1953 | } | ||
1954 | |||
1955 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
1956 | |||
1957 | return (*buf != 0); | ||
1958 | } | ||
1959 | |||
1960 | static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597, | ||
1961 | struct usb_hub_descriptor *desc) | ||
1962 | { | ||
1963 | desc->bDescriptorType = 0x29; | ||
1964 | desc->bHubContrCurrent = 0; | ||
1965 | desc->bNbrPorts = R8A66597_MAX_ROOT_HUB; | ||
1966 | desc->bDescLength = 9; | ||
1967 | desc->bPwrOn2PwrGood = 0; | ||
1968 | desc->wHubCharacteristics = cpu_to_le16(0x0011); | ||
1969 | desc->bitmap[0] = ((1 << R8A66597_MAX_ROOT_HUB) - 1) << 1; | ||
1970 | desc->bitmap[1] = ~0; | ||
1971 | } | ||
1972 | |||
1973 | static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | ||
1974 | u16 wIndex, char *buf, u16 wLength) | ||
1975 | { | ||
1976 | struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); | ||
1977 | int ret; | ||
1978 | int port = (wIndex & 0x00FF) - 1; | ||
1979 | struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; | ||
1980 | unsigned long flags; | ||
1981 | |||
1982 | ret = 0; | ||
1983 | |||
1984 | spin_lock_irqsave(&r8a66597->lock, flags); | ||
1985 | switch (typeReq) { | ||
1986 | case ClearHubFeature: | ||
1987 | case SetHubFeature: | ||
1988 | switch (wValue) { | ||
1989 | case C_HUB_OVER_CURRENT: | ||
1990 | case C_HUB_LOCAL_POWER: | ||
1991 | break; | ||
1992 | default: | ||
1993 | goto error; | ||
1994 | } | ||
1995 | break; | ||
1996 | case ClearPortFeature: | ||
1997 | if (wIndex > R8A66597_MAX_ROOT_HUB) | ||
1998 | goto error; | ||
1999 | if (wLength != 0) | ||
2000 | goto error; | ||
2001 | |||
2002 | switch (wValue) { | ||
2003 | case USB_PORT_FEAT_ENABLE: | ||
2004 | rh->port &= (1 << USB_PORT_FEAT_POWER); | ||
2005 | break; | ||
2006 | case USB_PORT_FEAT_SUSPEND: | ||
2007 | break; | ||
2008 | case USB_PORT_FEAT_POWER: | ||
2009 | r8a66597_port_power(r8a66597, port, 0); | ||
2010 | break; | ||
2011 | case USB_PORT_FEAT_C_ENABLE: | ||
2012 | case USB_PORT_FEAT_C_SUSPEND: | ||
2013 | case USB_PORT_FEAT_C_CONNECTION: | ||
2014 | case USB_PORT_FEAT_C_OVER_CURRENT: | ||
2015 | case USB_PORT_FEAT_C_RESET: | ||
2016 | break; | ||
2017 | default: | ||
2018 | goto error; | ||
2019 | } | ||
2020 | rh->port &= ~(1 << wValue); | ||
2021 | break; | ||
2022 | case GetHubDescriptor: | ||
2023 | r8a66597_hub_descriptor(r8a66597, | ||
2024 | (struct usb_hub_descriptor *)buf); | ||
2025 | break; | ||
2026 | case GetHubStatus: | ||
2027 | *buf = 0x00; | ||
2028 | break; | ||
2029 | case GetPortStatus: | ||
2030 | if (wIndex > R8A66597_MAX_ROOT_HUB) | ||
2031 | goto error; | ||
2032 | *(u32 *)buf = rh->port; | ||
2033 | break; | ||
2034 | case SetPortFeature: | ||
2035 | if (wIndex > R8A66597_MAX_ROOT_HUB) | ||
2036 | goto error; | ||
2037 | if (wLength != 0) | ||
2038 | goto error; | ||
2039 | |||
2040 | switch (wValue) { | ||
2041 | case USB_PORT_FEAT_SUSPEND: | ||
2042 | break; | ||
2043 | case USB_PORT_FEAT_POWER: | ||
2044 | r8a66597_port_power(r8a66597, port, 1); | ||
2045 | rh->port |= (1 << USB_PORT_FEAT_POWER); | ||
2046 | break; | ||
2047 | case USB_PORT_FEAT_RESET: { | ||
2048 | struct r8a66597_device *dev = rh->dev; | ||
2049 | |||
2050 | rh->port |= (1 << USB_PORT_FEAT_RESET); | ||
2051 | |||
2052 | disable_r8a66597_pipe_all(r8a66597, dev); | ||
2053 | free_usb_address(r8a66597, dev); | ||
2054 | |||
2055 | r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT, | ||
2056 | get_dvstctr_reg(port)); | ||
2057 | mod_timer(&r8a66597->rh_timer, | ||
2058 | jiffies + msecs_to_jiffies(50)); | ||
2059 | } | ||
2060 | break; | ||
2061 | default: | ||
2062 | goto error; | ||
2063 | } | ||
2064 | rh->port |= 1 << wValue; | ||
2065 | break; | ||
2066 | default: | ||
2067 | error: | ||
2068 | ret = -EPIPE; | ||
2069 | break; | ||
2070 | } | ||
2071 | |||
2072 | spin_unlock_irqrestore(&r8a66597->lock, flags); | ||
2073 | return ret; | ||
2074 | } | ||
2075 | |||
2076 | static struct hc_driver r8a66597_hc_driver = { | ||
2077 | .description = hcd_name, | ||
2078 | .hcd_priv_size = sizeof(struct r8a66597), | ||
2079 | .irq = r8a66597_irq, | ||
2080 | |||
2081 | /* | ||
2082 | * generic hardware linkage | ||
2083 | */ | ||
2084 | .flags = HCD_USB2, | ||
2085 | |||
2086 | .start = r8a66597_start, | ||
2087 | .stop = r8a66597_stop, | ||
2088 | |||
2089 | /* | ||
2090 | * managing i/o requests and associated device resources | ||
2091 | */ | ||
2092 | .urb_enqueue = r8a66597_urb_enqueue, | ||
2093 | .urb_dequeue = r8a66597_urb_dequeue, | ||
2094 | .endpoint_disable = r8a66597_endpoint_disable, | ||
2095 | |||
2096 | /* | ||
2097 | * periodic schedule support | ||
2098 | */ | ||
2099 | .get_frame_number = r8a66597_get_frame, | ||
2100 | |||
2101 | /* | ||
2102 | * root hub support | ||
2103 | */ | ||
2104 | .hub_status_data = r8a66597_hub_status_data, | ||
2105 | .hub_control = r8a66597_hub_control, | ||
2106 | }; | ||
2107 | |||
2108 | #if defined(CONFIG_PM) | ||
2109 | static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state) | ||
2110 | { | ||
2111 | pdev->dev.power.power_state = state; | ||
2112 | return 0; | ||
2113 | } | ||
2114 | |||
2115 | static int r8a66597_resume(struct platform_device *pdev) | ||
2116 | { | ||
2117 | pdev->dev.power.power_state = PMSG_ON; | ||
2118 | return 0; | ||
2119 | } | ||
2120 | #else /* if defined(CONFIG_PM) */ | ||
2121 | #define r8a66597_suspend NULL | ||
2122 | #define r8a66597_resume NULL | ||
2123 | #endif | ||
2124 | |||
2125 | static int __init_or_module r8a66597_remove(struct platform_device *pdev) | ||
2126 | { | ||
2127 | struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); | ||
2128 | struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); | ||
2129 | |||
2130 | del_timer_sync(&r8a66597->rh_timer); | ||
2131 | iounmap((void *)r8a66597->reg); | ||
2132 | usb_remove_hcd(hcd); | ||
2133 | usb_put_hcd(hcd); | ||
2134 | return 0; | ||
2135 | } | ||
2136 | |||
2137 | #define resource_len(r) (((r)->end - (r)->start) + 1) | ||
2138 | static int __init r8a66597_probe(struct platform_device *pdev) | ||
2139 | { | ||
2140 | struct resource *res = NULL; | ||
2141 | int irq = -1; | ||
2142 | void __iomem *reg = NULL; | ||
2143 | struct usb_hcd *hcd = NULL; | ||
2144 | struct r8a66597 *r8a66597; | ||
2145 | int ret = 0; | ||
2146 | int i; | ||
2147 | |||
2148 | if (pdev->dev.dma_mask) { | ||
2149 | ret = -EINVAL; | ||
2150 | err("dma not support"); | ||
2151 | goto clean_up; | ||
2152 | } | ||
2153 | |||
2154 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
2155 | (char *)hcd_name); | ||
2156 | if (!res) { | ||
2157 | ret = -ENODEV; | ||
2158 | err("platform_get_resource_byname error."); | ||
2159 | goto clean_up; | ||
2160 | } | ||
2161 | |||
2162 | irq = platform_get_irq(pdev, 0); | ||
2163 | if (irq < 0) { | ||
2164 | ret = -ENODEV; | ||
2165 | err("platform_get_irq error."); | ||
2166 | goto clean_up; | ||
2167 | } | ||
2168 | |||
2169 | reg = ioremap(res->start, resource_len(res)); | ||
2170 | if (reg == NULL) { | ||
2171 | ret = -ENOMEM; | ||
2172 | err("ioremap error."); | ||
2173 | goto clean_up; | ||
2174 | } | ||
2175 | |||
2176 | /* initialize hcd */ | ||
2177 | hcd = usb_create_hcd(&r8a66597_hc_driver, &pdev->dev, (char *)hcd_name); | ||
2178 | if (!hcd) { | ||
2179 | ret = -ENOMEM; | ||
2180 | err("Failed to create hcd"); | ||
2181 | goto clean_up; | ||
2182 | } | ||
2183 | r8a66597 = hcd_to_r8a66597(hcd); | ||
2184 | memset(r8a66597, 0, sizeof(struct r8a66597)); | ||
2185 | dev_set_drvdata(&pdev->dev, r8a66597); | ||
2186 | |||
2187 | spin_lock_init(&r8a66597->lock); | ||
2188 | init_timer(&r8a66597->rh_timer); | ||
2189 | r8a66597->rh_timer.function = r8a66597_timer; | ||
2190 | r8a66597->rh_timer.data = (unsigned long)r8a66597; | ||
2191 | r8a66597->reg = (unsigned long)reg; | ||
2192 | |||
2193 | for (i = 0; i < R8A66597_MAX_NUM_PIPE; i++) { | ||
2194 | INIT_LIST_HEAD(&r8a66597->pipe_queue[i]); | ||
2195 | init_timer(&r8a66597->td_timer[i]); | ||
2196 | r8a66597->td_timer[i].function = r8a66597_td_timer; | ||
2197 | r8a66597->td_timer[i].data = (unsigned long)r8a66597; | ||
2198 | } | ||
2199 | INIT_LIST_HEAD(&r8a66597->child_device); | ||
2200 | |||
2201 | hcd->rsrc_start = res->start; | ||
2202 | ret = usb_add_hcd(hcd, irq, 0); | ||
2203 | if (ret != 0) { | ||
2204 | err("Failed to add hcd"); | ||
2205 | goto clean_up; | ||
2206 | } | ||
2207 | |||
2208 | return 0; | ||
2209 | |||
2210 | clean_up: | ||
2211 | if (reg) | ||
2212 | iounmap(reg); | ||
2213 | if (res) | ||
2214 | release_mem_region(res->start, 1); | ||
2215 | |||
2216 | return ret; | ||
2217 | } | ||
2218 | |||
2219 | static struct platform_driver r8a66597_driver = { | ||
2220 | .probe = r8a66597_probe, | ||
2221 | .remove = r8a66597_remove, | ||
2222 | .suspend = r8a66597_suspend, | ||
2223 | .resume = r8a66597_resume, | ||
2224 | .driver = { | ||
2225 | .name = (char *) hcd_name, | ||
2226 | }, | ||
2227 | }; | ||
2228 | |||
2229 | static int __init r8a66597_init(void) | ||
2230 | { | ||
2231 | if (usb_disabled()) | ||
2232 | return -ENODEV; | ||
2233 | |||
2234 | info("driver %s, %s", hcd_name, DRIVER_VERSION); | ||
2235 | return platform_driver_register(&r8a66597_driver); | ||
2236 | } | ||
2237 | module_init(r8a66597_init); | ||
2238 | |||
2239 | static void __exit r8a66597_cleanup(void) | ||
2240 | { | ||
2241 | platform_driver_unregister(&r8a66597_driver); | ||
2242 | } | ||
2243 | module_exit(r8a66597_cleanup); | ||
2244 | |||
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h new file mode 100644 index 000000000000..97c2a71ac7a1 --- /dev/null +++ b/drivers/usb/host/r8a66597.h | |||
@@ -0,0 +1,634 @@ | |||
1 | /* | ||
2 | * R8A66597 HCD (Host Controller Driver) | ||
3 | * | ||
4 | * Copyright (C) 2006-2007 Renesas Solutions Corp. | ||
5 | * Portions Copyright (C) 2004 Psion Teklogix (for NetBook PRO) | ||
6 | * Portions Copyright (C) 2004-2005 David Brownell | ||
7 | * Portions Copyright (C) 1999 Roman Weissgaerber | ||
8 | * | ||
9 | * Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; version 2 of the License. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #ifndef __R8A66597_H__ | ||
27 | #define __R8A66597_H__ | ||
28 | |||
29 | #define SYSCFG0 0x00 | ||
30 | #define SYSCFG1 0x02 | ||
31 | #define SYSSTS0 0x04 | ||
32 | #define SYSSTS1 0x06 | ||
33 | #define DVSTCTR0 0x08 | ||
34 | #define DVSTCTR1 0x0A | ||
35 | #define TESTMODE 0x0C | ||
36 | #define PINCFG 0x0E | ||
37 | #define DMA0CFG 0x10 | ||
38 | #define DMA1CFG 0x12 | ||
39 | #define CFIFO 0x14 | ||
40 | #define D0FIFO 0x18 | ||
41 | #define D1FIFO 0x1C | ||
42 | #define CFIFOSEL 0x20 | ||
43 | #define CFIFOCTR 0x22 | ||
44 | #define CFIFOSIE 0x24 | ||
45 | #define D0FIFOSEL 0x28 | ||
46 | #define D0FIFOCTR 0x2A | ||
47 | #define D1FIFOSEL 0x2C | ||
48 | #define D1FIFOCTR 0x2E | ||
49 | #define INTENB0 0x30 | ||
50 | #define INTENB1 0x32 | ||
51 | #define INTENB2 0x34 | ||
52 | #define BRDYENB 0x36 | ||
53 | #define NRDYENB 0x38 | ||
54 | #define BEMPENB 0x3A | ||
55 | #define SOFCFG 0x3C | ||
56 | #define INTSTS0 0x40 | ||
57 | #define INTSTS1 0x42 | ||
58 | #define INTSTS2 0x44 | ||
59 | #define BRDYSTS 0x46 | ||
60 | #define NRDYSTS 0x48 | ||
61 | #define BEMPSTS 0x4A | ||
62 | #define FRMNUM 0x4C | ||
63 | #define UFRMNUM 0x4E | ||
64 | #define USBADDR 0x50 | ||
65 | #define USBREQ 0x54 | ||
66 | #define USBVAL 0x56 | ||
67 | #define USBINDX 0x58 | ||
68 | #define USBLENG 0x5A | ||
69 | #define DCPCFG 0x5C | ||
70 | #define DCPMAXP 0x5E | ||
71 | #define DCPCTR 0x60 | ||
72 | #define PIPESEL 0x64 | ||
73 | #define PIPECFG 0x68 | ||
74 | #define PIPEBUF 0x6A | ||
75 | #define PIPEMAXP 0x6C | ||
76 | #define PIPEPERI 0x6E | ||
77 | #define PIPE1CTR 0x70 | ||
78 | #define PIPE2CTR 0x72 | ||
79 | #define PIPE3CTR 0x74 | ||
80 | #define PIPE4CTR 0x76 | ||
81 | #define PIPE5CTR 0x78 | ||
82 | #define PIPE6CTR 0x7A | ||
83 | #define PIPE7CTR 0x7C | ||
84 | #define PIPE8CTR 0x7E | ||
85 | #define PIPE9CTR 0x80 | ||
86 | #define PIPE1TRE 0x90 | ||
87 | #define PIPE1TRN 0x92 | ||
88 | #define PIPE2TRE 0x94 | ||
89 | #define PIPE2TRN 0x96 | ||
90 | #define PIPE3TRE 0x98 | ||
91 | #define PIPE3TRN 0x9A | ||
92 | #define PIPE4TRE 0x9C | ||
93 | #define PIPE4TRN 0x9E | ||
94 | #define PIPE5TRE 0xA0 | ||
95 | #define PIPE5TRN 0xA2 | ||
96 | #define DEVADD0 0xD0 | ||
97 | #define DEVADD1 0xD2 | ||
98 | #define DEVADD2 0xD4 | ||
99 | #define DEVADD3 0xD6 | ||
100 | #define DEVADD4 0xD8 | ||
101 | #define DEVADD5 0xDA | ||
102 | #define DEVADD6 0xDC | ||
103 | #define DEVADD7 0xDE | ||
104 | #define DEVADD8 0xE0 | ||
105 | #define DEVADD9 0xE2 | ||
106 | #define DEVADDA 0xE4 | ||
107 | |||
108 | /* System Configuration Control Register */ | ||
109 | #define XTAL 0xC000 /* b15-14: Crystal selection */ | ||
110 | #define XTAL48 0x8000 /* 48MHz */ | ||
111 | #define XTAL24 0x4000 /* 24MHz */ | ||
112 | #define XTAL12 0x0000 /* 12MHz */ | ||
113 | #define XCKE 0x2000 /* b13: External clock enable */ | ||
114 | #define PLLC 0x0800 /* b11: PLL control */ | ||
115 | #define SCKE 0x0400 /* b10: USB clock enable */ | ||
116 | #define PCSDIS 0x0200 /* b9: not CS wakeup */ | ||
117 | #define LPSME 0x0100 /* b8: Low power sleep mode */ | ||
118 | #define HSE 0x0080 /* b7: Hi-speed enable */ | ||
119 | #define DCFM 0x0040 /* b6: Controller function select */ | ||
120 | #define DRPD 0x0020 /* b5: D+/- pull down control */ | ||
121 | #define DPRPU 0x0010 /* b4: D+ pull up control */ | ||
122 | #define USBE 0x0001 /* b0: USB module operation enable */ | ||
123 | |||
124 | /* System Configuration Status Register */ | ||
125 | #define OVCBIT 0x8000 /* b15-14: Over-current bit */ | ||
126 | #define OVCMON 0xC000 /* b15-14: Over-current monitor */ | ||
127 | #define SOFEA 0x0020 /* b5: SOF monitor */ | ||
128 | #define IDMON 0x0004 /* b3: ID-pin monitor */ | ||
129 | #define LNST 0x0003 /* b1-0: D+, D- line status */ | ||
130 | #define SE1 0x0003 /* SE1 */ | ||
131 | #define FS_KSTS 0x0002 /* Full-Speed K State */ | ||
132 | #define FS_JSTS 0x0001 /* Full-Speed J State */ | ||
133 | #define LS_JSTS 0x0002 /* Low-Speed J State */ | ||
134 | #define LS_KSTS 0x0001 /* Low-Speed K State */ | ||
135 | #define SE0 0x0000 /* SE0 */ | ||
136 | |||
137 | /* Device State Control Register */ | ||
138 | #define EXTLP0 0x0400 /* b10: External port */ | ||
139 | #define VBOUT 0x0200 /* b9: VBUS output */ | ||
140 | #define WKUP 0x0100 /* b8: Remote wakeup */ | ||
141 | #define RWUPE 0x0080 /* b7: Remote wakeup sense */ | ||
142 | #define USBRST 0x0040 /* b6: USB reset enable */ | ||
143 | #define RESUME 0x0020 /* b5: Resume enable */ | ||
144 | #define UACT 0x0010 /* b4: USB bus enable */ | ||
145 | #define RHST 0x0007 /* b1-0: Reset handshake status */ | ||
146 | #define HSPROC 0x0004 /* HS handshake is processing */ | ||
147 | #define HSMODE 0x0003 /* Hi-Speed mode */ | ||
148 | #define FSMODE 0x0002 /* Full-Speed mode */ | ||
149 | #define LSMODE 0x0001 /* Low-Speed mode */ | ||
150 | #define UNDECID 0x0000 /* Undecided */ | ||
151 | |||
152 | /* Test Mode Register */ | ||
153 | #define UTST 0x000F /* b3-0: Test select */ | ||
154 | #define H_TST_PACKET 0x000C /* HOST TEST Packet */ | ||
155 | #define H_TST_SE0_NAK 0x000B /* HOST TEST SE0 NAK */ | ||
156 | #define H_TST_K 0x000A /* HOST TEST K */ | ||
157 | #define H_TST_J 0x0009 /* HOST TEST J */ | ||
158 | #define H_TST_NORMAL 0x0000 /* HOST Normal Mode */ | ||
159 | #define P_TST_PACKET 0x0004 /* PERI TEST Packet */ | ||
160 | #define P_TST_SE0_NAK 0x0003 /* PERI TEST SE0 NAK */ | ||
161 | #define P_TST_K 0x0002 /* PERI TEST K */ | ||
162 | #define P_TST_J 0x0001 /* PERI TEST J */ | ||
163 | #define P_TST_NORMAL 0x0000 /* PERI Normal Mode */ | ||
164 | |||
165 | /* Data Pin Configuration Register */ | ||
166 | #define LDRV 0x8000 /* b15: Drive Current Adjust */ | ||
167 | #define VIF1 0x0000 /* VIF = 1.8V */ | ||
168 | #define VIF3 0x8000 /* VIF = 3.3V */ | ||
169 | #define INTA 0x0001 /* b1: USB INT-pin active */ | ||
170 | |||
171 | /* DMAx Pin Configuration Register */ | ||
172 | #define DREQA 0x4000 /* b14: Dreq active select */ | ||
173 | #define BURST 0x2000 /* b13: Burst mode */ | ||
174 | #define DACKA 0x0400 /* b10: Dack active select */ | ||
175 | #define DFORM 0x0380 /* b9-7: DMA mode select */ | ||
176 | #define CPU_ADR_RD_WR 0x0000 /* Address + RD/WR mode (CPU bus) */ | ||
177 | #define CPU_DACK_RD_WR 0x0100 /* DACK + RD/WR mode (CPU bus) */ | ||
178 | #define CPU_DACK_ONLY 0x0180 /* DACK only mode (CPU bus) */ | ||
179 | #define SPLIT_DACK_ONLY 0x0200 /* DACK only mode (SPLIT bus) */ | ||
180 | #define DENDA 0x0040 /* b6: Dend active select */ | ||
181 | #define PKTM 0x0020 /* b5: Packet mode */ | ||
182 | #define DENDE 0x0010 /* b4: Dend enable */ | ||
183 | #define OBUS 0x0004 /* b2: OUTbus mode */ | ||
184 | |||
185 | /* CFIFO/DxFIFO Port Select Register */ | ||
186 | #define RCNT 0x8000 /* b15: Read count mode */ | ||
187 | #define REW 0x4000 /* b14: Buffer rewind */ | ||
188 | #define DCLRM 0x2000 /* b13: DMA buffer clear mode */ | ||
189 | #define DREQE 0x1000 /* b12: DREQ output enable */ | ||
190 | #define MBW 0x0400 /* b10: Maximum bit width for FIFO access */ | ||
191 | #define MBW_8 0x0000 /* 8bit */ | ||
192 | #define MBW_16 0x0400 /* 16bit */ | ||
193 | #define BIGEND 0x0100 /* b8: Big endian mode */ | ||
194 | #define BYTE_LITTLE 0x0000 /* little dendian */ | ||
195 | #define BYTE_BIG 0x0100 /* big endifan */ | ||
196 | #define ISEL 0x0020 /* b5: DCP FIFO port direction select */ | ||
197 | #define CURPIPE 0x000F /* b2-0: PIPE select */ | ||
198 | |||
199 | /* CFIFO/DxFIFO Port Control Register */ | ||
200 | #define BVAL 0x8000 /* b15: Buffer valid flag */ | ||
201 | #define BCLR 0x4000 /* b14: Buffer clear */ | ||
202 | #define FRDY 0x2000 /* b13: FIFO ready */ | ||
203 | #define DTLN 0x0FFF /* b11-0: FIFO received data length */ | ||
204 | |||
205 | /* Interrupt Enable Register 0 */ | ||
206 | #define VBSE 0x8000 /* b15: VBUS interrupt */ | ||
207 | #define RSME 0x4000 /* b14: Resume interrupt */ | ||
208 | #define SOFE 0x2000 /* b13: Frame update interrupt */ | ||
209 | #define DVSE 0x1000 /* b12: Device state transition interrupt */ | ||
210 | #define CTRE 0x0800 /* b11: Control transfer stage transition interrupt */ | ||
211 | #define BEMPE 0x0400 /* b10: Buffer empty interrupt */ | ||
212 | #define NRDYE 0x0200 /* b9: Buffer not ready interrupt */ | ||
213 | #define BRDYE 0x0100 /* b8: Buffer ready interrupt */ | ||
214 | |||
215 | /* Interrupt Enable Register 1 */ | ||
216 | #define OVRCRE 0x8000 /* b15: Over-current interrupt */ | ||
217 | #define BCHGE 0x4000 /* b14: USB us chenge interrupt */ | ||
218 | #define DTCHE 0x1000 /* b12: Detach sense interrupt */ | ||
219 | #define ATTCHE 0x0800 /* b11: Attach sense interrupt */ | ||
220 | #define EOFERRE 0x0040 /* b6: EOF error interrupt */ | ||
221 | #define SIGNE 0x0020 /* b5: SETUP IGNORE interrupt */ | ||
222 | #define SACKE 0x0010 /* b4: SETUP ACK interrupt */ | ||
223 | |||
224 | /* BRDY Interrupt Enable/Status Register */ | ||
225 | #define BRDY9 0x0200 /* b9: PIPE9 */ | ||
226 | #define BRDY8 0x0100 /* b8: PIPE8 */ | ||
227 | #define BRDY7 0x0080 /* b7: PIPE7 */ | ||
228 | #define BRDY6 0x0040 /* b6: PIPE6 */ | ||
229 | #define BRDY5 0x0020 /* b5: PIPE5 */ | ||
230 | #define BRDY4 0x0010 /* b4: PIPE4 */ | ||
231 | #define BRDY3 0x0008 /* b3: PIPE3 */ | ||
232 | #define BRDY2 0x0004 /* b2: PIPE2 */ | ||
233 | #define BRDY1 0x0002 /* b1: PIPE1 */ | ||
234 | #define BRDY0 0x0001 /* b1: PIPE0 */ | ||
235 | |||
236 | /* NRDY Interrupt Enable/Status Register */ | ||
237 | #define NRDY9 0x0200 /* b9: PIPE9 */ | ||
238 | #define NRDY8 0x0100 /* b8: PIPE8 */ | ||
239 | #define NRDY7 0x0080 /* b7: PIPE7 */ | ||
240 | #define NRDY6 0x0040 /* b6: PIPE6 */ | ||
241 | #define NRDY5 0x0020 /* b5: PIPE5 */ | ||
242 | #define NRDY4 0x0010 /* b4: PIPE4 */ | ||
243 | #define NRDY3 0x0008 /* b3: PIPE3 */ | ||
244 | #define NRDY2 0x0004 /* b2: PIPE2 */ | ||
245 | #define NRDY1 0x0002 /* b1: PIPE1 */ | ||
246 | #define NRDY0 0x0001 /* b1: PIPE0 */ | ||
247 | |||
248 | /* BEMP Interrupt Enable/Status Register */ | ||
249 | #define BEMP9 0x0200 /* b9: PIPE9 */ | ||
250 | #define BEMP8 0x0100 /* b8: PIPE8 */ | ||
251 | #define BEMP7 0x0080 /* b7: PIPE7 */ | ||
252 | #define BEMP6 0x0040 /* b6: PIPE6 */ | ||
253 | #define BEMP5 0x0020 /* b5: PIPE5 */ | ||
254 | #define BEMP4 0x0010 /* b4: PIPE4 */ | ||
255 | #define BEMP3 0x0008 /* b3: PIPE3 */ | ||
256 | #define BEMP2 0x0004 /* b2: PIPE2 */ | ||
257 | #define BEMP1 0x0002 /* b1: PIPE1 */ | ||
258 | #define BEMP0 0x0001 /* b0: PIPE0 */ | ||
259 | |||
260 | /* SOF Pin Configuration Register */ | ||
261 | #define TRNENSEL 0x0100 /* b8: Select transaction enable period */ | ||
262 | #define BRDYM 0x0040 /* b6: BRDY clear timing */ | ||
263 | #define INTL 0x0020 /* b5: Interrupt sense select */ | ||
264 | #define EDGESTS 0x0010 /* b4: */ | ||
265 | #define SOFMODE 0x000C /* b3-2: SOF pin select */ | ||
266 | #define SOF_125US 0x0008 /* SOF OUT 125us Frame Signal */ | ||
267 | #define SOF_1MS 0x0004 /* SOF OUT 1ms Frame Signal */ | ||
268 | #define SOF_DISABLE 0x0000 /* SOF OUT Disable */ | ||
269 | |||
270 | /* Interrupt Status Register 0 */ | ||
271 | #define VBINT 0x8000 /* b15: VBUS interrupt */ | ||
272 | #define RESM 0x4000 /* b14: Resume interrupt */ | ||
273 | #define SOFR 0x2000 /* b13: SOF frame update interrupt */ | ||
274 | #define DVST 0x1000 /* b12: Device state transition interrupt */ | ||
275 | #define CTRT 0x0800 /* b11: Control transfer stage transition interrupt */ | ||
276 | #define BEMP 0x0400 /* b10: Buffer empty interrupt */ | ||
277 | #define NRDY 0x0200 /* b9: Buffer not ready interrupt */ | ||
278 | #define BRDY 0x0100 /* b8: Buffer ready interrupt */ | ||
279 | #define VBSTS 0x0080 /* b7: VBUS input port */ | ||
280 | #define DVSQ 0x0070 /* b6-4: Device state */ | ||
281 | #define DS_SPD_CNFG 0x0070 /* Suspend Configured */ | ||
282 | #define DS_SPD_ADDR 0x0060 /* Suspend Address */ | ||
283 | #define DS_SPD_DFLT 0x0050 /* Suspend Default */ | ||
284 | #define DS_SPD_POWR 0x0040 /* Suspend Powered */ | ||
285 | #define DS_SUSP 0x0040 /* Suspend */ | ||
286 | #define DS_CNFG 0x0030 /* Configured */ | ||
287 | #define DS_ADDS 0x0020 /* Address */ | ||
288 | #define DS_DFLT 0x0010 /* Default */ | ||
289 | #define DS_POWR 0x0000 /* Powered */ | ||
290 | #define DVSQS 0x0030 /* b5-4: Device state */ | ||
291 | #define VALID 0x0008 /* b3: Setup packet detected flag */ | ||
292 | #define CTSQ 0x0007 /* b2-0: Control transfer stage */ | ||
293 | #define CS_SQER 0x0006 /* Sequence error */ | ||
294 | #define CS_WRND 0x0005 /* Control write nodata status stage */ | ||
295 | #define CS_WRSS 0x0004 /* Control write status stage */ | ||
296 | #define CS_WRDS 0x0003 /* Control write data stage */ | ||
297 | #define CS_RDSS 0x0002 /* Control read status stage */ | ||
298 | #define CS_RDDS 0x0001 /* Control read data stage */ | ||
299 | #define CS_IDST 0x0000 /* Idle or setup stage */ | ||
300 | |||
301 | /* Interrupt Status Register 1 */ | ||
302 | #define OVRCR 0x8000 /* b15: Over-current interrupt */ | ||
303 | #define BCHG 0x4000 /* b14: USB bus chenge interrupt */ | ||
304 | #define DTCH 0x1000 /* b12: Detach sense interrupt */ | ||
305 | #define ATTCH 0x0800 /* b11: Attach sense interrupt */ | ||
306 | #define EOFERR 0x0040 /* b6: EOF-error interrupt */ | ||
307 | #define SIGN 0x0020 /* b5: Setup ignore interrupt */ | ||
308 | #define SACK 0x0010 /* b4: Setup acknowledge interrupt */ | ||
309 | |||
310 | /* Frame Number Register */ | ||
311 | #define OVRN 0x8000 /* b15: Overrun error */ | ||
312 | #define CRCE 0x4000 /* b14: Received data error */ | ||
313 | #define FRNM 0x07FF /* b10-0: Frame number */ | ||
314 | |||
315 | /* Micro Frame Number Register */ | ||
316 | #define UFRNM 0x0007 /* b2-0: Micro frame number */ | ||
317 | |||
318 | /* USB Address / Low Power Status Recovery Register */ | ||
319 | //#define USBADDR 0x007F /* b6-0: USB address */ | ||
320 | |||
321 | /* Default Control Pipe Maxpacket Size Register */ | ||
322 | /* Pipe Maxpacket Size Register */ | ||
323 | #define DEVSEL 0xF000 /* b15-14: Device address select */ | ||
324 | #define MAXP 0x007F /* b6-0: Maxpacket size of default control pipe */ | ||
325 | |||
326 | /* Default Control Pipe Control Register */ | ||
327 | #define BSTS 0x8000 /* b15: Buffer status */ | ||
328 | #define SUREQ 0x4000 /* b14: Send USB request */ | ||
329 | #define CSCLR 0x2000 /* b13: complete-split status clear */ | ||
330 | #define CSSTS 0x1000 /* b12: complete-split status */ | ||
331 | #define SUREQCLR 0x0800 /* b11: stop setup request */ | ||
332 | #define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ | ||
333 | #define SQSET 0x0080 /* b7: Sequence toggle bit set */ | ||
334 | #define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ | ||
335 | #define PBUSY 0x0020 /* b5: pipe busy */ | ||
336 | #define PINGE 0x0010 /* b4: ping enable */ | ||
337 | #define CCPL 0x0004 /* b2: Enable control transfer complete */ | ||
338 | #define PID 0x0003 /* b1-0: Response PID */ | ||
339 | #define PID_STALL11 0x0003 /* STALL */ | ||
340 | #define PID_STALL 0x0002 /* STALL */ | ||
341 | #define PID_BUF 0x0001 /* BUF */ | ||
342 | #define PID_NAK 0x0000 /* NAK */ | ||
343 | |||
344 | /* Pipe Window Select Register */ | ||
345 | #define PIPENM 0x0007 /* b2-0: Pipe select */ | ||
346 | |||
347 | /* Pipe Configuration Register */ | ||
348 | #define R8A66597_TYP 0xC000 /* b15-14: Transfer type */ | ||
349 | #define R8A66597_ISO 0xC000 /* Isochronous */ | ||
350 | #define R8A66597_INT 0x8000 /* Interrupt */ | ||
351 | #define R8A66597_BULK 0x4000 /* Bulk */ | ||
352 | #define R8A66597_BFRE 0x0400 /* b10: Buffer ready interrupt mode select */ | ||
353 | #define R8A66597_DBLB 0x0200 /* b9: Double buffer mode select */ | ||
354 | #define R8A66597_CNTMD 0x0100 /* b8: Continuous transfer mode select */ | ||
355 | #define R8A66597_SHTNAK 0x0080 /* b7: Transfer end NAK */ | ||
356 | #define R8A66597_DIR 0x0010 /* b4: Transfer direction select */ | ||
357 | #define R8A66597_EPNUM 0x000F /* b3-0: Eendpoint number select */ | ||
358 | |||
359 | /* Pipe Buffer Configuration Register */ | ||
360 | #define BUFSIZE 0x7C00 /* b14-10: Pipe buffer size */ | ||
361 | #define BUFNMB 0x007F /* b6-0: Pipe buffer number */ | ||
362 | #define PIPE0BUF 256 | ||
363 | #define PIPExBUF 64 | ||
364 | |||
365 | /* Pipe Maxpacket Size Register */ | ||
366 | #define MXPS 0x07FF /* b10-0: Maxpacket size */ | ||
367 | |||
368 | /* Pipe Cycle Configuration Register */ | ||
369 | #define IFIS 0x1000 /* b12: Isochronous in-buffer flush mode select */ | ||
370 | #define IITV 0x0007 /* b2-0: Isochronous interval */ | ||
371 | |||
372 | /* Pipex Control Register */ | ||
373 | #define BSTS 0x8000 /* b15: Buffer status */ | ||
374 | #define INBUFM 0x4000 /* b14: IN buffer monitor (Only for PIPE1 to 5) */ | ||
375 | #define CSCLR 0x2000 /* b13: complete-split status clear */ | ||
376 | #define CSSTS 0x1000 /* b12: complete-split status */ | ||
377 | #define ATREPM 0x0400 /* b10: Auto repeat mode */ | ||
378 | #define ACLRM 0x0200 /* b9: Out buffer auto clear mode */ | ||
379 | #define SQCLR 0x0100 /* b8: Sequence toggle bit clear */ | ||
380 | #define SQSET 0x0080 /* b7: Sequence toggle bit set */ | ||
381 | #define SQMON 0x0040 /* b6: Sequence toggle bit monitor */ | ||
382 | #define PBUSY 0x0020 /* b5: pipe busy */ | ||
383 | #define PID 0x0003 /* b1-0: Response PID */ | ||
384 | |||
385 | /* PIPExTRE */ | ||
386 | #define TRENB 0x0200 /* b9: Transaction counter enable */ | ||
387 | #define TRCLR 0x0100 /* b8: Transaction counter clear */ | ||
388 | |||
389 | /* PIPExTRN */ | ||
390 | #define TRNCNT 0xFFFF /* b15-0: Transaction counter */ | ||
391 | |||
392 | /* DEVADDx */ | ||
393 | #define UPPHUB 0x7800 | ||
394 | #define HUBPORT 0x0700 | ||
395 | #define USBSPD 0x00C0 | ||
396 | #define RTPORT 0x0001 | ||
397 | |||
398 | #define R8A66597_MAX_NUM_PIPE 10 | ||
399 | #define R8A66597_BUF_BSIZE 8 | ||
400 | #define R8A66597_MAX_DEVICE 10 | ||
401 | #define R8A66597_MAX_ROOT_HUB 2 | ||
402 | #define R8A66597_MAX_SAMPLING 10 | ||
403 | #define R8A66597_MAX_DMA_CHANNEL 2 | ||
404 | #define R8A66597_PIPE_NO_DMA R8A66597_MAX_DMA_CHANNEL | ||
405 | #define check_bulk_or_isoc(pipenum) ((pipenum >= 1 && pipenum <= 5)) | ||
406 | #define check_interrupt(pipenum) ((pipenum >= 6 && pipenum <= 9)) | ||
407 | #define make_devsel(addr) (addr << 12) | ||
408 | |||
409 | struct r8a66597_pipe_info { | ||
410 | u16 pipenum; | ||
411 | u16 address; /* R8A66597 HCD usb addres */ | ||
412 | u16 epnum; | ||
413 | u16 maxpacket; | ||
414 | u16 type; | ||
415 | u16 bufnum; | ||
416 | u16 buf_bsize; | ||
417 | u16 interval; | ||
418 | u16 dir_in; | ||
419 | }; | ||
420 | |||
421 | struct r8a66597_pipe { | ||
422 | struct r8a66597_pipe_info info; | ||
423 | |||
424 | unsigned long fifoaddr; | ||
425 | unsigned long fifosel; | ||
426 | unsigned long fifoctr; | ||
427 | unsigned long pipectr; | ||
428 | unsigned long pipetre; | ||
429 | unsigned long pipetrn; | ||
430 | }; | ||
431 | |||
432 | struct r8a66597_td { | ||
433 | struct r8a66597_pipe *pipe; | ||
434 | struct urb *urb; | ||
435 | struct list_head queue; | ||
436 | |||
437 | u16 type; | ||
438 | u16 pipenum; | ||
439 | int iso_cnt; | ||
440 | |||
441 | u16 address; /* R8A66597's USB address */ | ||
442 | u16 maxpacket; | ||
443 | |||
444 | unsigned zero_packet:1; | ||
445 | unsigned short_packet:1; | ||
446 | unsigned set_address:1; | ||
447 | }; | ||
448 | |||
449 | struct r8a66597_device { | ||
450 | u16 address; /* R8A66597's USB address */ | ||
451 | u16 hub_port; | ||
452 | u16 root_port; | ||
453 | |||
454 | unsigned short ep_in_toggle; | ||
455 | unsigned short ep_out_toggle; | ||
456 | unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE]; | ||
457 | unsigned char dma_map; | ||
458 | |||
459 | enum usb_device_state state; | ||
460 | |||
461 | struct usb_device *udev; | ||
462 | int usb_address; | ||
463 | struct list_head device_list; | ||
464 | }; | ||
465 | |||
466 | struct r8a66597_root_hub { | ||
467 | u32 port; | ||
468 | u16 old_syssts; | ||
469 | int scount; | ||
470 | |||
471 | struct r8a66597_device *dev; | ||
472 | }; | ||
473 | |||
474 | struct r8a66597 { | ||
475 | spinlock_t lock; | ||
476 | unsigned long reg; | ||
477 | |||
478 | struct r8a66597_device device0; | ||
479 | struct r8a66597_root_hub root_hub[R8A66597_MAX_ROOT_HUB]; | ||
480 | struct list_head pipe_queue[R8A66597_MAX_NUM_PIPE]; | ||
481 | |||
482 | struct timer_list rh_timer; | ||
483 | struct timer_list td_timer[R8A66597_MAX_NUM_PIPE]; | ||
484 | |||
485 | unsigned short address_map; | ||
486 | unsigned short timeout_map; | ||
487 | unsigned char pipe_cnt[R8A66597_MAX_NUM_PIPE]; | ||
488 | unsigned char dma_map; | ||
489 | |||
490 | struct list_head child_device; | ||
491 | unsigned long child_connect_map[4]; | ||
492 | }; | ||
493 | |||
494 | static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd) | ||
495 | { | ||
496 | return (struct r8a66597 *)(hcd->hcd_priv); | ||
497 | } | ||
498 | |||
499 | static inline struct usb_hcd *r8a66597_to_hcd(struct r8a66597 *r8a66597) | ||
500 | { | ||
501 | return container_of((void *)r8a66597, struct usb_hcd, hcd_priv); | ||
502 | } | ||
503 | |||
504 | static inline struct r8a66597_td *r8a66597_get_td(struct r8a66597 *r8a66597, | ||
505 | u16 pipenum) | ||
506 | { | ||
507 | if (unlikely(list_empty(&r8a66597->pipe_queue[pipenum]))) | ||
508 | return NULL; | ||
509 | |||
510 | return list_entry(r8a66597->pipe_queue[pipenum].next, | ||
511 | struct r8a66597_td, queue); | ||
512 | } | ||
513 | |||
514 | static inline struct urb *r8a66597_get_urb(struct r8a66597 *r8a66597, | ||
515 | u16 pipenum) | ||
516 | { | ||
517 | struct r8a66597_td *td; | ||
518 | |||
519 | td = r8a66597_get_td(r8a66597, pipenum); | ||
520 | return (td ? td->urb : NULL); | ||
521 | } | ||
522 | |||
523 | static inline u16 r8a66597_read(struct r8a66597 *r8a66597, unsigned long offset) | ||
524 | { | ||
525 | return inw(r8a66597->reg + offset); | ||
526 | } | ||
527 | |||
528 | static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, | ||
529 | unsigned long offset, u16 *buf, | ||
530 | int len) | ||
531 | { | ||
532 | len = (len + 1) / 2; | ||
533 | insw(r8a66597->reg + offset, buf, len); | ||
534 | } | ||
535 | |||
536 | static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, | ||
537 | unsigned long offset) | ||
538 | { | ||
539 | outw(val, r8a66597->reg + offset); | ||
540 | } | ||
541 | |||
542 | static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, | ||
543 | unsigned long offset, u16 *buf, | ||
544 | int len) | ||
545 | { | ||
546 | unsigned long fifoaddr = r8a66597->reg + offset; | ||
547 | int odd = len & 0x0001; | ||
548 | |||
549 | len = len / 2; | ||
550 | outsw(fifoaddr, buf, len); | ||
551 | if (unlikely(odd)) { | ||
552 | buf = &buf[len]; | ||
553 | outb((unsigned char)*buf, fifoaddr); | ||
554 | } | ||
555 | } | ||
556 | |||
557 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, | ||
558 | u16 val, u16 pat, unsigned long offset) | ||
559 | { | ||
560 | u16 tmp; | ||
561 | tmp = r8a66597_read(r8a66597, offset); | ||
562 | tmp = tmp & (~pat); | ||
563 | tmp = tmp | val; | ||
564 | r8a66597_write(r8a66597, tmp, offset); | ||
565 | } | ||
566 | |||
567 | #define r8a66597_bclr(r8a66597, val, offset) \ | ||
568 | r8a66597_mdfy(r8a66597, 0, val, offset) | ||
569 | #define r8a66597_bset(r8a66597, val, offset) \ | ||
570 | r8a66597_mdfy(r8a66597, val, 0, offset) | ||
571 | |||
572 | static inline unsigned long get_syscfg_reg(int port) | ||
573 | { | ||
574 | return port == 0 ? SYSCFG0 : SYSCFG1; | ||
575 | } | ||
576 | |||
577 | static inline unsigned long get_syssts_reg(int port) | ||
578 | { | ||
579 | return port == 0 ? SYSSTS0 : SYSSTS1; | ||
580 | } | ||
581 | |||
582 | static inline unsigned long get_dvstctr_reg(int port) | ||
583 | { | ||
584 | return port == 0 ? DVSTCTR0 : DVSTCTR1; | ||
585 | } | ||
586 | |||
587 | static inline unsigned long get_intenb_reg(int port) | ||
588 | { | ||
589 | return port == 0 ? INTENB1 : INTENB2; | ||
590 | } | ||
591 | |||
592 | static inline unsigned long get_intsts_reg(int port) | ||
593 | { | ||
594 | return port == 0 ? INTSTS1 : INTSTS2; | ||
595 | } | ||
596 | |||
597 | static inline u16 get_rh_usb_speed(struct r8a66597 *r8a66597, int port) | ||
598 | { | ||
599 | unsigned long dvstctr_reg = get_dvstctr_reg(port); | ||
600 | |||
601 | return r8a66597_read(r8a66597, dvstctr_reg) & RHST; | ||
602 | } | ||
603 | |||
604 | static inline void r8a66597_port_power(struct r8a66597 *r8a66597, int port, | ||
605 | int power) | ||
606 | { | ||
607 | unsigned long dvstctr_reg = get_dvstctr_reg(port); | ||
608 | |||
609 | if (power) | ||
610 | r8a66597_bset(r8a66597, VBOUT, dvstctr_reg); | ||
611 | else | ||
612 | r8a66597_bclr(r8a66597, VBOUT, dvstctr_reg); | ||
613 | } | ||
614 | |||
615 | #define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2) | ||
616 | #define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4) | ||
617 | #define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4) | ||
618 | #define get_devadd_addr(address) (DEVADD0 + address * 2) | ||
619 | |||
620 | #define enable_irq_ready(r8a66597, pipenum) \ | ||
621 | enable_pipe_irq(r8a66597, pipenum, BRDYENB) | ||
622 | #define disable_irq_ready(r8a66597, pipenum) \ | ||
623 | disable_pipe_irq(r8a66597, pipenum, BRDYENB) | ||
624 | #define enable_irq_empty(r8a66597, pipenum) \ | ||
625 | enable_pipe_irq(r8a66597, pipenum, BEMPENB) | ||
626 | #define disable_irq_empty(r8a66597, pipenum) \ | ||
627 | disable_pipe_irq(r8a66597, pipenum, BEMPENB) | ||
628 | #define enable_irq_nrdy(r8a66597, pipenum) \ | ||
629 | enable_pipe_irq(r8a66597, pipenum, NRDYENB) | ||
630 | #define disable_irq_nrdy(r8a66597, pipenum) \ | ||
631 | disable_pipe_irq(r8a66597, pipenum, NRDYENB) | ||
632 | |||
633 | #endif /* __R8A66597_H__ */ | ||
634 | |||
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index d22da26ff167..76c555a67dac 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -730,10 +730,9 @@ static int uhci_rh_resume(struct usb_hcd *hcd) | |||
730 | int rc = 0; | 730 | int rc = 0; |
731 | 731 | ||
732 | spin_lock_irq(&uhci->lock); | 732 | spin_lock_irq(&uhci->lock); |
733 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { | 733 | if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) |
734 | dev_warn(&hcd->self.root_hub->dev, "HC isn't running!\n"); | ||
735 | rc = -ESHUTDOWN; | 734 | rc = -ESHUTDOWN; |
736 | } else if (!uhci->dead) | 735 | else if (!uhci->dead) |
737 | wakeup_rh(uhci); | 736 | wakeup_rh(uhci); |
738 | spin_unlock_irq(&uhci->lock); | 737 | spin_unlock_irq(&uhci->lock); |
739 | return rc; | 738 | return rc; |
diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 77145f9db043..d72c42e5f22d 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c | |||
@@ -108,8 +108,6 @@ struct adu_device { | |||
108 | struct urb* interrupt_out_urb; | 108 | struct urb* interrupt_out_urb; |
109 | }; | 109 | }; |
110 | 110 | ||
111 | /* prevent races between open() and disconnect */ | ||
112 | static DEFINE_MUTEX(disconnect_mutex); | ||
113 | static struct usb_driver adu_driver; | 111 | static struct usb_driver adu_driver; |
114 | 112 | ||
115 | static void adu_debug_data(int level, const char *function, int size, | 113 | static void adu_debug_data(int level, const char *function, int size, |
@@ -256,8 +254,6 @@ static int adu_open(struct inode *inode, struct file *file) | |||
256 | 254 | ||
257 | subminor = iminor(inode); | 255 | subminor = iminor(inode); |
258 | 256 | ||
259 | mutex_lock(&disconnect_mutex); | ||
260 | |||
261 | interface = usb_find_interface(&adu_driver, subminor); | 257 | interface = usb_find_interface(&adu_driver, subminor); |
262 | if (!interface) { | 258 | if (!interface) { |
263 | err("%s - error, can't find device for minor %d", | 259 | err("%s - error, can't find device for minor %d", |
@@ -306,7 +302,6 @@ static int adu_open(struct inode *inode, struct file *file) | |||
306 | up(&dev->sem); | 302 | up(&dev->sem); |
307 | 303 | ||
308 | exit_no_device: | 304 | exit_no_device: |
309 | mutex_unlock(&disconnect_mutex); | ||
310 | dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); | 305 | dbg(2,"%s : leave, return value %d ", __FUNCTION__, retval); |
311 | 306 | ||
312 | return retval; | 307 | return retval; |
@@ -318,12 +313,6 @@ static int adu_release_internal(struct adu_device *dev) | |||
318 | 313 | ||
319 | dbg(2," %s : enter", __FUNCTION__); | 314 | dbg(2," %s : enter", __FUNCTION__); |
320 | 315 | ||
321 | if (dev->udev == NULL) { | ||
322 | /* the device was unplugged before the file was released */ | ||
323 | adu_delete(dev); | ||
324 | goto exit; | ||
325 | } | ||
326 | |||
327 | /* decrement our usage count for the device */ | 316 | /* decrement our usage count for the device */ |
328 | --dev->open_count; | 317 | --dev->open_count; |
329 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); | 318 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); |
@@ -332,7 +321,6 @@ static int adu_release_internal(struct adu_device *dev) | |||
332 | dev->open_count = 0; | 321 | dev->open_count = 0; |
333 | } | 322 | } |
334 | 323 | ||
335 | exit: | ||
336 | dbg(2," %s : leave", __FUNCTION__); | 324 | dbg(2," %s : leave", __FUNCTION__); |
337 | return retval; | 325 | return retval; |
338 | } | 326 | } |
@@ -367,8 +355,15 @@ static int adu_release(struct inode *inode, struct file *file) | |||
367 | goto exit; | 355 | goto exit; |
368 | } | 356 | } |
369 | 357 | ||
370 | /* do the work */ | 358 | if (dev->udev == NULL) { |
371 | retval = adu_release_internal(dev); | 359 | /* the device was unplugged before the file was released */ |
360 | up(&dev->sem); | ||
361 | adu_delete(dev); | ||
362 | dev = NULL; | ||
363 | } else { | ||
364 | /* do the work */ | ||
365 | retval = adu_release_internal(dev); | ||
366 | } | ||
372 | 367 | ||
373 | exit: | 368 | exit: |
374 | if (dev) | 369 | if (dev) |
@@ -831,19 +826,17 @@ static void adu_disconnect(struct usb_interface *interface) | |||
831 | 826 | ||
832 | dbg(2," %s : enter", __FUNCTION__); | 827 | dbg(2," %s : enter", __FUNCTION__); |
833 | 828 | ||
834 | mutex_lock(&disconnect_mutex); /* not interruptible */ | ||
835 | |||
836 | dev = usb_get_intfdata(interface); | 829 | dev = usb_get_intfdata(interface); |
837 | usb_set_intfdata(interface, NULL); | 830 | usb_set_intfdata(interface, NULL); |
838 | 831 | ||
839 | down(&dev->sem); /* not interruptible */ | ||
840 | |||
841 | minor = dev->minor; | 832 | minor = dev->minor; |
842 | 833 | ||
843 | /* give back our minor */ | 834 | /* give back our minor */ |
844 | usb_deregister_dev(interface, &adu_class); | 835 | usb_deregister_dev(interface, &adu_class); |
845 | dev->minor = 0; | 836 | dev->minor = 0; |
846 | 837 | ||
838 | down(&dev->sem); /* not interruptible */ | ||
839 | |||
847 | /* if the device is not opened, then we clean up right now */ | 840 | /* if the device is not opened, then we clean up right now */ |
848 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); | 841 | dbg(2," %s : open count %d", __FUNCTION__, dev->open_count); |
849 | if (!dev->open_count) { | 842 | if (!dev->open_count) { |
@@ -854,8 +847,6 @@ static void adu_disconnect(struct usb_interface *interface) | |||
854 | up(&dev->sem); | 847 | up(&dev->sem); |
855 | } | 848 | } |
856 | 849 | ||
857 | mutex_unlock(&disconnect_mutex); | ||
858 | |||
859 | dev_info(&interface->dev, "ADU device adutux%d now disconnected", | 850 | dev_info(&interface->dev, "ADU device adutux%d now disconnected", |
860 | (minor - ADU_MINOR_BASE)); | 851 | (minor - ADU_MINOR_BASE)); |
861 | 852 | ||
diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index cac1500cba62..1fd5fc220cd7 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c | |||
@@ -2034,12 +2034,12 @@ static void auerswald_disconnect (struct usb_interface *intf) | |||
2034 | if (!cp) | 2034 | if (!cp) |
2035 | return; | 2035 | return; |
2036 | 2036 | ||
2037 | down (&cp->mutex); | ||
2038 | info ("device /dev/%s now disconnecting", cp->name); | ||
2039 | |||
2040 | /* give back our USB minor number */ | 2037 | /* give back our USB minor number */ |
2041 | usb_deregister_dev(intf, &auerswald_class); | 2038 | usb_deregister_dev(intf, &auerswald_class); |
2042 | 2039 | ||
2040 | down (&cp->mutex); | ||
2041 | info ("device /dev/%s now disconnecting", cp->name); | ||
2042 | |||
2043 | /* Stop the interrupt endpoint */ | 2043 | /* Stop the interrupt endpoint */ |
2044 | auerswald_int_release (cp); | 2044 | auerswald_int_release (cp); |
2045 | 2045 | ||
diff --git a/drivers/usb/misc/berry_charge.c b/drivers/usb/misc/berry_charge.c index b15f2fd8dab4..92c1d2768df9 100644 --- a/drivers/usb/misc/berry_charge.c +++ b/drivers/usb/misc/berry_charge.c | |||
@@ -26,8 +26,11 @@ | |||
26 | 26 | ||
27 | #define RIM_VENDOR 0x0fca | 27 | #define RIM_VENDOR 0x0fca |
28 | #define BLACKBERRY 0x0001 | 28 | #define BLACKBERRY 0x0001 |
29 | #define BLACKBERRY_PEARL_DUAL 0x0004 | ||
30 | #define BLACKBERRY_PEARL 0x0006 | ||
29 | 31 | ||
30 | static int debug; | 32 | static int debug; |
33 | static int pearl_dual_mode = 1; | ||
31 | 34 | ||
32 | #ifdef dbg | 35 | #ifdef dbg |
33 | #undef dbg | 36 | #undef dbg |
@@ -38,6 +41,8 @@ static int debug; | |||
38 | 41 | ||
39 | static struct usb_device_id id_table [] = { | 42 | static struct usb_device_id id_table [] = { |
40 | { USB_DEVICE(RIM_VENDOR, BLACKBERRY) }, | 43 | { USB_DEVICE(RIM_VENDOR, BLACKBERRY) }, |
44 | { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL) }, | ||
45 | { USB_DEVICE(RIM_VENDOR, BLACKBERRY_PEARL_DUAL) }, | ||
41 | { }, /* Terminating entry */ | 46 | { }, /* Terminating entry */ |
42 | }; | 47 | }; |
43 | MODULE_DEVICE_TABLE(usb, id_table); | 48 | MODULE_DEVICE_TABLE(usb, id_table); |
@@ -86,6 +91,30 @@ static int magic_charge(struct usb_device *udev) | |||
86 | return retval; | 91 | return retval; |
87 | } | 92 | } |
88 | 93 | ||
94 | static int magic_dual_mode(struct usb_device *udev) | ||
95 | { | ||
96 | char *dummy_buffer = kzalloc(2, GFP_KERNEL); | ||
97 | int retval; | ||
98 | |||
99 | if (!dummy_buffer) | ||
100 | return -ENOMEM; | ||
101 | |||
102 | /* send magic command so that the Blackberry Pearl device exposes | ||
103 | * two interfaces: both the USB mass-storage one and one which can | ||
104 | * be used for database access. */ | ||
105 | dbg(&udev->dev, "Sending magic pearl command\n"); | ||
106 | retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), | ||
107 | 0xa9, 0xc0, 1, 1, dummy_buffer, 2, 100); | ||
108 | dbg(&udev->dev, "Magic pearl command returned %d\n", retval); | ||
109 | |||
110 | dbg(&udev->dev, "Calling set_configuration\n"); | ||
111 | retval = usb_driver_set_configuration(udev, 1); | ||
112 | if (retval) | ||
113 | dev_err(&udev->dev, "Set Configuration failed :%d.\n", retval); | ||
114 | |||
115 | return retval; | ||
116 | } | ||
117 | |||
89 | static int berry_probe(struct usb_interface *intf, | 118 | static int berry_probe(struct usb_interface *intf, |
90 | const struct usb_device_id *id) | 119 | const struct usb_device_id *id) |
91 | { | 120 | { |
@@ -105,6 +134,10 @@ static int berry_probe(struct usb_interface *intf, | |||
105 | /* turn the power on */ | 134 | /* turn the power on */ |
106 | magic_charge(udev); | 135 | magic_charge(udev); |
107 | 136 | ||
137 | if ((le16_to_cpu(udev->descriptor.idProduct) == BLACKBERRY_PEARL) && | ||
138 | (pearl_dual_mode)) | ||
139 | magic_dual_mode(udev); | ||
140 | |||
108 | /* we don't really want to bind to the device, userspace programs can | 141 | /* we don't really want to bind to the device, userspace programs can |
109 | * handle the syncing just fine, so get outta here. */ | 142 | * handle the syncing just fine, so get outta here. */ |
110 | return -ENODEV; | 143 | return -ENODEV; |
@@ -138,3 +171,5 @@ MODULE_LICENSE("GPL"); | |||
138 | MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>"); | 171 | MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>"); |
139 | module_param(debug, bool, S_IRUGO | S_IWUSR); | 172 | module_param(debug, bool, S_IRUGO | S_IWUSR); |
140 | MODULE_PARM_DESC(debug, "Debug enabled or not"); | 173 | MODULE_PARM_DESC(debug, "Debug enabled or not"); |
174 | module_param(pearl_dual_mode, bool, S_IRUGO | S_IWUSR); | ||
175 | MODULE_PARM_DESC(pearl_dual_mode, "Change Blackberry Pearl to run in dual mode"); | ||
diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 8d0e360636e6..e6fd024024f5 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c | |||
@@ -119,9 +119,6 @@ static struct usb_driver idmouse_driver = { | |||
119 | .id_table = idmouse_table, | 119 | .id_table = idmouse_table, |
120 | }; | 120 | }; |
121 | 121 | ||
122 | /* prevent races between open() and disconnect() */ | ||
123 | static DEFINE_MUTEX(disconnect_mutex); | ||
124 | |||
125 | static int idmouse_create_image(struct usb_idmouse *dev) | 122 | static int idmouse_create_image(struct usb_idmouse *dev) |
126 | { | 123 | { |
127 | int bytes_read; | 124 | int bytes_read; |
@@ -211,21 +208,15 @@ static int idmouse_open(struct inode *inode, struct file *file) | |||
211 | struct usb_interface *interface; | 208 | struct usb_interface *interface; |
212 | int result; | 209 | int result; |
213 | 210 | ||
214 | /* prevent disconnects */ | ||
215 | mutex_lock(&disconnect_mutex); | ||
216 | |||
217 | /* get the interface from minor number and driver information */ | 211 | /* get the interface from minor number and driver information */ |
218 | interface = usb_find_interface (&idmouse_driver, iminor (inode)); | 212 | interface = usb_find_interface (&idmouse_driver, iminor (inode)); |
219 | if (!interface) { | 213 | if (!interface) |
220 | mutex_unlock(&disconnect_mutex); | ||
221 | return -ENODEV; | 214 | return -ENODEV; |
222 | } | 215 | |
223 | /* get the device information block from the interface */ | 216 | /* get the device information block from the interface */ |
224 | dev = usb_get_intfdata(interface); | 217 | dev = usb_get_intfdata(interface); |
225 | if (!dev) { | 218 | if (!dev) |
226 | mutex_unlock(&disconnect_mutex); | ||
227 | return -ENODEV; | 219 | return -ENODEV; |
228 | } | ||
229 | 220 | ||
230 | /* lock this device */ | 221 | /* lock this device */ |
231 | down(&dev->sem); | 222 | down(&dev->sem); |
@@ -255,9 +246,6 @@ error: | |||
255 | 246 | ||
256 | /* unlock this device */ | 247 | /* unlock this device */ |
257 | up(&dev->sem); | 248 | up(&dev->sem); |
258 | |||
259 | /* unlock the disconnect semaphore */ | ||
260 | mutex_unlock(&disconnect_mutex); | ||
261 | return result; | 249 | return result; |
262 | } | 250 | } |
263 | 251 | ||
@@ -265,15 +253,10 @@ static int idmouse_release(struct inode *inode, struct file *file) | |||
265 | { | 253 | { |
266 | struct usb_idmouse *dev; | 254 | struct usb_idmouse *dev; |
267 | 255 | ||
268 | /* prevent a race condition with open() */ | ||
269 | mutex_lock(&disconnect_mutex); | ||
270 | |||
271 | dev = file->private_data; | 256 | dev = file->private_data; |
272 | 257 | ||
273 | if (dev == NULL) { | 258 | if (dev == NULL) |
274 | mutex_unlock(&disconnect_mutex); | ||
275 | return -ENODEV; | 259 | return -ENODEV; |
276 | } | ||
277 | 260 | ||
278 | /* lock our device */ | 261 | /* lock our device */ |
279 | down(&dev->sem); | 262 | down(&dev->sem); |
@@ -281,7 +264,6 @@ static int idmouse_release(struct inode *inode, struct file *file) | |||
281 | /* are we really open? */ | 264 | /* are we really open? */ |
282 | if (dev->open <= 0) { | 265 | if (dev->open <= 0) { |
283 | up(&dev->sem); | 266 | up(&dev->sem); |
284 | mutex_unlock(&disconnect_mutex); | ||
285 | return -ENODEV; | 267 | return -ENODEV; |
286 | } | 268 | } |
287 | 269 | ||
@@ -291,12 +273,9 @@ static int idmouse_release(struct inode *inode, struct file *file) | |||
291 | /* the device was unplugged before the file was released */ | 273 | /* the device was unplugged before the file was released */ |
292 | up(&dev->sem); | 274 | up(&dev->sem); |
293 | idmouse_delete(dev); | 275 | idmouse_delete(dev); |
294 | mutex_unlock(&disconnect_mutex); | 276 | } else { |
295 | return 0; | 277 | up(&dev->sem); |
296 | } | 278 | } |
297 | |||
298 | up(&dev->sem); | ||
299 | mutex_unlock(&disconnect_mutex); | ||
300 | return 0; | 279 | return 0; |
301 | } | 280 | } |
302 | 281 | ||
@@ -391,30 +370,27 @@ static void idmouse_disconnect(struct usb_interface *interface) | |||
391 | { | 370 | { |
392 | struct usb_idmouse *dev; | 371 | struct usb_idmouse *dev; |
393 | 372 | ||
394 | /* prevent races with open() */ | ||
395 | mutex_lock(&disconnect_mutex); | ||
396 | |||
397 | /* get device structure */ | 373 | /* get device structure */ |
398 | dev = usb_get_intfdata(interface); | 374 | dev = usb_get_intfdata(interface); |
399 | usb_set_intfdata(interface, NULL); | 375 | usb_set_intfdata(interface, NULL); |
400 | 376 | ||
401 | /* lock it */ | ||
402 | down(&dev->sem); | ||
403 | |||
404 | /* give back our minor */ | 377 | /* give back our minor */ |
405 | usb_deregister_dev(interface, &idmouse_class); | 378 | usb_deregister_dev(interface, &idmouse_class); |
406 | 379 | ||
380 | /* lock it */ | ||
381 | down(&dev->sem); | ||
382 | |||
407 | /* prevent device read, write and ioctl */ | 383 | /* prevent device read, write and ioctl */ |
408 | dev->present = 0; | 384 | dev->present = 0; |
409 | 385 | ||
410 | /* unlock */ | ||
411 | up(&dev->sem); | ||
412 | |||
413 | /* if the device is opened, idmouse_release will clean this up */ | 386 | /* if the device is opened, idmouse_release will clean this up */ |
414 | if (!dev->open) | 387 | if (!dev->open) { |
388 | up(&dev->sem); | ||
415 | idmouse_delete(dev); | 389 | idmouse_delete(dev); |
416 | 390 | } else { | |
417 | mutex_unlock(&disconnect_mutex); | 391 | /* unlock */ |
392 | up(&dev->sem); | ||
393 | } | ||
418 | 394 | ||
419 | info("%s disconnected", DRIVER_DESC); | 395 | info("%s disconnected", DRIVER_DESC); |
420 | } | 396 | } |
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 3bb33f7bfa36..28548d186712 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c | |||
@@ -100,8 +100,6 @@ struct iowarrior { | |||
100 | /*--------------*/ | 100 | /*--------------*/ |
101 | /* globals */ | 101 | /* globals */ |
102 | /*--------------*/ | 102 | /*--------------*/ |
103 | /* prevent races between open() and disconnect() */ | ||
104 | static DECLARE_MUTEX(disconnect_sem); | ||
105 | 103 | ||
106 | /* | 104 | /* |
107 | * USB spec identifies 5 second timeouts. | 105 | * USB spec identifies 5 second timeouts. |
@@ -600,22 +598,18 @@ static int iowarrior_open(struct inode *inode, struct file *file) | |||
600 | 598 | ||
601 | subminor = iminor(inode); | 599 | subminor = iminor(inode); |
602 | 600 | ||
603 | /* prevent disconnects */ | ||
604 | down(&disconnect_sem); | ||
605 | |||
606 | interface = usb_find_interface(&iowarrior_driver, subminor); | 601 | interface = usb_find_interface(&iowarrior_driver, subminor); |
607 | if (!interface) { | 602 | if (!interface) { |
608 | err("%s - error, can't find device for minor %d", __FUNCTION__, | 603 | err("%s - error, can't find device for minor %d", __FUNCTION__, |
609 | subminor); | 604 | subminor); |
610 | retval = -ENODEV; | 605 | return -ENODEV; |
611 | goto out; | ||
612 | } | 606 | } |
613 | 607 | ||
614 | dev = usb_get_intfdata(interface); | 608 | dev = usb_get_intfdata(interface); |
615 | if (!dev) { | 609 | if (!dev) |
616 | retval = -ENODEV; | 610 | return -ENODEV; |
617 | goto out; | 611 | |
618 | } | 612 | mutex_lock(&dev->mutex); |
619 | 613 | ||
620 | /* Only one process can open each device, no sharing. */ | 614 | /* Only one process can open each device, no sharing. */ |
621 | if (dev->opened) { | 615 | if (dev->opened) { |
@@ -636,7 +630,7 @@ static int iowarrior_open(struct inode *inode, struct file *file) | |||
636 | retval = 0; | 630 | retval = 0; |
637 | 631 | ||
638 | out: | 632 | out: |
639 | up(&disconnect_sem); | 633 | mutex_unlock(&dev->mutex); |
640 | return retval; | 634 | return retval; |
641 | } | 635 | } |
642 | 636 | ||
@@ -868,19 +862,16 @@ static void iowarrior_disconnect(struct usb_interface *interface) | |||
868 | struct iowarrior *dev; | 862 | struct iowarrior *dev; |
869 | int minor; | 863 | int minor; |
870 | 864 | ||
871 | /* prevent races with open() */ | ||
872 | down(&disconnect_sem); | ||
873 | |||
874 | dev = usb_get_intfdata(interface); | 865 | dev = usb_get_intfdata(interface); |
875 | usb_set_intfdata(interface, NULL); | 866 | usb_set_intfdata(interface, NULL); |
876 | 867 | ||
877 | mutex_lock(&dev->mutex); | ||
878 | |||
879 | minor = dev->minor; | 868 | minor = dev->minor; |
880 | 869 | ||
881 | /* give back our minor */ | 870 | /* give back our minor */ |
882 | usb_deregister_dev(interface, &iowarrior_class); | 871 | usb_deregister_dev(interface, &iowarrior_class); |
883 | 872 | ||
873 | mutex_lock(&dev->mutex); | ||
874 | |||
884 | /* prevent device read, write and ioctl */ | 875 | /* prevent device read, write and ioctl */ |
885 | dev->present = 0; | 876 | dev->present = 0; |
886 | 877 | ||
@@ -898,7 +889,6 @@ static void iowarrior_disconnect(struct usb_interface *interface) | |||
898 | /* no process is using the device, cleanup now */ | 889 | /* no process is using the device, cleanup now */ |
899 | iowarrior_delete(dev); | 890 | iowarrior_delete(dev); |
900 | } | 891 | } |
901 | up(&disconnect_sem); | ||
902 | 892 | ||
903 | dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n", | 893 | dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n", |
904 | minor - IOWARRIOR_MINOR_BASE); | 894 | minor - IOWARRIOR_MINOR_BASE); |
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 7bad49404762..5e950b90c541 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c | |||
@@ -176,9 +176,6 @@ struct ld_usb { | |||
176 | int interrupt_out_busy; | 176 | int interrupt_out_busy; |
177 | }; | 177 | }; |
178 | 178 | ||
179 | /* prevent races between open() and disconnect() */ | ||
180 | static DEFINE_MUTEX(disconnect_mutex); | ||
181 | |||
182 | static struct usb_driver ld_usb_driver; | 179 | static struct usb_driver ld_usb_driver; |
183 | 180 | ||
184 | /** | 181 | /** |
@@ -298,35 +295,28 @@ static int ld_usb_open(struct inode *inode, struct file *file) | |||
298 | { | 295 | { |
299 | struct ld_usb *dev; | 296 | struct ld_usb *dev; |
300 | int subminor; | 297 | int subminor; |
301 | int retval = 0; | 298 | int retval; |
302 | struct usb_interface *interface; | 299 | struct usb_interface *interface; |
303 | 300 | ||
304 | nonseekable_open(inode, file); | 301 | nonseekable_open(inode, file); |
305 | subminor = iminor(inode); | 302 | subminor = iminor(inode); |
306 | 303 | ||
307 | mutex_lock(&disconnect_mutex); | ||
308 | |||
309 | interface = usb_find_interface(&ld_usb_driver, subminor); | 304 | interface = usb_find_interface(&ld_usb_driver, subminor); |
310 | 305 | ||
311 | if (!interface) { | 306 | if (!interface) { |
312 | err("%s - error, can't find device for minor %d\n", | 307 | err("%s - error, can't find device for minor %d\n", |
313 | __FUNCTION__, subminor); | 308 | __FUNCTION__, subminor); |
314 | retval = -ENODEV; | 309 | return -ENODEV; |
315 | goto unlock_disconnect_exit; | ||
316 | } | 310 | } |
317 | 311 | ||
318 | dev = usb_get_intfdata(interface); | 312 | dev = usb_get_intfdata(interface); |
319 | 313 | ||
320 | if (!dev) { | 314 | if (!dev) |
321 | retval = -ENODEV; | 315 | return -ENODEV; |
322 | goto unlock_disconnect_exit; | ||
323 | } | ||
324 | 316 | ||
325 | /* lock this device */ | 317 | /* lock this device */ |
326 | if (down_interruptible(&dev->sem)) { | 318 | if (down_interruptible(&dev->sem)) |
327 | retval = -ERESTARTSYS; | 319 | return -ERESTARTSYS; |
328 | goto unlock_disconnect_exit; | ||
329 | } | ||
330 | 320 | ||
331 | /* allow opening only once */ | 321 | /* allow opening only once */ |
332 | if (dev->open_count) { | 322 | if (dev->open_count) { |
@@ -366,9 +356,6 @@ static int ld_usb_open(struct inode *inode, struct file *file) | |||
366 | unlock_exit: | 356 | unlock_exit: |
367 | up(&dev->sem); | 357 | up(&dev->sem); |
368 | 358 | ||
369 | unlock_disconnect_exit: | ||
370 | mutex_unlock(&disconnect_mutex); | ||
371 | |||
372 | return retval; | 359 | return retval; |
373 | } | 360 | } |
374 | 361 | ||
@@ -766,18 +753,16 @@ static void ld_usb_disconnect(struct usb_interface *intf) | |||
766 | struct ld_usb *dev; | 753 | struct ld_usb *dev; |
767 | int minor; | 754 | int minor; |
768 | 755 | ||
769 | mutex_lock(&disconnect_mutex); | ||
770 | |||
771 | dev = usb_get_intfdata(intf); | 756 | dev = usb_get_intfdata(intf); |
772 | usb_set_intfdata(intf, NULL); | 757 | usb_set_intfdata(intf, NULL); |
773 | 758 | ||
774 | down(&dev->sem); | ||
775 | |||
776 | minor = intf->minor; | 759 | minor = intf->minor; |
777 | 760 | ||
778 | /* give back our minor */ | 761 | /* give back our minor */ |
779 | usb_deregister_dev(intf, &ld_usb_class); | 762 | usb_deregister_dev(intf, &ld_usb_class); |
780 | 763 | ||
764 | down(&dev->sem); | ||
765 | |||
781 | /* if the device is not opened, then we clean up right now */ | 766 | /* if the device is not opened, then we clean up right now */ |
782 | if (!dev->open_count) { | 767 | if (!dev->open_count) { |
783 | up(&dev->sem); | 768 | up(&dev->sem); |
@@ -787,8 +772,6 @@ static void ld_usb_disconnect(struct usb_interface *intf) | |||
787 | up(&dev->sem); | 772 | up(&dev->sem); |
788 | } | 773 | } |
789 | 774 | ||
790 | mutex_unlock(&disconnect_mutex); | ||
791 | |||
792 | dev_info(&intf->dev, "LD USB Device #%d now disconnected\n", | 775 | dev_info(&intf->dev, "LD USB Device #%d now disconnected\n", |
793 | (minor - USB_LD_MINOR_BASE)); | 776 | (minor - USB_LD_MINOR_BASE)); |
794 | } | 777 | } |
diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 1713e19a7899..2ed0daea894c 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c | |||
@@ -254,9 +254,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_devic | |||
254 | static void tower_disconnect (struct usb_interface *interface); | 254 | static void tower_disconnect (struct usb_interface *interface); |
255 | 255 | ||
256 | 256 | ||
257 | /* prevent races between open() and disconnect */ | ||
258 | static DEFINE_MUTEX (disconnect_mutex); | ||
259 | |||
260 | /* file operations needed when we register this driver */ | 257 | /* file operations needed when we register this driver */ |
261 | static const struct file_operations tower_fops = { | 258 | static const struct file_operations tower_fops = { |
262 | .owner = THIS_MODULE, | 259 | .owner = THIS_MODULE, |
@@ -344,28 +341,26 @@ static int tower_open (struct inode *inode, struct file *file) | |||
344 | nonseekable_open(inode, file); | 341 | nonseekable_open(inode, file); |
345 | subminor = iminor(inode); | 342 | subminor = iminor(inode); |
346 | 343 | ||
347 | mutex_lock (&disconnect_mutex); | ||
348 | |||
349 | interface = usb_find_interface (&tower_driver, subminor); | 344 | interface = usb_find_interface (&tower_driver, subminor); |
350 | 345 | ||
351 | if (!interface) { | 346 | if (!interface) { |
352 | err ("%s - error, can't find device for minor %d", | 347 | err ("%s - error, can't find device for minor %d", |
353 | __FUNCTION__, subminor); | 348 | __FUNCTION__, subminor); |
354 | retval = -ENODEV; | 349 | retval = -ENODEV; |
355 | goto unlock_disconnect_exit; | 350 | goto exit; |
356 | } | 351 | } |
357 | 352 | ||
358 | dev = usb_get_intfdata(interface); | 353 | dev = usb_get_intfdata(interface); |
359 | 354 | ||
360 | if (!dev) { | 355 | if (!dev) { |
361 | retval = -ENODEV; | 356 | retval = -ENODEV; |
362 | goto unlock_disconnect_exit; | 357 | goto exit; |
363 | } | 358 | } |
364 | 359 | ||
365 | /* lock this device */ | 360 | /* lock this device */ |
366 | if (down_interruptible (&dev->sem)) { | 361 | if (down_interruptible (&dev->sem)) { |
367 | retval = -ERESTARTSYS; | 362 | retval = -ERESTARTSYS; |
368 | goto unlock_disconnect_exit; | 363 | goto exit; |
369 | } | 364 | } |
370 | 365 | ||
371 | /* allow opening only once */ | 366 | /* allow opening only once */ |
@@ -421,9 +416,7 @@ static int tower_open (struct inode *inode, struct file *file) | |||
421 | unlock_exit: | 416 | unlock_exit: |
422 | up (&dev->sem); | 417 | up (&dev->sem); |
423 | 418 | ||
424 | unlock_disconnect_exit: | 419 | exit: |
425 | mutex_unlock (&disconnect_mutex); | ||
426 | |||
427 | dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval); | 420 | dbg(2, "%s: leave, return value %d ", __FUNCTION__, retval); |
428 | 421 | ||
429 | return retval; | 422 | return retval; |
@@ -993,19 +986,16 @@ static void tower_disconnect (struct usb_interface *interface) | |||
993 | 986 | ||
994 | dbg(2, "%s: enter", __FUNCTION__); | 987 | dbg(2, "%s: enter", __FUNCTION__); |
995 | 988 | ||
996 | mutex_lock (&disconnect_mutex); | ||
997 | |||
998 | dev = usb_get_intfdata (interface); | 989 | dev = usb_get_intfdata (interface); |
999 | usb_set_intfdata (interface, NULL); | 990 | usb_set_intfdata (interface, NULL); |
1000 | 991 | ||
1001 | |||
1002 | down (&dev->sem); | ||
1003 | |||
1004 | minor = dev->minor; | 992 | minor = dev->minor; |
1005 | 993 | ||
1006 | /* give back our minor */ | 994 | /* give back our minor */ |
1007 | usb_deregister_dev (interface, &tower_class); | 995 | usb_deregister_dev (interface, &tower_class); |
1008 | 996 | ||
997 | down (&dev->sem); | ||
998 | |||
1009 | /* if the device is not opened, then we clean up right now */ | 999 | /* if the device is not opened, then we clean up right now */ |
1010 | if (!dev->open_count) { | 1000 | if (!dev->open_count) { |
1011 | up (&dev->sem); | 1001 | up (&dev->sem); |
@@ -1015,8 +1005,6 @@ static void tower_disconnect (struct usb_interface *interface) | |||
1015 | up (&dev->sem); | 1005 | up (&dev->sem); |
1016 | } | 1006 | } |
1017 | 1007 | ||
1018 | mutex_unlock (&disconnect_mutex); | ||
1019 | |||
1020 | info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); | 1008 | info("LEGO USB Tower #%d now disconnected", (minor - LEGO_USB_TOWER_MINOR_BASE)); |
1021 | 1009 | ||
1022 | dbg(2, "%s: leave", __FUNCTION__); | 1010 | dbg(2, "%s: leave", __FUNCTION__); |
diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 6f8b134a79cb..9f37ba44c132 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c | |||
@@ -72,8 +72,6 @@ MODULE_PARM_DESC(last, "Number of last console to take over (1 - MAX_NR_CONSOLES | |||
72 | 72 | ||
73 | static struct usb_driver sisusb_driver; | 73 | static struct usb_driver sisusb_driver; |
74 | 74 | ||
75 | DEFINE_MUTEX(disconnect_mutex); | ||
76 | |||
77 | static void | 75 | static void |
78 | sisusb_free_buffers(struct sisusb_usb_data *sisusb) | 76 | sisusb_free_buffers(struct sisusb_usb_data *sisusb) |
79 | { | 77 | { |
@@ -2511,31 +2509,24 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2511 | struct usb_interface *interface; | 2509 | struct usb_interface *interface; |
2512 | int subminor = iminor(inode); | 2510 | int subminor = iminor(inode); |
2513 | 2511 | ||
2514 | mutex_lock(&disconnect_mutex); | ||
2515 | |||
2516 | if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { | 2512 | if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { |
2517 | printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", | 2513 | printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", |
2518 | subminor); | 2514 | subminor); |
2519 | mutex_unlock(&disconnect_mutex); | ||
2520 | return -ENODEV; | 2515 | return -ENODEV; |
2521 | } | 2516 | } |
2522 | 2517 | ||
2523 | if (!(sisusb = usb_get_intfdata(interface))) { | 2518 | if (!(sisusb = usb_get_intfdata(interface))) |
2524 | mutex_unlock(&disconnect_mutex); | ||
2525 | return -ENODEV; | 2519 | return -ENODEV; |
2526 | } | ||
2527 | 2520 | ||
2528 | mutex_lock(&sisusb->lock); | 2521 | mutex_lock(&sisusb->lock); |
2529 | 2522 | ||
2530 | if (!sisusb->present || !sisusb->ready) { | 2523 | if (!sisusb->present || !sisusb->ready) { |
2531 | mutex_unlock(&sisusb->lock); | 2524 | mutex_unlock(&sisusb->lock); |
2532 | mutex_unlock(&disconnect_mutex); | ||
2533 | return -ENODEV; | 2525 | return -ENODEV; |
2534 | } | 2526 | } |
2535 | 2527 | ||
2536 | if (sisusb->isopen) { | 2528 | if (sisusb->isopen) { |
2537 | mutex_unlock(&sisusb->lock); | 2529 | mutex_unlock(&sisusb->lock); |
2538 | mutex_unlock(&disconnect_mutex); | ||
2539 | return -EBUSY; | 2530 | return -EBUSY; |
2540 | } | 2531 | } |
2541 | 2532 | ||
@@ -2543,7 +2534,6 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2543 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { | 2534 | if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { |
2544 | if (sisusb_init_gfxdevice(sisusb, 0)) { | 2535 | if (sisusb_init_gfxdevice(sisusb, 0)) { |
2545 | mutex_unlock(&sisusb->lock); | 2536 | mutex_unlock(&sisusb->lock); |
2546 | mutex_unlock(&disconnect_mutex); | ||
2547 | printk(KERN_ERR | 2537 | printk(KERN_ERR |
2548 | "sisusbvga[%d]: Failed to initialize " | 2538 | "sisusbvga[%d]: Failed to initialize " |
2549 | "device\n", | 2539 | "device\n", |
@@ -2552,7 +2542,6 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2552 | } | 2542 | } |
2553 | } else { | 2543 | } else { |
2554 | mutex_unlock(&sisusb->lock); | 2544 | mutex_unlock(&sisusb->lock); |
2555 | mutex_unlock(&disconnect_mutex); | ||
2556 | printk(KERN_ERR | 2545 | printk(KERN_ERR |
2557 | "sisusbvga[%d]: Device not attached to " | 2546 | "sisusbvga[%d]: Device not attached to " |
2558 | "USB 2.0 hub\n", | 2547 | "USB 2.0 hub\n", |
@@ -2570,8 +2559,6 @@ sisusb_open(struct inode *inode, struct file *file) | |||
2570 | 2559 | ||
2571 | mutex_unlock(&sisusb->lock); | 2560 | mutex_unlock(&sisusb->lock); |
2572 | 2561 | ||
2573 | mutex_unlock(&disconnect_mutex); | ||
2574 | |||
2575 | return 0; | 2562 | return 0; |
2576 | } | 2563 | } |
2577 | 2564 | ||
@@ -2601,12 +2588,8 @@ sisusb_release(struct inode *inode, struct file *file) | |||
2601 | struct sisusb_usb_data *sisusb; | 2588 | struct sisusb_usb_data *sisusb; |
2602 | int myminor; | 2589 | int myminor; |
2603 | 2590 | ||
2604 | mutex_lock(&disconnect_mutex); | 2591 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) |
2605 | |||
2606 | if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) { | ||
2607 | mutex_unlock(&disconnect_mutex); | ||
2608 | return -ENODEV; | 2592 | return -ENODEV; |
2609 | } | ||
2610 | 2593 | ||
2611 | mutex_lock(&sisusb->lock); | 2594 | mutex_lock(&sisusb->lock); |
2612 | 2595 | ||
@@ -2626,8 +2609,6 @@ sisusb_release(struct inode *inode, struct file *file) | |||
2626 | /* decrement the usage count on our device */ | 2609 | /* decrement the usage count on our device */ |
2627 | kref_put(&sisusb->kref, sisusb_delete); | 2610 | kref_put(&sisusb->kref, sisusb_delete); |
2628 | 2611 | ||
2629 | mutex_unlock(&disconnect_mutex); | ||
2630 | |||
2631 | return 0; | 2612 | return 0; |
2632 | } | 2613 | } |
2633 | 2614 | ||
@@ -3383,12 +3364,9 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3383 | sisusb_console_exit(sisusb); | 3364 | sisusb_console_exit(sisusb); |
3384 | #endif | 3365 | #endif |
3385 | 3366 | ||
3386 | /* The above code doesn't need the disconnect | 3367 | minor = sisusb->minor; |
3387 | * semaphore to be down; its meaning is to | 3368 | |
3388 | * protect all other routines from the disconnect | 3369 | usb_deregister_dev(intf, &usb_sisusb_class); |
3389 | * case, not the other way round. | ||
3390 | */ | ||
3391 | mutex_lock(&disconnect_mutex); | ||
3392 | 3370 | ||
3393 | mutex_lock(&sisusb->lock); | 3371 | mutex_lock(&sisusb->lock); |
3394 | 3372 | ||
@@ -3396,12 +3374,8 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3396 | if (!sisusb_wait_all_out_complete(sisusb)) | 3374 | if (!sisusb_wait_all_out_complete(sisusb)) |
3397 | sisusb_kill_all_busy(sisusb); | 3375 | sisusb_kill_all_busy(sisusb); |
3398 | 3376 | ||
3399 | minor = sisusb->minor; | ||
3400 | |||
3401 | usb_set_intfdata(intf, NULL); | 3377 | usb_set_intfdata(intf, NULL); |
3402 | 3378 | ||
3403 | usb_deregister_dev(intf, &usb_sisusb_class); | ||
3404 | |||
3405 | #ifdef SISUSB_OLD_CONFIG_COMPAT | 3379 | #ifdef SISUSB_OLD_CONFIG_COMPAT |
3406 | if (sisusb->ioctl32registered) { | 3380 | if (sisusb->ioctl32registered) { |
3407 | int ret; | 3381 | int ret; |
@@ -3426,8 +3400,6 @@ static void sisusb_disconnect(struct usb_interface *intf) | |||
3426 | /* decrement our usage count */ | 3400 | /* decrement our usage count */ |
3427 | kref_put(&sisusb->kref, sisusb_delete); | 3401 | kref_put(&sisusb->kref, sisusb_delete); |
3428 | 3402 | ||
3429 | mutex_unlock(&disconnect_mutex); | ||
3430 | |||
3431 | printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); | 3403 | printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor); |
3432 | } | 3404 | } |
3433 | 3405 | ||
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 5947afb0017e..8d0edc867f33 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c | |||
@@ -214,18 +214,13 @@ sisusbcon_init(struct vc_data *c, int init) | |||
214 | * are set up/restored. | 214 | * are set up/restored. |
215 | */ | 215 | */ |
216 | 216 | ||
217 | mutex_lock(&disconnect_mutex); | 217 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) |
218 | |||
219 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { | ||
220 | mutex_unlock(&disconnect_mutex); | ||
221 | return; | 218 | return; |
222 | } | ||
223 | 219 | ||
224 | mutex_lock(&sisusb->lock); | 220 | mutex_lock(&sisusb->lock); |
225 | 221 | ||
226 | if (!sisusb_sisusb_valid(sisusb)) { | 222 | if (!sisusb_sisusb_valid(sisusb)) { |
227 | mutex_unlock(&sisusb->lock); | 223 | mutex_unlock(&sisusb->lock); |
228 | mutex_unlock(&disconnect_mutex); | ||
229 | return; | 224 | return; |
230 | } | 225 | } |
231 | 226 | ||
@@ -264,8 +259,6 @@ sisusbcon_init(struct vc_data *c, int init) | |||
264 | 259 | ||
265 | mutex_unlock(&sisusb->lock); | 260 | mutex_unlock(&sisusb->lock); |
266 | 261 | ||
267 | mutex_unlock(&disconnect_mutex); | ||
268 | |||
269 | if (init) { | 262 | if (init) { |
270 | c->vc_cols = cols; | 263 | c->vc_cols = cols; |
271 | c->vc_rows = rows; | 264 | c->vc_rows = rows; |
@@ -284,12 +277,8 @@ sisusbcon_deinit(struct vc_data *c) | |||
284 | * and others, ie not under our control. | 277 | * and others, ie not under our control. |
285 | */ | 278 | */ |
286 | 279 | ||
287 | mutex_lock(&disconnect_mutex); | 280 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) |
288 | |||
289 | if (!(sisusb = sisusb_get_sisusb(c->vc_num))) { | ||
290 | mutex_unlock(&disconnect_mutex); | ||
291 | return; | 281 | return; |
292 | } | ||
293 | 282 | ||
294 | mutex_lock(&sisusb->lock); | 283 | mutex_lock(&sisusb->lock); |
295 | 284 | ||
@@ -314,8 +303,6 @@ sisusbcon_deinit(struct vc_data *c) | |||
314 | 303 | ||
315 | /* decrement the usage count on our sisusb */ | 304 | /* decrement the usage count on our sisusb */ |
316 | kref_put(&sisusb->kref, sisusb_delete); | 305 | kref_put(&sisusb->kref, sisusb_delete); |
317 | |||
318 | mutex_unlock(&disconnect_mutex); | ||
319 | } | 306 | } |
320 | 307 | ||
321 | /* interface routine */ | 308 | /* interface routine */ |
@@ -1490,14 +1477,11 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1490 | { | 1477 | { |
1491 | int i, ret, minor = sisusb->minor; | 1478 | int i, ret, minor = sisusb->minor; |
1492 | 1479 | ||
1493 | mutex_lock(&disconnect_mutex); | ||
1494 | |||
1495 | mutex_lock(&sisusb->lock); | 1480 | mutex_lock(&sisusb->lock); |
1496 | 1481 | ||
1497 | /* Erm.. that should not happen */ | 1482 | /* Erm.. that should not happen */ |
1498 | if (sisusb->haveconsole || !sisusb->SiS_Pr) { | 1483 | if (sisusb->haveconsole || !sisusb->SiS_Pr) { |
1499 | mutex_unlock(&sisusb->lock); | 1484 | mutex_unlock(&sisusb->lock); |
1500 | mutex_unlock(&disconnect_mutex); | ||
1501 | return 1; | 1485 | return 1; |
1502 | } | 1486 | } |
1503 | 1487 | ||
@@ -1508,14 +1492,12 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1508 | first > MAX_NR_CONSOLES || | 1492 | first > MAX_NR_CONSOLES || |
1509 | last > MAX_NR_CONSOLES) { | 1493 | last > MAX_NR_CONSOLES) { |
1510 | mutex_unlock(&sisusb->lock); | 1494 | mutex_unlock(&sisusb->lock); |
1511 | mutex_unlock(&disconnect_mutex); | ||
1512 | return 1; | 1495 | return 1; |
1513 | } | 1496 | } |
1514 | 1497 | ||
1515 | /* If gfxcore not initialized or no consoles given, quit graciously */ | 1498 | /* If gfxcore not initialized or no consoles given, quit graciously */ |
1516 | if (!sisusb->gfxinit || first < 1 || last < 1) { | 1499 | if (!sisusb->gfxinit || first < 1 || last < 1) { |
1517 | mutex_unlock(&sisusb->lock); | 1500 | mutex_unlock(&sisusb->lock); |
1518 | mutex_unlock(&disconnect_mutex); | ||
1519 | return 0; | 1501 | return 0; |
1520 | } | 1502 | } |
1521 | 1503 | ||
@@ -1526,7 +1508,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1526 | /* Set up text mode (and upload default font) */ | 1508 | /* Set up text mode (and upload default font) */ |
1527 | if (sisusb_reset_text_mode(sisusb, 1)) { | 1509 | if (sisusb_reset_text_mode(sisusb, 1)) { |
1528 | mutex_unlock(&sisusb->lock); | 1510 | mutex_unlock(&sisusb->lock); |
1529 | mutex_unlock(&disconnect_mutex); | ||
1530 | printk(KERN_ERR | 1511 | printk(KERN_ERR |
1531 | "sisusbvga[%d]: Failed to set up text mode\n", | 1512 | "sisusbvga[%d]: Failed to set up text mode\n", |
1532 | minor); | 1513 | minor); |
@@ -1550,7 +1531,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1550 | /* Allocate screen buffer */ | 1531 | /* Allocate screen buffer */ |
1551 | if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { | 1532 | if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) { |
1552 | mutex_unlock(&sisusb->lock); | 1533 | mutex_unlock(&sisusb->lock); |
1553 | mutex_unlock(&disconnect_mutex); | ||
1554 | printk(KERN_ERR | 1534 | printk(KERN_ERR |
1555 | "sisusbvga[%d]: Failed to allocate screen buffer\n", | 1535 | "sisusbvga[%d]: Failed to allocate screen buffer\n", |
1556 | minor); | 1536 | minor); |
@@ -1558,7 +1538,6 @@ sisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last) | |||
1558 | } | 1538 | } |
1559 | 1539 | ||
1560 | mutex_unlock(&sisusb->lock); | 1540 | mutex_unlock(&sisusb->lock); |
1561 | mutex_unlock(&disconnect_mutex); | ||
1562 | 1541 | ||
1563 | /* Now grab the desired console(s) */ | 1542 | /* Now grab the desired console(s) */ |
1564 | ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); | 1543 | ret = take_over_console(&sisusb_con, first - 1, last - 1, 0); |
diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.h b/drivers/usb/misc/sisusbvga/sisusb_init.h index f05f83268af4..864bc0e96591 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.h +++ b/drivers/usb/misc/sisusbvga/sisusb_init.h | |||
@@ -808,8 +808,6 @@ static const struct SiS_VCLKData SiSUSB_VCLKData[] = | |||
808 | { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ | 808 | { 0x2b,0xc2, 35} /* 0x71 768@576@60 */ |
809 | }; | 809 | }; |
810 | 810 | ||
811 | extern struct mutex disconnect_mutex; | ||
812 | |||
813 | int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); | 811 | int SiSUSBSetMode(struct SiS_Private *SiS_Pr, unsigned short ModeNo); |
814 | int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); | 812 | int SiSUSBSetVESAMode(struct SiS_Private *SiS_Pr, unsigned short VModeNo); |
815 | 813 | ||
diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 12bad8a205a7..504f7221b0d0 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c | |||
@@ -45,13 +45,13 @@ struct usb_lcd { | |||
45 | struct kref kref; | 45 | struct kref kref; |
46 | struct semaphore limit_sem; /* to stop writes at full throttle from | 46 | struct semaphore limit_sem; /* to stop writes at full throttle from |
47 | * using up all RAM */ | 47 | * using up all RAM */ |
48 | struct usb_anchor submitted; /* URBs to wait for before suspend */ | ||
48 | }; | 49 | }; |
49 | #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) | 50 | #define to_lcd_dev(d) container_of(d, struct usb_lcd, kref) |
50 | 51 | ||
51 | #define USB_LCD_CONCURRENT_WRITES 5 | 52 | #define USB_LCD_CONCURRENT_WRITES 5 |
52 | 53 | ||
53 | static struct usb_driver lcd_driver; | 54 | static struct usb_driver lcd_driver; |
54 | static DEFINE_MUTEX(usb_lcd_open_mutex); | ||
55 | 55 | ||
56 | 56 | ||
57 | static void lcd_delete(struct kref *kref) | 57 | static void lcd_delete(struct kref *kref) |
@@ -68,35 +68,35 @@ static int lcd_open(struct inode *inode, struct file *file) | |||
68 | { | 68 | { |
69 | struct usb_lcd *dev; | 69 | struct usb_lcd *dev; |
70 | struct usb_interface *interface; | 70 | struct usb_interface *interface; |
71 | int subminor; | 71 | int subminor, r; |
72 | int retval = 0; | ||
73 | 72 | ||
74 | subminor = iminor(inode); | 73 | subminor = iminor(inode); |
75 | 74 | ||
76 | mutex_lock(&usb_lcd_open_mutex); | ||
77 | interface = usb_find_interface(&lcd_driver, subminor); | 75 | interface = usb_find_interface(&lcd_driver, subminor); |
78 | if (!interface) { | 76 | if (!interface) { |
79 | err ("USBLCD: %s - error, can't find device for minor %d", | 77 | err ("USBLCD: %s - error, can't find device for minor %d", |
80 | __FUNCTION__, subminor); | 78 | __FUNCTION__, subminor); |
81 | retval = -ENODEV; | 79 | return -ENODEV; |
82 | goto exit; | ||
83 | } | 80 | } |
84 | 81 | ||
85 | dev = usb_get_intfdata(interface); | 82 | dev = usb_get_intfdata(interface); |
86 | if (!dev) { | 83 | if (!dev) |
87 | retval = -ENODEV; | 84 | return -ENODEV; |
88 | goto exit; | ||
89 | } | ||
90 | 85 | ||
91 | /* increment our usage count for the device */ | 86 | /* increment our usage count for the device */ |
92 | kref_get(&dev->kref); | 87 | kref_get(&dev->kref); |
93 | 88 | ||
89 | /* grab a power reference */ | ||
90 | r = usb_autopm_get_interface(interface); | ||
91 | if (r < 0) { | ||
92 | kref_put(&dev->kref, lcd_delete); | ||
93 | return r; | ||
94 | } | ||
95 | |||
94 | /* save our object in the file's private structure */ | 96 | /* save our object in the file's private structure */ |
95 | file->private_data = dev; | 97 | file->private_data = dev; |
96 | 98 | ||
97 | exit: | 99 | return 0; |
98 | mutex_unlock(&usb_lcd_open_mutex); | ||
99 | return retval; | ||
100 | } | 100 | } |
101 | 101 | ||
102 | static int lcd_release(struct inode *inode, struct file *file) | 102 | static int lcd_release(struct inode *inode, struct file *file) |
@@ -108,6 +108,7 @@ static int lcd_release(struct inode *inode, struct file *file) | |||
108 | return -ENODEV; | 108 | return -ENODEV; |
109 | 109 | ||
110 | /* decrement the count on our device */ | 110 | /* decrement the count on our device */ |
111 | usb_autopm_put_interface(dev->interface); | ||
111 | kref_put(&dev->kref, lcd_delete); | 112 | kref_put(&dev->kref, lcd_delete); |
112 | return 0; | 113 | return 0; |
113 | } | 114 | } |
@@ -233,12 +234,14 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz | |||
233 | usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), | 234 | usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), |
234 | buf, count, lcd_write_bulk_callback, dev); | 235 | buf, count, lcd_write_bulk_callback, dev); |
235 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 236 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
237 | |||
238 | usb_anchor_urb(urb, &dev->submitted); | ||
236 | 239 | ||
237 | /* send the data out the bulk port */ | 240 | /* send the data out the bulk port */ |
238 | retval = usb_submit_urb(urb, GFP_KERNEL); | 241 | retval = usb_submit_urb(urb, GFP_KERNEL); |
239 | if (retval) { | 242 | if (retval) { |
240 | err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval); | 243 | err("USBLCD: %s - failed submitting write urb, error %d", __FUNCTION__, retval); |
241 | goto error; | 244 | goto error_unanchor; |
242 | } | 245 | } |
243 | 246 | ||
244 | /* release our reference to this urb, the USB core will eventually free it entirely */ | 247 | /* release our reference to this urb, the USB core will eventually free it entirely */ |
@@ -246,7 +249,8 @@ static ssize_t lcd_write(struct file *file, const char __user * user_buffer, siz | |||
246 | 249 | ||
247 | exit: | 250 | exit: |
248 | return count; | 251 | return count; |
249 | 252 | error_unanchor: | |
253 | usb_unanchor_urb(urb); | ||
250 | error: | 254 | error: |
251 | usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); | 255 | usb_buffer_free(dev->udev, count, buf, urb->transfer_dma); |
252 | usb_free_urb(urb); | 256 | usb_free_urb(urb); |
@@ -291,6 +295,7 @@ static int lcd_probe(struct usb_interface *interface, const struct usb_device_id | |||
291 | } | 295 | } |
292 | kref_init(&dev->kref); | 296 | kref_init(&dev->kref); |
293 | sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES); | 297 | sema_init(&dev->limit_sem, USB_LCD_CONCURRENT_WRITES); |
298 | init_usb_anchor(&dev->submitted); | ||
294 | 299 | ||
295 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | 300 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
296 | dev->interface = interface; | 301 | dev->interface = interface; |
@@ -358,22 +363,41 @@ error: | |||
358 | return retval; | 363 | return retval; |
359 | } | 364 | } |
360 | 365 | ||
366 | static void lcd_draw_down(struct usb_lcd *dev) | ||
367 | { | ||
368 | int time; | ||
369 | |||
370 | time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000); | ||
371 | if (!time) | ||
372 | usb_kill_anchored_urbs(&dev->submitted); | ||
373 | } | ||
374 | |||
375 | static int lcd_suspend(struct usb_interface *intf, pm_message_t message) | ||
376 | { | ||
377 | struct usb_lcd *dev = usb_get_intfdata(intf); | ||
378 | |||
379 | if (!dev) | ||
380 | return 0; | ||
381 | lcd_draw_down(dev); | ||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static int lcd_resume (struct usb_interface *intf) | ||
386 | { | ||
387 | return 0; | ||
388 | } | ||
389 | |||
361 | static void lcd_disconnect(struct usb_interface *interface) | 390 | static void lcd_disconnect(struct usb_interface *interface) |
362 | { | 391 | { |
363 | struct usb_lcd *dev; | 392 | struct usb_lcd *dev; |
364 | int minor = interface->minor; | 393 | int minor = interface->minor; |
365 | 394 | ||
366 | /* prevent skel_open() from racing skel_disconnect() */ | ||
367 | mutex_lock(&usb_lcd_open_mutex); | ||
368 | |||
369 | dev = usb_get_intfdata(interface); | 395 | dev = usb_get_intfdata(interface); |
370 | usb_set_intfdata(interface, NULL); | 396 | usb_set_intfdata(interface, NULL); |
371 | 397 | ||
372 | /* give back our minor */ | 398 | /* give back our minor */ |
373 | usb_deregister_dev(interface, &lcd_class); | 399 | usb_deregister_dev(interface, &lcd_class); |
374 | 400 | ||
375 | mutex_unlock(&usb_lcd_open_mutex); | ||
376 | |||
377 | /* decrement our usage count */ | 401 | /* decrement our usage count */ |
378 | kref_put(&dev->kref, lcd_delete); | 402 | kref_put(&dev->kref, lcd_delete); |
379 | 403 | ||
@@ -384,7 +408,10 @@ static struct usb_driver lcd_driver = { | |||
384 | .name = "usblcd", | 408 | .name = "usblcd", |
385 | .probe = lcd_probe, | 409 | .probe = lcd_probe, |
386 | .disconnect = lcd_disconnect, | 410 | .disconnect = lcd_disconnect, |
411 | .suspend = lcd_suspend, | ||
412 | .resume = lcd_resume, | ||
387 | .id_table = id_table, | 413 | .id_table = id_table, |
414 | .supports_autosuspend = 1, | ||
388 | }; | 415 | }; |
389 | 416 | ||
390 | static int __init usb_lcd_init(void) | 417 | static int __init usb_lcd_init(void) |
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 0af11a66207c..c03dfd7a9d36 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * This is a binary format reader. | 4 | * This is a binary format reader. |
5 | * | 5 | * |
6 | * Copyright (C) 2006 Paolo Abeni (paolo.abeni@email.it) | 6 | * Copyright (C) 2006 Paolo Abeni (paolo.abeni@email.it) |
7 | * Copyright (C) 2006 Pete Zaitcev (zaitcev@redhat.com) | 7 | * Copyright (C) 2006,2007 Pete Zaitcev (zaitcev@redhat.com) |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
@@ -172,6 +172,7 @@ static inline struct mon_bin_hdr *MON_OFF2HDR(const struct mon_reader_bin *rp, | |||
172 | 172 | ||
173 | #define MON_RING_EMPTY(rp) ((rp)->b_cnt == 0) | 173 | #define MON_RING_EMPTY(rp) ((rp)->b_cnt == 0) |
174 | 174 | ||
175 | static struct class *mon_bin_class; | ||
175 | static dev_t mon_bin_dev0; | 176 | static dev_t mon_bin_dev0; |
176 | static struct cdev mon_bin_cdev; | 177 | static struct cdev mon_bin_cdev; |
177 | 178 | ||
@@ -1144,10 +1145,38 @@ static void mon_free_buff(struct mon_pgmap *map, int npages) | |||
1144 | free_page((unsigned long) map[n].ptr); | 1145 | free_page((unsigned long) map[n].ptr); |
1145 | } | 1146 | } |
1146 | 1147 | ||
1148 | int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus) | ||
1149 | { | ||
1150 | struct device *dev; | ||
1151 | unsigned minor = ubus? ubus->busnum: 0; | ||
1152 | |||
1153 | if (minor >= MON_BIN_MAX_MINOR) | ||
1154 | return 0; | ||
1155 | |||
1156 | dev = device_create(mon_bin_class, ubus? ubus->controller: NULL, | ||
1157 | MKDEV(MAJOR(mon_bin_dev0), minor), "usbmon%d", minor); | ||
1158 | if (IS_ERR(dev)) | ||
1159 | return 0; | ||
1160 | |||
1161 | mbus->classdev = dev; | ||
1162 | return 1; | ||
1163 | } | ||
1164 | |||
1165 | void mon_bin_del(struct mon_bus *mbus) | ||
1166 | { | ||
1167 | device_destroy(mon_bin_class, mbus->classdev->devt); | ||
1168 | } | ||
1169 | |||
1147 | int __init mon_bin_init(void) | 1170 | int __init mon_bin_init(void) |
1148 | { | 1171 | { |
1149 | int rc; | 1172 | int rc; |
1150 | 1173 | ||
1174 | mon_bin_class = class_create(THIS_MODULE, "usbmon"); | ||
1175 | if (IS_ERR(mon_bin_class)) { | ||
1176 | rc = PTR_ERR(mon_bin_class); | ||
1177 | goto err_class; | ||
1178 | } | ||
1179 | |||
1151 | rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon"); | 1180 | rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon"); |
1152 | if (rc < 0) | 1181 | if (rc < 0) |
1153 | goto err_dev; | 1182 | goto err_dev; |
@@ -1164,6 +1193,8 @@ int __init mon_bin_init(void) | |||
1164 | err_add: | 1193 | err_add: |
1165 | unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); | 1194 | unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); |
1166 | err_dev: | 1195 | err_dev: |
1196 | class_destroy(mon_bin_class); | ||
1197 | err_class: | ||
1167 | return rc; | 1198 | return rc; |
1168 | } | 1199 | } |
1169 | 1200 | ||
@@ -1171,4 +1202,5 @@ void mon_bin_exit(void) | |||
1171 | { | 1202 | { |
1172 | cdev_del(&mon_bin_cdev); | 1203 | cdev_del(&mon_bin_cdev); |
1173 | unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); | 1204 | unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR); |
1205 | class_destroy(mon_bin_class); | ||
1174 | } | 1206 | } |
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c index 8977ec0d0f99..ce61d8b0fd86 100644 --- a/drivers/usb/mon/mon_main.c +++ b/drivers/usb/mon/mon_main.c | |||
@@ -220,6 +220,8 @@ static void mon_bus_remove(struct usb_bus *ubus) | |||
220 | list_del(&mbus->bus_link); | 220 | list_del(&mbus->bus_link); |
221 | if (mbus->text_inited) | 221 | if (mbus->text_inited) |
222 | mon_text_del(mbus); | 222 | mon_text_del(mbus); |
223 | if (mbus->bin_inited) | ||
224 | mon_bin_del(mbus); | ||
223 | 225 | ||
224 | mon_dissolve(mbus, ubus); | 226 | mon_dissolve(mbus, ubus); |
225 | kref_put(&mbus->ref, mon_bus_drop); | 227 | kref_put(&mbus->ref, mon_bus_drop); |
@@ -301,8 +303,8 @@ static void mon_bus_init(struct usb_bus *ubus) | |||
301 | mbus->u_bus = ubus; | 303 | mbus->u_bus = ubus; |
302 | ubus->mon_bus = mbus; | 304 | ubus->mon_bus = mbus; |
303 | 305 | ||
304 | mbus->text_inited = mon_text_add(mbus, ubus->busnum); | 306 | mbus->text_inited = mon_text_add(mbus, ubus); |
305 | // mon_bin_add(...) | 307 | mbus->bin_inited = mon_bin_add(mbus, ubus); |
306 | 308 | ||
307 | mutex_lock(&mon_lock); | 309 | mutex_lock(&mon_lock); |
308 | list_add_tail(&mbus->bus_link, &mon_buses); | 310 | list_add_tail(&mbus->bus_link, &mon_buses); |
@@ -321,8 +323,8 @@ static void mon_bus0_init(void) | |||
321 | spin_lock_init(&mbus->lock); | 323 | spin_lock_init(&mbus->lock); |
322 | INIT_LIST_HEAD(&mbus->r_list); | 324 | INIT_LIST_HEAD(&mbus->r_list); |
323 | 325 | ||
324 | mbus->text_inited = mon_text_add(mbus, 0); | 326 | mbus->text_inited = mon_text_add(mbus, NULL); |
325 | // mbus->bin_inited = mon_bin_add(mbus, 0); | 327 | mbus->bin_inited = mon_bin_add(mbus, NULL); |
326 | } | 328 | } |
327 | 329 | ||
328 | /* | 330 | /* |
@@ -403,6 +405,8 @@ static void __exit mon_exit(void) | |||
403 | 405 | ||
404 | if (mbus->text_inited) | 406 | if (mbus->text_inited) |
405 | mon_text_del(mbus); | 407 | mon_text_del(mbus); |
408 | if (mbus->bin_inited) | ||
409 | mon_bin_del(mbus); | ||
406 | 410 | ||
407 | /* | 411 | /* |
408 | * This never happens, because the open/close paths in | 412 | * This never happens, because the open/close paths in |
@@ -423,6 +427,8 @@ static void __exit mon_exit(void) | |||
423 | mbus = &mon_bus0; | 427 | mbus = &mon_bus0; |
424 | if (mbus->text_inited) | 428 | if (mbus->text_inited) |
425 | mon_text_del(mbus); | 429 | mon_text_del(mbus); |
430 | if (mbus->bin_inited) | ||
431 | mon_bin_del(mbus); | ||
426 | 432 | ||
427 | mutex_unlock(&mon_lock); | 433 | mutex_unlock(&mon_lock); |
428 | 434 | ||
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index ec0cc51e39ac..982b773d71e6 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c | |||
@@ -655,20 +655,24 @@ static const struct file_operations mon_fops_text_u = { | |||
655 | .release = mon_text_release, | 655 | .release = mon_text_release, |
656 | }; | 656 | }; |
657 | 657 | ||
658 | int mon_text_add(struct mon_bus *mbus, int busnum) | 658 | int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus) |
659 | { | 659 | { |
660 | struct dentry *d; | 660 | struct dentry *d; |
661 | enum { NAMESZ = 10 }; | 661 | enum { NAMESZ = 10 }; |
662 | char name[NAMESZ]; | 662 | char name[NAMESZ]; |
663 | int busnum = ubus? ubus->busnum: 0; | ||
663 | int rc; | 664 | int rc; |
664 | 665 | ||
665 | rc = snprintf(name, NAMESZ, "%dt", busnum); | 666 | if (ubus != NULL) { |
666 | if (rc <= 0 || rc >= NAMESZ) | 667 | rc = snprintf(name, NAMESZ, "%dt", busnum); |
667 | goto err_print_t; | 668 | if (rc <= 0 || rc >= NAMESZ) |
668 | d = debugfs_create_file(name, 0600, mon_dir, mbus, &mon_fops_text_t); | 669 | goto err_print_t; |
669 | if (d == NULL) | 670 | d = debugfs_create_file(name, 0600, mon_dir, mbus, |
670 | goto err_create_t; | 671 | &mon_fops_text_t); |
671 | mbus->dent_t = d; | 672 | if (d == NULL) |
673 | goto err_create_t; | ||
674 | mbus->dent_t = d; | ||
675 | } | ||
672 | 676 | ||
673 | rc = snprintf(name, NAMESZ, "%du", busnum); | 677 | rc = snprintf(name, NAMESZ, "%du", busnum); |
674 | if (rc <= 0 || rc >= NAMESZ) | 678 | if (rc <= 0 || rc >= NAMESZ) |
@@ -694,8 +698,10 @@ err_print_s: | |||
694 | mbus->dent_u = NULL; | 698 | mbus->dent_u = NULL; |
695 | err_create_u: | 699 | err_create_u: |
696 | err_print_u: | 700 | err_print_u: |
697 | debugfs_remove(mbus->dent_t); | 701 | if (ubus != NULL) { |
698 | mbus->dent_t = NULL; | 702 | debugfs_remove(mbus->dent_t); |
703 | mbus->dent_t = NULL; | ||
704 | } | ||
699 | err_create_t: | 705 | err_create_t: |
700 | err_print_t: | 706 | err_print_t: |
701 | return 0; | 707 | return 0; |
@@ -704,7 +710,8 @@ err_print_t: | |||
704 | void mon_text_del(struct mon_bus *mbus) | 710 | void mon_text_del(struct mon_bus *mbus) |
705 | { | 711 | { |
706 | debugfs_remove(mbus->dent_u); | 712 | debugfs_remove(mbus->dent_u); |
707 | debugfs_remove(mbus->dent_t); | 713 | if (mbus->dent_t != NULL) |
714 | debugfs_remove(mbus->dent_t); | ||
708 | debugfs_remove(mbus->dent_s); | 715 | debugfs_remove(mbus->dent_s); |
709 | } | 716 | } |
710 | 717 | ||
diff --git a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h index 13d63255283e..f68ad6d99ad7 100644 --- a/drivers/usb/mon/usb_mon.h +++ b/drivers/usb/mon/usb_mon.h | |||
@@ -20,9 +20,11 @@ struct mon_bus { | |||
20 | struct usb_bus *u_bus; | 20 | struct usb_bus *u_bus; |
21 | 21 | ||
22 | int text_inited; | 22 | int text_inited; |
23 | int bin_inited; | ||
23 | struct dentry *dent_s; /* Debugging file */ | 24 | struct dentry *dent_s; /* Debugging file */ |
24 | struct dentry *dent_t; /* Text interface file */ | 25 | struct dentry *dent_t; /* Text interface file */ |
25 | struct dentry *dent_u; /* Second text interface file */ | 26 | struct dentry *dent_u; /* Second text interface file */ |
27 | struct device *classdev; /* Device in usbmon class */ | ||
26 | 28 | ||
27 | /* Ref */ | 29 | /* Ref */ |
28 | int nreaders; /* Under mon_lock AND mbus->lock */ | 30 | int nreaders; /* Under mon_lock AND mbus->lock */ |
@@ -52,9 +54,10 @@ void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r); | |||
52 | 54 | ||
53 | struct mon_bus *mon_bus_lookup(unsigned int num); | 55 | struct mon_bus *mon_bus_lookup(unsigned int num); |
54 | 56 | ||
55 | int /*bool*/ mon_text_add(struct mon_bus *mbus, int busnum); | 57 | int /*bool*/ mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus); |
56 | void mon_text_del(struct mon_bus *mbus); | 58 | void mon_text_del(struct mon_bus *mbus); |
57 | // void mon_bin_add(struct mon_bus *); | 59 | int /*bool*/ mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus); |
60 | void mon_bin_del(struct mon_bus *mbus); | ||
58 | 61 | ||
59 | int __init mon_text_init(void); | 62 | int __init mon_text_init(void); |
60 | void mon_text_exit(void); | 63 | void mon_text_exit(void); |
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 3efe67092f15..43d6db696f90 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig | |||
@@ -464,6 +464,16 @@ config USB_SERIAL_PL2303 | |||
464 | To compile this driver as a module, choose M here: the | 464 | To compile this driver as a module, choose M here: the |
465 | module will be called pl2303. | 465 | module will be called pl2303. |
466 | 466 | ||
467 | config USB_SERIAL_OTI6858 | ||
468 | tristate "USB Ours Technology Inc. OTi-6858 USB To RS232 Bridge Controller (EXPERIMENTAL)" | ||
469 | depends on USB_SERIAL | ||
470 | help | ||
471 | Say Y here if you want to use the OTi-6858 single port USB to serial | ||
472 | converter device. | ||
473 | |||
474 | To compile this driver as a module, choose M here: the | ||
475 | module will be called oti6858. | ||
476 | |||
467 | config USB_SERIAL_HP4X | 477 | config USB_SERIAL_HP4X |
468 | tristate "USB HP4x Calculators support" | 478 | tristate "USB HP4x Calculators support" |
469 | depends on USB_SERIAL | 479 | depends on USB_SERIAL |
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 61166ad450e6..07a976eca6b7 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile | |||
@@ -40,6 +40,7 @@ obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o | |||
40 | obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o | 40 | obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o |
41 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o | 41 | obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o |
42 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o | 42 | obj-$(CONFIG_USB_SERIAL_OPTION) += option.o |
43 | obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o | ||
43 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o | 44 | obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o |
44 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o | 45 | obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o |
45 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o | 46 | obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o |
diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index fbc8c27d5d99..1cd29cd6bd00 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c | |||
@@ -411,12 +411,13 @@ static int aircable_write(struct usb_serial_port *port, | |||
411 | static void aircable_write_bulk_callback(struct urb *urb) | 411 | static void aircable_write_bulk_callback(struct urb *urb) |
412 | { | 412 | { |
413 | struct usb_serial_port *port = urb->context; | 413 | struct usb_serial_port *port = urb->context; |
414 | int status = urb->status; | ||
414 | int result; | 415 | int result; |
415 | 416 | ||
416 | dbg("%s - urb->status: %d", __FUNCTION__ , urb->status); | 417 | dbg("%s - urb status: %d", __FUNCTION__ , status); |
417 | 418 | ||
418 | /* This has been taken from cypress_m8.c cypress_write_int_callback */ | 419 | /* This has been taken from cypress_m8.c cypress_write_int_callback */ |
419 | switch (urb->status) { | 420 | switch (status) { |
420 | case 0: | 421 | case 0: |
421 | /* success */ | 422 | /* success */ |
422 | break; | 423 | break; |
@@ -425,14 +426,14 @@ static void aircable_write_bulk_callback(struct urb *urb) | |||
425 | case -ESHUTDOWN: | 426 | case -ESHUTDOWN: |
426 | /* this urb is terminated, clean up */ | 427 | /* this urb is terminated, clean up */ |
427 | dbg("%s - urb shutting down with status: %d", | 428 | dbg("%s - urb shutting down with status: %d", |
428 | __FUNCTION__, urb->status); | 429 | __FUNCTION__, status); |
429 | port->write_urb_busy = 0; | 430 | port->write_urb_busy = 0; |
430 | return; | 431 | return; |
431 | default: | 432 | default: |
432 | /* error in the urb, so we have to resubmit it */ | 433 | /* error in the urb, so we have to resubmit it */ |
433 | dbg("%s - Overflow in write", __FUNCTION__); | 434 | dbg("%s - Overflow in write", __FUNCTION__); |
434 | dbg("%s - nonzero write bulk status received: %d", | 435 | dbg("%s - nonzero write bulk status received: %d", |
435 | __FUNCTION__, urb->status); | 436 | __FUNCTION__, status); |
436 | port->write_urb->transfer_buffer_length = 1; | 437 | port->write_urb->transfer_buffer_length = 1; |
437 | port->write_urb->dev = port->serial->dev; | 438 | port->write_urb->dev = port->serial->dev; |
438 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 439 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
@@ -457,16 +458,17 @@ static void aircable_read_bulk_callback(struct urb *urb) | |||
457 | unsigned long no_packages, remaining, package_length, i; | 458 | unsigned long no_packages, remaining, package_length, i; |
458 | int result, shift = 0; | 459 | int result, shift = 0; |
459 | unsigned char *temp; | 460 | unsigned char *temp; |
461 | int status = urb->status; | ||
460 | 462 | ||
461 | dbg("%s - port %d", __FUNCTION__, port->number); | 463 | dbg("%s - port %d", __FUNCTION__, port->number); |
462 | 464 | ||
463 | if (urb->status) { | 465 | if (status) { |
464 | dbg("%s - urb->status = %d", __FUNCTION__, urb->status); | 466 | dbg("%s - urb status = %d", __FUNCTION__, status); |
465 | if (!port->open_count) { | 467 | if (!port->open_count) { |
466 | dbg("%s - port is closed, exiting.", __FUNCTION__); | 468 | dbg("%s - port is closed, exiting.", __FUNCTION__); |
467 | return; | 469 | return; |
468 | } | 470 | } |
469 | if (urb->status == -EPROTO) { | 471 | if (status == -EPROTO) { |
470 | dbg("%s - caught -EPROTO, resubmitting the urb", | 472 | dbg("%s - caught -EPROTO, resubmitting the urb", |
471 | __FUNCTION__); | 473 | __FUNCTION__); |
472 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, | 474 | usb_fill_bulk_urb(port->read_urb, port->serial->dev, |
diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 39a498362594..cff6fd190a28 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c | |||
@@ -82,12 +82,13 @@ static void airprime_read_bulk_callback(struct urb *urb) | |||
82 | unsigned char *data = urb->transfer_buffer; | 82 | unsigned char *data = urb->transfer_buffer; |
83 | struct tty_struct *tty; | 83 | struct tty_struct *tty; |
84 | int result; | 84 | int result; |
85 | int status = urb->status; | ||
85 | 86 | ||
86 | dbg("%s - port %d", __FUNCTION__, port->number); | 87 | dbg("%s - port %d", __FUNCTION__, port->number); |
87 | 88 | ||
88 | if (urb->status) { | 89 | if (status) { |
89 | dbg("%s - nonzero read bulk status received: %d", | 90 | dbg("%s - nonzero read bulk status received: %d", |
90 | __FUNCTION__, urb->status); | 91 | __FUNCTION__, status); |
91 | return; | 92 | return; |
92 | } | 93 | } |
93 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | 94 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); |
@@ -109,6 +110,7 @@ static void airprime_write_bulk_callback(struct urb *urb) | |||
109 | { | 110 | { |
110 | struct usb_serial_port *port = urb->context; | 111 | struct usb_serial_port *port = urb->context; |
111 | struct airprime_private *priv = usb_get_serial_port_data(port); | 112 | struct airprime_private *priv = usb_get_serial_port_data(port); |
113 | int status = urb->status; | ||
112 | unsigned long flags; | 114 | unsigned long flags; |
113 | 115 | ||
114 | dbg("%s - port %d", __FUNCTION__, port->number); | 116 | dbg("%s - port %d", __FUNCTION__, port->number); |
@@ -116,9 +118,9 @@ static void airprime_write_bulk_callback(struct urb *urb) | |||
116 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | 118 | /* free up the transfer buffer, as usb_free_urb() does not do this */ |
117 | kfree (urb->transfer_buffer); | 119 | kfree (urb->transfer_buffer); |
118 | 120 | ||
119 | if (urb->status) | 121 | if (status) |
120 | dbg("%s - nonzero write bulk status received: %d", | 122 | dbg("%s - nonzero write bulk status received: %d", |
121 | __FUNCTION__, urb->status); | 123 | __FUNCTION__, status); |
122 | spin_lock_irqsave(&priv->lock, flags); | 124 | spin_lock_irqsave(&priv->lock, flags); |
123 | --priv->outstanding_urbs; | 125 | --priv->outstanding_urbs; |
124 | spin_unlock_irqrestore(&priv->lock, flags); | 126 | spin_unlock_irqrestore(&priv->lock, flags); |
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index fe437125f14b..c9fd486c1c7d 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c | |||
@@ -172,7 +172,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
172 | 172 | ||
173 | dbg("%s - port %d", __FUNCTION__, port->number); | 173 | dbg("%s - port %d", __FUNCTION__, port->number); |
174 | 174 | ||
175 | if ((!port->tty) || (!port->tty->termios)) { | 175 | if (!port->tty || !port->tty->termios) { |
176 | dbg("%s - no tty structures", __FUNCTION__); | 176 | dbg("%s - no tty structures", __FUNCTION__); |
177 | return; | 177 | return; |
178 | } | 178 | } |
@@ -188,16 +188,6 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
188 | 188 | ||
189 | cflag = port->tty->termios->c_cflag; | 189 | cflag = port->tty->termios->c_cflag; |
190 | 190 | ||
191 | /* check that they really want us to change something: */ | ||
192 | if (old_termios) { | ||
193 | if ((cflag == old_termios->c_cflag) && | ||
194 | (RELEVANT_IFLAG(port->tty->termios->c_iflag) == | ||
195 | RELEVANT_IFLAG(old_termios->c_iflag))) { | ||
196 | dbg("%s - nothing to change...", __FUNCTION__); | ||
197 | return; | ||
198 | } | ||
199 | } | ||
200 | |||
201 | buf = kmalloc(1, GFP_KERNEL); | 191 | buf = kmalloc(1, GFP_KERNEL); |
202 | if (!buf) { | 192 | if (!buf) { |
203 | dbg("error kmalloc"); | 193 | dbg("error kmalloc"); |
@@ -220,7 +210,7 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
220 | dbg("setting CS7"); | 210 | dbg("setting CS7"); |
221 | break; | 211 | break; |
222 | default: | 212 | default: |
223 | err("CSIZE was set but not CS5-CS8, using CS8!"); | 213 | dbg("CSIZE was set but not CS5-CS8, using CS8!"); |
224 | /* fall through */ | 214 | /* fall through */ |
225 | case CS8: | 215 | case CS8: |
226 | config |= 0x03; | 216 | config |= 0x03; |
@@ -251,38 +241,33 @@ static void ark3116_set_termios(struct usb_serial_port *port, | |||
251 | } | 241 | } |
252 | 242 | ||
253 | /* set baudrate */ | 243 | /* set baudrate */ |
254 | baud = 0; | 244 | baud = tty_get_baud_rate(port->tty); |
255 | switch (cflag & CBAUD) { | 245 | |
256 | case B0: | 246 | switch (baud) { |
257 | err("can't set 0 baud, using 9600 instead"); | 247 | case 75: |
248 | case 150: | ||
249 | case 300: | ||
250 | case 600: | ||
251 | case 1200: | ||
252 | case 1800: | ||
253 | case 2400: | ||
254 | case 4800: | ||
255 | case 9600: | ||
256 | case 19200: | ||
257 | case 38400: | ||
258 | case 57600: | ||
259 | case 115200: | ||
260 | case 230400: | ||
261 | case 460800: | ||
258 | break; | 262 | break; |
259 | case B75: baud = 75; break; | 263 | /* set 9600 as default (if given baudrate is invalid for example) */ |
260 | case B150: baud = 150; break; | ||
261 | case B300: baud = 300; break; | ||
262 | case B600: baud = 600; break; | ||
263 | case B1200: baud = 1200; break; | ||
264 | case B1800: baud = 1800; break; | ||
265 | case B2400: baud = 2400; break; | ||
266 | case B4800: baud = 4800; break; | ||
267 | case B9600: baud = 9600; break; | ||
268 | case B19200: baud = 19200; break; | ||
269 | case B38400: baud = 38400; break; | ||
270 | case B57600: baud = 57600; break; | ||
271 | case B115200: baud = 115200; break; | ||
272 | case B230400: baud = 230400; break; | ||
273 | case B460800: baud = 460800; break; | ||
274 | default: | 264 | default: |
275 | dbg("does not support the baudrate requested (fix it)"); | 265 | baud = 9600; |
276 | break; | ||
277 | } | 266 | } |
278 | 267 | ||
279 | /* set 9600 as default (if given baudrate is invalid for example) */ | ||
280 | if (baud == 0) | ||
281 | baud = 9600; | ||
282 | |||
283 | /* | 268 | /* |
284 | * found by try'n'error, be careful, maybe there are other options | 269 | * found by try'n'error, be careful, maybe there are other options |
285 | * for multiplicator etc! | 270 | * for multiplicator etc! (3.5 for example) |
286 | */ | 271 | */ |
287 | if (baud == 460800) | 272 | if (baud == 460800) |
288 | /* strange, for 460800 the formula is wrong | 273 | /* strange, for 460800 the formula is wrong |
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 3b800d277c4b..e67ce25f7512 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c | |||
@@ -255,9 +255,10 @@ static void belkin_sa_read_int_callback (struct urb *urb) | |||
255 | struct belkin_sa_private *priv; | 255 | struct belkin_sa_private *priv; |
256 | unsigned char *data = urb->transfer_buffer; | 256 | unsigned char *data = urb->transfer_buffer; |
257 | int retval; | 257 | int retval; |
258 | int status = urb->status; | ||
258 | unsigned long flags; | 259 | unsigned long flags; |
259 | 260 | ||
260 | switch (urb->status) { | 261 | switch (status) { |
261 | case 0: | 262 | case 0: |
262 | /* success */ | 263 | /* success */ |
263 | break; | 264 | break; |
@@ -265,10 +266,12 @@ static void belkin_sa_read_int_callback (struct urb *urb) | |||
265 | case -ENOENT: | 266 | case -ENOENT: |
266 | case -ESHUTDOWN: | 267 | case -ESHUTDOWN: |
267 | /* this urb is terminated, clean up */ | 268 | /* this urb is terminated, clean up */ |
268 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 269 | dbg("%s - urb shutting down with status: %d", |
270 | __FUNCTION__, status); | ||
269 | return; | 271 | return; |
270 | default: | 272 | default: |
271 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 273 | dbg("%s - nonzero urb status received: %d", |
274 | __FUNCTION__, status); | ||
272 | goto exit; | 275 | goto exit; |
273 | } | 276 | } |
274 | 277 | ||
@@ -346,6 +349,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios | |||
346 | unsigned long flags; | 349 | unsigned long flags; |
347 | unsigned long control_state; | 350 | unsigned long control_state; |
348 | int bad_flow_control; | 351 | int bad_flow_control; |
352 | speed_t baud; | ||
349 | 353 | ||
350 | if ((!port->tty) || (!port->tty->termios)) { | 354 | if ((!port->tty) || (!port->tty->termios)) { |
351 | dbg ("%s - no tty or termios structure", __FUNCTION__); | 355 | dbg ("%s - no tty or termios structure", __FUNCTION__); |
@@ -361,16 +365,8 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios | |||
361 | bad_flow_control = priv->bad_flow_control; | 365 | bad_flow_control = priv->bad_flow_control; |
362 | spin_unlock_irqrestore(&priv->lock, flags); | 366 | spin_unlock_irqrestore(&priv->lock, flags); |
363 | 367 | ||
364 | /* check that they really want us to change something */ | 368 | old_iflag = old_termios->c_iflag; |
365 | if (old_termios) { | 369 | old_cflag = old_termios->c_cflag; |
366 | if ((cflag == old_termios->c_cflag) && | ||
367 | (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { | ||
368 | dbg("%s - nothing to change...", __FUNCTION__); | ||
369 | return; | ||
370 | } | ||
371 | old_iflag = old_termios->c_iflag; | ||
372 | old_cflag = old_termios->c_cflag; | ||
373 | } | ||
374 | 370 | ||
375 | /* Set the baud rate */ | 371 | /* Set the baud rate */ |
376 | if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { | 372 | if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { |
@@ -384,38 +380,30 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios | |||
384 | if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0) | 380 | if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0) |
385 | err("Set RTS error"); | 381 | err("Set RTS error"); |
386 | } | 382 | } |
383 | } | ||
387 | 384 | ||
388 | switch(cflag & CBAUD) { | 385 | baud = tty_get_baud_rate(port->tty); |
389 | case B0: /* handled below */ break; | 386 | urb_value = BELKIN_SA_BAUD(baud); |
390 | case B300: urb_value = BELKIN_SA_BAUD(300); break; | 387 | /* Clip to maximum speed */ |
391 | case B600: urb_value = BELKIN_SA_BAUD(600); break; | 388 | if (urb_value == 0) |
392 | case B1200: urb_value = BELKIN_SA_BAUD(1200); break; | 389 | urb_value = 1; |
393 | case B2400: urb_value = BELKIN_SA_BAUD(2400); break; | 390 | /* Turn it back into a resulting real baud rate */ |
394 | case B4800: urb_value = BELKIN_SA_BAUD(4800); break; | 391 | baud = BELKIN_SA_BAUD(urb_value); |
395 | case B9600: urb_value = BELKIN_SA_BAUD(9600); break; | 392 | /* FIXME: Once the tty updates are done then push this back to the tty */ |
396 | case B19200: urb_value = BELKIN_SA_BAUD(19200); break; | 393 | |
397 | case B38400: urb_value = BELKIN_SA_BAUD(38400); break; | 394 | if ((cflag & CBAUD) != B0 ) { |
398 | case B57600: urb_value = BELKIN_SA_BAUD(57600); break; | 395 | if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0) |
399 | case B115200: urb_value = BELKIN_SA_BAUD(115200); break; | 396 | err("Set baudrate error"); |
400 | case B230400: urb_value = BELKIN_SA_BAUD(230400); break; | 397 | } else { |
401 | default: err("BELKIN USB Serial Adapter: unsupported baudrate request, using default of 9600"); | 398 | /* Disable flow control */ |
402 | urb_value = BELKIN_SA_BAUD(9600); break; | 399 | if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0) |
403 | } | 400 | err("Disable flowcontrol error"); |
404 | if ((cflag & CBAUD) != B0 ) { | 401 | /* Drop RTS and DTR */ |
405 | if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0) | 402 | control_state &= ~(TIOCM_DTR | TIOCM_RTS); |
406 | err("Set baudrate error"); | 403 | if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0) |
407 | } else { | 404 | err("DTR LOW error"); |
408 | /* Disable flow control */ | 405 | if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0) |
409 | if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0) | 406 | err("RTS LOW error"); |
410 | err("Disable flowcontrol error"); | ||
411 | |||
412 | /* Drop RTS and DTR */ | ||
413 | control_state &= ~(TIOCM_DTR | TIOCM_RTS); | ||
414 | if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0) | ||
415 | err("DTR LOW error"); | ||
416 | if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0) | ||
417 | err("RTS LOW error"); | ||
418 | } | ||
419 | } | 407 | } |
420 | 408 | ||
421 | /* set the parity */ | 409 | /* set the parity */ |
@@ -435,7 +423,7 @@ static void belkin_sa_set_termios (struct usb_serial_port *port, struct ktermios | |||
435 | case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break; | 423 | case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break; |
436 | case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break; | 424 | case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break; |
437 | case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break; | 425 | case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break; |
438 | default: err("CSIZE was not CS5-CS8, using default of 8"); | 426 | default: dbg("CSIZE was not CS5-CS8, using default of 8"); |
439 | urb_value = BELKIN_SA_DATA_BITS(8); | 427 | urb_value = BELKIN_SA_DATA_BITS(8); |
440 | break; | 428 | break; |
441 | } | 429 | } |
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 4167753ed31f..4353df92487f 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
@@ -305,12 +305,13 @@ static void cyberjack_read_int_callback( struct urb *urb ) | |||
305 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 305 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
306 | struct cyberjack_private *priv = usb_get_serial_port_data(port); | 306 | struct cyberjack_private *priv = usb_get_serial_port_data(port); |
307 | unsigned char *data = urb->transfer_buffer; | 307 | unsigned char *data = urb->transfer_buffer; |
308 | int status = urb->status; | ||
308 | int result; | 309 | int result; |
309 | 310 | ||
310 | dbg("%s - port %d", __FUNCTION__, port->number); | 311 | dbg("%s - port %d", __FUNCTION__, port->number); |
311 | 312 | ||
312 | /* the urb might have been killed. */ | 313 | /* the urb might have been killed. */ |
313 | if (urb->status) | 314 | if (status) |
314 | return; | 315 | return; |
315 | 316 | ||
316 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | 317 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); |
@@ -365,12 +366,14 @@ static void cyberjack_read_bulk_callback (struct urb *urb) | |||
365 | unsigned char *data = urb->transfer_buffer; | 366 | unsigned char *data = urb->transfer_buffer; |
366 | short todo; | 367 | short todo; |
367 | int result; | 368 | int result; |
369 | int status = urb->status; | ||
368 | 370 | ||
369 | dbg("%s - port %d", __FUNCTION__, port->number); | 371 | dbg("%s - port %d", __FUNCTION__, port->number); |
370 | 372 | ||
371 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | 373 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); |
372 | if (urb->status) { | 374 | if (status) { |
373 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 375 | dbg("%s - nonzero read bulk status received: %d", |
376 | __FUNCTION__, status); | ||
374 | return; | 377 | return; |
375 | } | 378 | } |
376 | 379 | ||
@@ -411,12 +414,14 @@ static void cyberjack_write_bulk_callback (struct urb *urb) | |||
411 | { | 414 | { |
412 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 415 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
413 | struct cyberjack_private *priv = usb_get_serial_port_data(port); | 416 | struct cyberjack_private *priv = usb_get_serial_port_data(port); |
417 | int status = urb->status; | ||
414 | 418 | ||
415 | dbg("%s - port %d", __FUNCTION__, port->number); | 419 | dbg("%s - port %d", __FUNCTION__, port->number); |
416 | 420 | ||
417 | port->write_urb_busy = 0; | 421 | port->write_urb_busy = 0; |
418 | if (urb->status) { | 422 | if (status) { |
419 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 423 | dbg("%s - nonzero write bulk status received: %d", |
424 | __FUNCTION__, status); | ||
420 | return; | 425 | return; |
421 | } | 426 | } |
422 | 427 | ||
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 57b8e27285fc..163386336a5d 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -1275,10 +1275,11 @@ static void cypress_read_int_callback(struct urb *urb) | |||
1275 | int bytes = 0; | 1275 | int bytes = 0; |
1276 | int result; | 1276 | int result; |
1277 | int i = 0; | 1277 | int i = 0; |
1278 | int status = urb->status; | ||
1278 | 1279 | ||
1279 | dbg("%s - port %d", __FUNCTION__, port->number); | 1280 | dbg("%s - port %d", __FUNCTION__, port->number); |
1280 | 1281 | ||
1281 | switch (urb->status) { | 1282 | switch (status) { |
1282 | case 0: /* success */ | 1283 | case 0: /* success */ |
1283 | break; | 1284 | break; |
1284 | case -ECONNRESET: | 1285 | case -ECONNRESET: |
@@ -1292,7 +1293,7 @@ static void cypress_read_int_callback(struct urb *urb) | |||
1292 | default: | 1293 | default: |
1293 | /* something ugly is going on... */ | 1294 | /* something ugly is going on... */ |
1294 | dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n", | 1295 | dev_err(&urb->dev->dev,"%s - unexpected nonzero read status received: %d\n", |
1295 | __FUNCTION__,urb->status); | 1296 | __FUNCTION__, status); |
1296 | cypress_set_dead(port); | 1297 | cypress_set_dead(port); |
1297 | return; | 1298 | return; |
1298 | } | 1299 | } |
@@ -1419,10 +1420,11 @@ static void cypress_write_int_callback(struct urb *urb) | |||
1419 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1420 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1420 | struct cypress_private *priv = usb_get_serial_port_data(port); | 1421 | struct cypress_private *priv = usb_get_serial_port_data(port); |
1421 | int result; | 1422 | int result; |
1423 | int status = urb->status; | ||
1422 | 1424 | ||
1423 | dbg("%s - port %d", __FUNCTION__, port->number); | 1425 | dbg("%s - port %d", __FUNCTION__, port->number); |
1424 | 1426 | ||
1425 | switch (urb->status) { | 1427 | switch (status) { |
1426 | case 0: | 1428 | case 0: |
1427 | /* success */ | 1429 | /* success */ |
1428 | break; | 1430 | break; |
@@ -1430,7 +1432,8 @@ static void cypress_write_int_callback(struct urb *urb) | |||
1430 | case -ENOENT: | 1432 | case -ENOENT: |
1431 | case -ESHUTDOWN: | 1433 | case -ESHUTDOWN: |
1432 | /* this urb is terminated, clean up */ | 1434 | /* this urb is terminated, clean up */ |
1433 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 1435 | dbg("%s - urb shutting down with status: %d", |
1436 | __FUNCTION__, status); | ||
1434 | priv->write_urb_in_use = 0; | 1437 | priv->write_urb_in_use = 0; |
1435 | return; | 1438 | return; |
1436 | case -EPIPE: /* no break needed; clear halt and resubmit */ | 1439 | case -EPIPE: /* no break needed; clear halt and resubmit */ |
@@ -1438,7 +1441,8 @@ static void cypress_write_int_callback(struct urb *urb) | |||
1438 | break; | 1441 | break; |
1439 | usb_clear_halt(port->serial->dev, 0x02); | 1442 | usb_clear_halt(port->serial->dev, 0x02); |
1440 | /* error in the urb, so we have to resubmit it */ | 1443 | /* error in the urb, so we have to resubmit it */ |
1441 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 1444 | dbg("%s - nonzero write bulk status received: %d", |
1445 | __FUNCTION__, status); | ||
1442 | port->interrupt_out_urb->transfer_buffer_length = 1; | 1446 | port->interrupt_out_urb->transfer_buffer_length = 1; |
1443 | port->interrupt_out_urb->dev = port->serial->dev; | 1447 | port->interrupt_out_urb->dev = port->serial->dev; |
1444 | result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); | 1448 | result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); |
@@ -1450,7 +1454,7 @@ static void cypress_write_int_callback(struct urb *urb) | |||
1450 | break; | 1454 | break; |
1451 | default: | 1455 | default: |
1452 | dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n", | 1456 | dev_err(&urb->dev->dev,"%s - unexpected nonzero write status received: %d\n", |
1453 | __FUNCTION__,urb->status); | 1457 | __FUNCTION__, status); |
1454 | cypress_set_dead(port); | 1458 | cypress_set_dead(port); |
1455 | break; | 1459 | break; |
1456 | } | 1460 | } |
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index d78692c01cfa..976f54ec26e6 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
@@ -416,9 +416,6 @@ struct digi_port { | |||
416 | int dp_port_num; | 416 | int dp_port_num; |
417 | int dp_out_buf_len; | 417 | int dp_out_buf_len; |
418 | unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE]; | 418 | unsigned char dp_out_buf[DIGI_OUT_BUF_SIZE]; |
419 | int dp_in_buf_len; | ||
420 | unsigned char dp_in_buf[DIGI_IN_BUF_SIZE]; | ||
421 | unsigned char dp_in_flag_buf[DIGI_IN_BUF_SIZE]; | ||
422 | int dp_write_urb_in_use; | 419 | int dp_write_urb_in_use; |
423 | unsigned int dp_modem_signals; | 420 | unsigned int dp_modem_signals; |
424 | wait_queue_head_t dp_modem_change_wait; | 421 | wait_queue_head_t dp_modem_change_wait; |
@@ -920,7 +917,6 @@ dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num ); | |||
920 | spin_lock_irqsave( &priv->dp_port_lock, flags ); | 917 | spin_lock_irqsave( &priv->dp_port_lock, flags ); |
921 | priv->dp_throttled = 1; | 918 | priv->dp_throttled = 1; |
922 | priv->dp_throttle_restart = 0; | 919 | priv->dp_throttle_restart = 0; |
923 | priv->dp_in_buf_len = 0; | ||
924 | spin_unlock_irqrestore( &priv->dp_port_lock, flags ); | 920 | spin_unlock_irqrestore( &priv->dp_port_lock, flags ); |
925 | 921 | ||
926 | } | 922 | } |
@@ -930,23 +926,16 @@ static void digi_rx_unthrottle( struct usb_serial_port *port ) | |||
930 | { | 926 | { |
931 | 927 | ||
932 | int ret = 0; | 928 | int ret = 0; |
933 | int len; | ||
934 | unsigned long flags; | 929 | unsigned long flags; |
935 | struct digi_port *priv = usb_get_serial_port_data(port); | 930 | struct digi_port *priv = usb_get_serial_port_data(port); |
936 | struct tty_struct *tty = port->tty; | ||
937 | |||
938 | 931 | ||
939 | dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); | 932 | dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); |
940 | 933 | ||
941 | spin_lock_irqsave( &priv->dp_port_lock, flags ); | 934 | spin_lock_irqsave( &priv->dp_port_lock, flags ); |
942 | 935 | ||
943 | /* send any buffered chars from throttle time on to tty subsystem */ | 936 | /* turn throttle off */ |
944 | 937 | priv->dp_throttled = 0; | |
945 | len = tty_buffer_request_room(tty, priv->dp_in_buf_len); | 938 | priv->dp_throttle_restart = 0; |
946 | if( len > 0 ) { | ||
947 | tty_insert_flip_string_flags(tty, priv->dp_in_buf, priv->dp_in_flag_buf, len); | ||
948 | tty_flip_buffer_push( tty ); | ||
949 | } | ||
950 | 939 | ||
951 | /* restart read chain */ | 940 | /* restart read chain */ |
952 | if( priv->dp_throttle_restart ) { | 941 | if( priv->dp_throttle_restart ) { |
@@ -954,11 +943,6 @@ dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); | |||
954 | ret = usb_submit_urb( port->read_urb, GFP_ATOMIC ); | 943 | ret = usb_submit_urb( port->read_urb, GFP_ATOMIC ); |
955 | } | 944 | } |
956 | 945 | ||
957 | /* turn throttle off */ | ||
958 | priv->dp_throttled = 0; | ||
959 | priv->dp_in_buf_len = 0; | ||
960 | priv->dp_throttle_restart = 0; | ||
961 | |||
962 | spin_unlock_irqrestore( &priv->dp_port_lock, flags ); | 946 | spin_unlock_irqrestore( &priv->dp_port_lock, flags ); |
963 | 947 | ||
964 | if( ret ) { | 948 | if( ret ) { |
@@ -1340,19 +1324,21 @@ static void digi_write_bulk_callback( struct urb *urb ) | |||
1340 | struct digi_port *priv; | 1324 | struct digi_port *priv; |
1341 | struct digi_serial *serial_priv; | 1325 | struct digi_serial *serial_priv; |
1342 | int ret = 0; | 1326 | int ret = 0; |
1327 | int status = urb->status; | ||
1343 | 1328 | ||
1344 | 1329 | ||
1345 | dbg( "digi_write_bulk_callback: TOP, urb->status=%d", urb->status ); | 1330 | dbg("digi_write_bulk_callback: TOP, urb status=%d", status); |
1346 | 1331 | ||
1347 | /* port and serial sanity check */ | 1332 | /* port and serial sanity check */ |
1348 | if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) { | 1333 | if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) { |
1349 | err("%s: port or port->private is NULL, status=%d", __FUNCTION__, | 1334 | err("%s: port or port->private is NULL, status=%d", |
1350 | urb->status ); | 1335 | __FUNCTION__, status); |
1351 | return; | 1336 | return; |
1352 | } | 1337 | } |
1353 | serial = port->serial; | 1338 | serial = port->serial; |
1354 | if( serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL ) { | 1339 | if( serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL ) { |
1355 | err("%s: serial or serial->private is NULL, status=%d", __FUNCTION__, urb->status ); | 1340 | err("%s: serial or serial->private is NULL, status=%d", |
1341 | __FUNCTION__, status); | ||
1356 | return; | 1342 | return; |
1357 | } | 1343 | } |
1358 | 1344 | ||
@@ -1687,7 +1673,6 @@ dbg( "digi_startup: TOP" ); | |||
1687 | spin_lock_init( &priv->dp_port_lock ); | 1673 | spin_lock_init( &priv->dp_port_lock ); |
1688 | priv->dp_port_num = i; | 1674 | priv->dp_port_num = i; |
1689 | priv->dp_out_buf_len = 0; | 1675 | priv->dp_out_buf_len = 0; |
1690 | priv->dp_in_buf_len = 0; | ||
1691 | priv->dp_write_urb_in_use = 0; | 1676 | priv->dp_write_urb_in_use = 0; |
1692 | priv->dp_modem_signals = 0; | 1677 | priv->dp_modem_signals = 0; |
1693 | init_waitqueue_head( &priv->dp_modem_change_wait ); | 1678 | init_waitqueue_head( &priv->dp_modem_change_wait ); |
@@ -1757,25 +1742,28 @@ static void digi_read_bulk_callback( struct urb *urb ) | |||
1757 | struct digi_port *priv; | 1742 | struct digi_port *priv; |
1758 | struct digi_serial *serial_priv; | 1743 | struct digi_serial *serial_priv; |
1759 | int ret; | 1744 | int ret; |
1745 | int status = urb->status; | ||
1760 | 1746 | ||
1761 | 1747 | ||
1762 | dbg( "digi_read_bulk_callback: TOP" ); | 1748 | dbg( "digi_read_bulk_callback: TOP" ); |
1763 | 1749 | ||
1764 | /* port sanity check, do not resubmit if port is not valid */ | 1750 | /* port sanity check, do not resubmit if port is not valid */ |
1765 | if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) { | 1751 | if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) { |
1766 | err("%s: port or port->private is NULL, status=%d", __FUNCTION__, | 1752 | err("%s: port or port->private is NULL, status=%d", |
1767 | urb->status ); | 1753 | __FUNCTION__, status); |
1768 | return; | 1754 | return; |
1769 | } | 1755 | } |
1770 | if( port->serial == NULL | 1756 | if( port->serial == NULL |
1771 | || (serial_priv=usb_get_serial_data(port->serial)) == NULL ) { | 1757 | || (serial_priv=usb_get_serial_data(port->serial)) == NULL ) { |
1772 | err("%s: serial is bad or serial->private is NULL, status=%d", __FUNCTION__, urb->status ); | 1758 | err("%s: serial is bad or serial->private is NULL, status=%d", |
1759 | __FUNCTION__, status); | ||
1773 | return; | 1760 | return; |
1774 | } | 1761 | } |
1775 | 1762 | ||
1776 | /* do not resubmit urb if it has any status error */ | 1763 | /* do not resubmit urb if it has any status error */ |
1777 | if( urb->status ) { | 1764 | if (status) { |
1778 | err("%s: nonzero read bulk status: status=%d, port=%d", __FUNCTION__, urb->status, priv->dp_port_num ); | 1765 | err("%s: nonzero read bulk status: status=%d, port=%d", |
1766 | __FUNCTION__, status, priv->dp_port_num); | ||
1779 | return; | 1767 | return; |
1780 | } | 1768 | } |
1781 | 1769 | ||
@@ -1816,10 +1804,11 @@ static int digi_read_inb_callback( struct urb *urb ) | |||
1816 | struct digi_port *priv = usb_get_serial_port_data(port); | 1804 | struct digi_port *priv = usb_get_serial_port_data(port); |
1817 | int opcode = ((unsigned char *)urb->transfer_buffer)[0]; | 1805 | int opcode = ((unsigned char *)urb->transfer_buffer)[0]; |
1818 | int len = ((unsigned char *)urb->transfer_buffer)[1]; | 1806 | int len = ((unsigned char *)urb->transfer_buffer)[1]; |
1819 | int status = ((unsigned char *)urb->transfer_buffer)[2]; | 1807 | int port_status = ((unsigned char *)urb->transfer_buffer)[2]; |
1820 | unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3; | 1808 | unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3; |
1821 | int flag,throttled; | 1809 | int flag,throttled; |
1822 | int i; | 1810 | int i; |
1811 | int status = urb->status; | ||
1823 | 1812 | ||
1824 | /* do not process callbacks on closed ports */ | 1813 | /* do not process callbacks on closed ports */ |
1825 | /* but do continue the read chain */ | 1814 | /* but do continue the read chain */ |
@@ -1828,7 +1817,10 @@ static int digi_read_inb_callback( struct urb *urb ) | |||
1828 | 1817 | ||
1829 | /* short/multiple packet check */ | 1818 | /* short/multiple packet check */ |
1830 | if( urb->actual_length != len + 2 ) { | 1819 | if( urb->actual_length != len + 2 ) { |
1831 | err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", __FUNCTION__, urb->status, priv->dp_port_num, opcode, len, urb->actual_length, status ); | 1820 | err("%s: INCOMPLETE OR MULTIPLE PACKET, urb status=%d, " |
1821 | "port=%d, opcode=%d, len=%d, actual_length=%d, " | ||
1822 | "port_status=%d", __FUNCTION__, status, priv->dp_port_num, | ||
1823 | opcode, len, urb->actual_length, port_status); | ||
1832 | return( -1 ); | 1824 | return( -1 ); |
1833 | } | 1825 | } |
1834 | 1826 | ||
@@ -1843,52 +1835,37 @@ static int digi_read_inb_callback( struct urb *urb ) | |||
1843 | /* receive data */ | 1835 | /* receive data */ |
1844 | if( opcode == DIGI_CMD_RECEIVE_DATA ) { | 1836 | if( opcode == DIGI_CMD_RECEIVE_DATA ) { |
1845 | 1837 | ||
1846 | /* get flag from status */ | 1838 | /* get flag from port_status */ |
1847 | flag = 0; | 1839 | flag = 0; |
1848 | 1840 | ||
1849 | /* overrun is special, not associated with a char */ | 1841 | /* overrun is special, not associated with a char */ |
1850 | if( status & DIGI_OVERRUN_ERROR ) { | 1842 | if (port_status & DIGI_OVERRUN_ERROR) { |
1851 | tty_insert_flip_char( tty, 0, TTY_OVERRUN ); | 1843 | tty_insert_flip_char( tty, 0, TTY_OVERRUN ); |
1852 | } | 1844 | } |
1853 | 1845 | ||
1854 | /* break takes precedence over parity, */ | 1846 | /* break takes precedence over parity, */ |
1855 | /* which takes precedence over framing errors */ | 1847 | /* which takes precedence over framing errors */ |
1856 | if( status & DIGI_BREAK_ERROR ) { | 1848 | if (port_status & DIGI_BREAK_ERROR) { |
1857 | flag = TTY_BREAK; | 1849 | flag = TTY_BREAK; |
1858 | } else if( status & DIGI_PARITY_ERROR ) { | 1850 | } else if (port_status & DIGI_PARITY_ERROR) { |
1859 | flag = TTY_PARITY; | 1851 | flag = TTY_PARITY; |
1860 | } else if( status & DIGI_FRAMING_ERROR ) { | 1852 | } else if (port_status & DIGI_FRAMING_ERROR) { |
1861 | flag = TTY_FRAME; | 1853 | flag = TTY_FRAME; |
1862 | } | 1854 | } |
1863 | 1855 | ||
1864 | /* data length is len-1 (one byte of len is status) */ | 1856 | /* data length is len-1 (one byte of len is port_status) */ |
1865 | --len; | 1857 | --len; |
1866 | 1858 | ||
1867 | if( throttled ) { | 1859 | len = tty_buffer_request_room(tty, len); |
1868 | 1860 | if( len > 0 ) { | |
1869 | len = min( len, | 1861 | /* Hot path */ |
1870 | DIGI_IN_BUF_SIZE - priv->dp_in_buf_len ); | 1862 | if(flag == TTY_NORMAL) |
1871 | 1863 | tty_insert_flip_string(tty, data, len); | |
1872 | if( len > 0 ) { | 1864 | else { |
1873 | memcpy( priv->dp_in_buf + priv->dp_in_buf_len, | 1865 | for(i = 0; i < len; i++) |
1874 | data, len ); | 1866 | tty_insert_flip_char(tty, data[i], flag); |
1875 | memset( priv->dp_in_flag_buf | ||
1876 | + priv->dp_in_buf_len, flag, len ); | ||
1877 | priv->dp_in_buf_len += len; | ||
1878 | } | ||
1879 | |||
1880 | } else { | ||
1881 | len = tty_buffer_request_room(tty, len); | ||
1882 | if( len > 0 ) { | ||
1883 | /* Hot path */ | ||
1884 | if(flag == TTY_NORMAL) | ||
1885 | tty_insert_flip_string(tty, data, len); | ||
1886 | else { | ||
1887 | for(i = 0; i < len; i++) | ||
1888 | tty_insert_flip_char(tty, data[i], flag); | ||
1889 | } | ||
1890 | tty_flip_buffer_push( tty ); | ||
1891 | } | 1867 | } |
1868 | tty_flip_buffer_push( tty ); | ||
1892 | } | 1869 | } |
1893 | } | 1870 | } |
1894 | 1871 | ||
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index 4703c8f85383..050fcc996f56 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c | |||
@@ -326,12 +326,14 @@ static int empeg_chars_in_buffer (struct usb_serial_port *port) | |||
326 | 326 | ||
327 | static void empeg_write_bulk_callback (struct urb *urb) | 327 | static void empeg_write_bulk_callback (struct urb *urb) |
328 | { | 328 | { |
329 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 329 | struct usb_serial_port *port = urb->context; |
330 | int status = urb->status; | ||
330 | 331 | ||
331 | dbg("%s - port %d", __FUNCTION__, port->number); | 332 | dbg("%s - port %d", __FUNCTION__, port->number); |
332 | 333 | ||
333 | if (urb->status) { | 334 | if (status) { |
334 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 335 | dbg("%s - nonzero write bulk status received: %d", |
336 | __FUNCTION__, status); | ||
335 | return; | 337 | return; |
336 | } | 338 | } |
337 | 339 | ||
@@ -345,11 +347,13 @@ static void empeg_read_bulk_callback (struct urb *urb) | |||
345 | struct tty_struct *tty; | 347 | struct tty_struct *tty; |
346 | unsigned char *data = urb->transfer_buffer; | 348 | unsigned char *data = urb->transfer_buffer; |
347 | int result; | 349 | int result; |
350 | int status = urb->status; | ||
348 | 351 | ||
349 | dbg("%s - port %d", __FUNCTION__, port->number); | 352 | dbg("%s - port %d", __FUNCTION__, port->number); |
350 | 353 | ||
351 | if (urb->status) { | 354 | if (status) { |
352 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 355 | dbg("%s - nonzero read bulk status received: %d", |
356 | __FUNCTION__, status); | ||
353 | return; | 357 | return; |
354 | } | 358 | } |
355 | 359 | ||
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index da1c6f7f82b8..7b1673a44077 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -271,26 +271,58 @@ static int debug; | |||
271 | static __u16 vendor = FTDI_VID; | 271 | static __u16 vendor = FTDI_VID; |
272 | static __u16 product; | 272 | static __u16 product; |
273 | 273 | ||
274 | struct ftdi_private { | ||
275 | ftdi_chip_type_t chip_type; | ||
276 | /* type of the device, either SIO or FT8U232AM */ | ||
277 | int baud_base; /* baud base clock for divisor setting */ | ||
278 | int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ | ||
279 | __u16 last_set_data_urb_value ; | ||
280 | /* the last data state set - needed for doing a break */ | ||
281 | int write_offset; /* This is the offset in the usb data block to write the serial data - | ||
282 | * it is different between devices | ||
283 | */ | ||
284 | int flags; /* some ASYNC_xxxx flags are supported */ | ||
285 | unsigned long last_dtr_rts; /* saved modem control outputs */ | ||
286 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
287 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ | ||
288 | __u8 rx_flags; /* receive state flags (throttling) */ | ||
289 | spinlock_t rx_lock; /* spinlock for receive state */ | ||
290 | struct delayed_work rx_work; | ||
291 | struct usb_serial_port *port; | ||
292 | int rx_processed; | ||
293 | unsigned long rx_bytes; | ||
294 | |||
295 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ | ||
296 | |||
297 | int force_baud; /* if non-zero, force the baud rate to this value */ | ||
298 | int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ | ||
299 | |||
300 | spinlock_t tx_lock; /* spinlock for transmit state */ | ||
301 | unsigned long tx_bytes; | ||
302 | unsigned long tx_outstanding_bytes; | ||
303 | unsigned long tx_outstanding_urbs; | ||
304 | }; | ||
305 | |||
274 | /* struct ftdi_sio_quirk is used by devices requiring special attention. */ | 306 | /* struct ftdi_sio_quirk is used by devices requiring special attention. */ |
275 | struct ftdi_sio_quirk { | 307 | struct ftdi_sio_quirk { |
276 | int (*probe)(struct usb_serial *); | 308 | int (*probe)(struct usb_serial *); |
277 | void (*setup)(struct usb_serial *); /* Special settings during startup. */ | 309 | void (*port_probe)(struct ftdi_private *); /* Special settings for probed ports. */ |
278 | }; | 310 | }; |
279 | 311 | ||
280 | static int ftdi_olimex_probe (struct usb_serial *serial); | 312 | static int ftdi_olimex_probe (struct usb_serial *serial); |
281 | static void ftdi_USB_UIRT_setup (struct usb_serial *serial); | 313 | static void ftdi_USB_UIRT_setup (struct ftdi_private *priv); |
282 | static void ftdi_HE_TIRA1_setup (struct usb_serial *serial); | 314 | static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv); |
283 | 315 | ||
284 | static struct ftdi_sio_quirk ftdi_olimex_quirk = { | 316 | static struct ftdi_sio_quirk ftdi_olimex_quirk = { |
285 | .probe = ftdi_olimex_probe, | 317 | .probe = ftdi_olimex_probe, |
286 | }; | 318 | }; |
287 | 319 | ||
288 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { | 320 | static struct ftdi_sio_quirk ftdi_USB_UIRT_quirk = { |
289 | .setup = ftdi_USB_UIRT_setup, | 321 | .port_probe = ftdi_USB_UIRT_setup, |
290 | }; | 322 | }; |
291 | 323 | ||
292 | static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { | 324 | static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { |
293 | .setup = ftdi_HE_TIRA1_setup, | 325 | .port_probe = ftdi_HE_TIRA1_setup, |
294 | }; | 326 | }; |
295 | 327 | ||
296 | /* | 328 | /* |
@@ -567,38 +599,6 @@ static const char *ftdi_chip_name[] = { | |||
567 | #define THROTTLED 0x01 | 599 | #define THROTTLED 0x01 |
568 | #define ACTUALLY_THROTTLED 0x02 | 600 | #define ACTUALLY_THROTTLED 0x02 |
569 | 601 | ||
570 | struct ftdi_private { | ||
571 | ftdi_chip_type_t chip_type; | ||
572 | /* type of the device, either SIO or FT8U232AM */ | ||
573 | int baud_base; /* baud base clock for divisor setting */ | ||
574 | int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ | ||
575 | __u16 last_set_data_urb_value ; | ||
576 | /* the last data state set - needed for doing a break */ | ||
577 | int write_offset; /* This is the offset in the usb data block to write the serial data - | ||
578 | * it is different between devices | ||
579 | */ | ||
580 | int flags; /* some ASYNC_xxxx flags are supported */ | ||
581 | unsigned long last_dtr_rts; /* saved modem control outputs */ | ||
582 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
583 | char prev_status, diff_status; /* Used for TIOCMIWAIT */ | ||
584 | __u8 rx_flags; /* receive state flags (throttling) */ | ||
585 | spinlock_t rx_lock; /* spinlock for receive state */ | ||
586 | struct delayed_work rx_work; | ||
587 | struct usb_serial_port *port; | ||
588 | int rx_processed; | ||
589 | unsigned long rx_bytes; | ||
590 | |||
591 | __u16 interface; /* FT2232C port interface (0 for FT232/245) */ | ||
592 | |||
593 | int force_baud; /* if non-zero, force the baud rate to this value */ | ||
594 | int force_rtscts; /* if non-zero, force RTS-CTS to always be enabled */ | ||
595 | |||
596 | spinlock_t tx_lock; /* spinlock for transmit state */ | ||
597 | unsigned long tx_bytes; | ||
598 | unsigned long tx_outstanding_bytes; | ||
599 | unsigned long tx_outstanding_urbs; | ||
600 | }; | ||
601 | |||
602 | /* Used for TIOCMIWAIT */ | 602 | /* Used for TIOCMIWAIT */ |
603 | #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) | 603 | #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) |
604 | #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) | 604 | #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) |
@@ -609,7 +609,6 @@ struct ftdi_private { | |||
609 | 609 | ||
610 | /* function prototypes for a FTDI serial converter */ | 610 | /* function prototypes for a FTDI serial converter */ |
611 | static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); | 611 | static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id *id); |
612 | static int ftdi_sio_attach (struct usb_serial *serial); | ||
613 | static void ftdi_shutdown (struct usb_serial *serial); | 612 | static void ftdi_shutdown (struct usb_serial *serial); |
614 | static int ftdi_sio_port_probe (struct usb_serial_port *port); | 613 | static int ftdi_sio_port_probe (struct usb_serial_port *port); |
615 | static int ftdi_sio_port_remove (struct usb_serial_port *port); | 614 | static int ftdi_sio_port_remove (struct usb_serial_port *port); |
@@ -663,7 +662,6 @@ static struct usb_serial_driver ftdi_sio_device = { | |||
663 | .ioctl = ftdi_ioctl, | 662 | .ioctl = ftdi_ioctl, |
664 | .set_termios = ftdi_set_termios, | 663 | .set_termios = ftdi_set_termios, |
665 | .break_ctl = ftdi_break_ctl, | 664 | .break_ctl = ftdi_break_ctl, |
666 | .attach = ftdi_sio_attach, | ||
667 | .shutdown = ftdi_shutdown, | 665 | .shutdown = ftdi_shutdown, |
668 | }; | 666 | }; |
669 | 667 | ||
@@ -1149,7 +1147,9 @@ static int create_sysfs_attrs(struct usb_serial_port *port) | |||
1149 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); | 1147 | dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); |
1150 | retval = device_create_file(&port->dev, &dev_attr_event_char); | 1148 | retval = device_create_file(&port->dev, &dev_attr_event_char); |
1151 | if ((!retval) && | 1149 | if ((!retval) && |
1152 | (priv->chip_type == FT232BM || priv->chip_type == FT2232C)) { | 1150 | (priv->chip_type == FT232BM || |
1151 | priv->chip_type == FT2232C || | ||
1152 | priv->chip_type == FT232RL)) { | ||
1153 | retval = device_create_file(&port->dev, | 1153 | retval = device_create_file(&port->dev, |
1154 | &dev_attr_latency_timer); | 1154 | &dev_attr_latency_timer); |
1155 | } | 1155 | } |
@@ -1198,6 +1198,8 @@ static int ftdi_sio_probe (struct usb_serial *serial, const struct usb_device_id | |||
1198 | static int ftdi_sio_port_probe(struct usb_serial_port *port) | 1198 | static int ftdi_sio_port_probe(struct usb_serial_port *port) |
1199 | { | 1199 | { |
1200 | struct ftdi_private *priv; | 1200 | struct ftdi_private *priv; |
1201 | struct ftdi_sio_quirk *quirk = usb_get_serial_data(port->serial); | ||
1202 | |||
1201 | 1203 | ||
1202 | dbg("%s",__FUNCTION__); | 1204 | dbg("%s",__FUNCTION__); |
1203 | 1205 | ||
@@ -1214,6 +1216,9 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1214 | than queue a task to deliver them */ | 1216 | than queue a task to deliver them */ |
1215 | priv->flags = ASYNC_LOW_LATENCY; | 1217 | priv->flags = ASYNC_LOW_LATENCY; |
1216 | 1218 | ||
1219 | if (quirk && quirk->port_probe) | ||
1220 | quirk->port_probe(priv); | ||
1221 | |||
1217 | /* Increase the size of read buffers */ | 1222 | /* Increase the size of read buffers */ |
1218 | kfree(port->bulk_in_buffer); | 1223 | kfree(port->bulk_in_buffer); |
1219 | port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); | 1224 | port->bulk_in_buffer = kmalloc (BUFSZ, GFP_KERNEL); |
@@ -1244,29 +1249,13 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1244 | return 0; | 1249 | return 0; |
1245 | } | 1250 | } |
1246 | 1251 | ||
1247 | /* attach subroutine */ | ||
1248 | static int ftdi_sio_attach (struct usb_serial *serial) | ||
1249 | { | ||
1250 | /* Check for device requiring special set up. */ | ||
1251 | struct ftdi_sio_quirk *quirk = usb_get_serial_data(serial); | ||
1252 | |||
1253 | if (quirk && quirk->setup) | ||
1254 | quirk->setup(serial); | ||
1255 | |||
1256 | return 0; | ||
1257 | } /* ftdi_sio_attach */ | ||
1258 | |||
1259 | |||
1260 | /* Setup for the USB-UIRT device, which requires hardwired | 1252 | /* Setup for the USB-UIRT device, which requires hardwired |
1261 | * baudrate (38400 gets mapped to 312500) */ | 1253 | * baudrate (38400 gets mapped to 312500) */ |
1262 | /* Called from usbserial:serial_probe */ | 1254 | /* Called from usbserial:serial_probe */ |
1263 | static void ftdi_USB_UIRT_setup (struct usb_serial *serial) | 1255 | static void ftdi_USB_UIRT_setup (struct ftdi_private *priv) |
1264 | { | 1256 | { |
1265 | struct ftdi_private *priv; | ||
1266 | |||
1267 | dbg("%s",__FUNCTION__); | 1257 | dbg("%s",__FUNCTION__); |
1268 | 1258 | ||
1269 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1270 | priv->flags |= ASYNC_SPD_CUST; | 1259 | priv->flags |= ASYNC_SPD_CUST; |
1271 | priv->custom_divisor = 77; | 1260 | priv->custom_divisor = 77; |
1272 | priv->force_baud = B38400; | 1261 | priv->force_baud = B38400; |
@@ -1274,13 +1263,10 @@ static void ftdi_USB_UIRT_setup (struct usb_serial *serial) | |||
1274 | 1263 | ||
1275 | /* Setup for the HE-TIRA1 device, which requires hardwired | 1264 | /* Setup for the HE-TIRA1 device, which requires hardwired |
1276 | * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ | 1265 | * baudrate (38400 gets mapped to 100000) and RTS-CTS enabled. */ |
1277 | static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) | 1266 | static void ftdi_HE_TIRA1_setup (struct ftdi_private *priv) |
1278 | { | 1267 | { |
1279 | struct ftdi_private *priv; | ||
1280 | |||
1281 | dbg("%s",__FUNCTION__); | 1268 | dbg("%s",__FUNCTION__); |
1282 | 1269 | ||
1283 | priv = usb_get_serial_port_data(serial->port[0]); | ||
1284 | priv->flags |= ASYNC_SPD_CUST; | 1270 | priv->flags |= ASYNC_SPD_CUST; |
1285 | priv->custom_divisor = 240; | 1271 | priv->custom_divisor = 240; |
1286 | priv->force_baud = B38400; | 1272 | priv->force_baud = B38400; |
@@ -1574,14 +1560,15 @@ static void ftdi_write_bulk_callback (struct urb *urb) | |||
1574 | struct ftdi_private *priv; | 1560 | struct ftdi_private *priv; |
1575 | int data_offset; /* will be 1 for the SIO and 0 otherwise */ | 1561 | int data_offset; /* will be 1 for the SIO and 0 otherwise */ |
1576 | unsigned long countback; | 1562 | unsigned long countback; |
1563 | int status = urb->status; | ||
1577 | 1564 | ||
1578 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | 1565 | /* free up the transfer buffer, as usb_free_urb() does not do this */ |
1579 | kfree (urb->transfer_buffer); | 1566 | kfree (urb->transfer_buffer); |
1580 | 1567 | ||
1581 | dbg("%s - port %d", __FUNCTION__, port->number); | 1568 | dbg("%s - port %d", __FUNCTION__, port->number); |
1582 | 1569 | ||
1583 | if (urb->status) { | 1570 | if (status) { |
1584 | dbg("nonzero write bulk status received: %d", urb->status); | 1571 | dbg("nonzero write bulk status received: %d", status); |
1585 | return; | 1572 | return; |
1586 | } | 1573 | } |
1587 | 1574 | ||
@@ -1657,6 +1644,7 @@ static void ftdi_read_bulk_callback (struct urb *urb) | |||
1657 | struct ftdi_private *priv; | 1644 | struct ftdi_private *priv; |
1658 | unsigned long countread; | 1645 | unsigned long countread; |
1659 | unsigned long flags; | 1646 | unsigned long flags; |
1647 | int status = urb->status; | ||
1660 | 1648 | ||
1661 | if (urb->number_of_packets > 0) { | 1649 | if (urb->number_of_packets > 0) { |
1662 | err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, | 1650 | err("%s transfer_buffer_length %d actual_length %d number of packets %d",__FUNCTION__, |
@@ -1685,9 +1673,10 @@ static void ftdi_read_bulk_callback (struct urb *urb) | |||
1685 | err("%s - Not my urb!", __FUNCTION__); | 1673 | err("%s - Not my urb!", __FUNCTION__); |
1686 | } | 1674 | } |
1687 | 1675 | ||
1688 | if (urb->status) { | 1676 | if (status) { |
1689 | /* This will happen at close every time so it is a dbg not an err */ | 1677 | /* This will happen at close every time so it is a dbg not an err */ |
1690 | dbg("(this is ok on close) nonzero read bulk status received: %d", urb->status); | 1678 | dbg("(this is ok on close) nonzero read bulk status received: " |
1679 | "%d", status); | ||
1691 | return; | 1680 | return; |
1692 | } | 1681 | } |
1693 | 1682 | ||
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 74660a3aa670..04bd3b7a2985 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -1036,15 +1036,16 @@ static void garmin_write_bulk_callback (struct urb *urb) | |||
1036 | unsigned long flags; | 1036 | unsigned long flags; |
1037 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1037 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1038 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1038 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1039 | int status = urb->status; | ||
1039 | 1040 | ||
1040 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | 1041 | /* free up the transfer buffer, as usb_free_urb() does not do this */ |
1041 | kfree (urb->transfer_buffer); | 1042 | kfree (urb->transfer_buffer); |
1042 | 1043 | ||
1043 | dbg("%s - port %d", __FUNCTION__, port->number); | 1044 | dbg("%s - port %d", __FUNCTION__, port->number); |
1044 | 1045 | ||
1045 | if (urb->status) { | 1046 | if (status) { |
1046 | dbg("%s - nonzero write bulk status received: %d", | 1047 | dbg("%s - nonzero write bulk status received: %d", |
1047 | __FUNCTION__, urb->status); | 1048 | __FUNCTION__, status); |
1048 | spin_lock_irqsave(&garmin_data_p->lock, flags); | 1049 | spin_lock_irqsave(&garmin_data_p->lock, flags); |
1049 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; | 1050 | garmin_data_p->flags |= CLEAR_HALT_REQUIRED; |
1050 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | 1051 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
@@ -1281,7 +1282,8 @@ static void garmin_read_bulk_callback (struct urb *urb) | |||
1281 | struct usb_serial *serial = port->serial; | 1282 | struct usb_serial *serial = port->serial; |
1282 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1283 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1283 | unsigned char *data = urb->transfer_buffer; | 1284 | unsigned char *data = urb->transfer_buffer; |
1284 | int status; | 1285 | int status = urb->status; |
1286 | int retval; | ||
1285 | 1287 | ||
1286 | dbg("%s - port %d", __FUNCTION__, port->number); | 1288 | dbg("%s - port %d", __FUNCTION__, port->number); |
1287 | 1289 | ||
@@ -1290,9 +1292,9 @@ static void garmin_read_bulk_callback (struct urb *urb) | |||
1290 | return; | 1292 | return; |
1291 | } | 1293 | } |
1292 | 1294 | ||
1293 | if (urb->status) { | 1295 | if (status) { |
1294 | dbg("%s - nonzero read bulk status received: %d", | 1296 | dbg("%s - nonzero read bulk status received: %d", |
1295 | __FUNCTION__, urb->status); | 1297 | __FUNCTION__, status); |
1296 | return; | 1298 | return; |
1297 | } | 1299 | } |
1298 | 1300 | ||
@@ -1306,19 +1308,19 @@ static void garmin_read_bulk_callback (struct urb *urb) | |||
1306 | spin_lock_irqsave(&garmin_data_p->lock, flags); | 1308 | spin_lock_irqsave(&garmin_data_p->lock, flags); |
1307 | garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART; | 1309 | garmin_data_p->flags &= ~FLAGS_BULK_IN_RESTART; |
1308 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); | 1310 | spin_unlock_irqrestore(&garmin_data_p->lock, flags); |
1309 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 1311 | retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
1310 | if (status) | 1312 | if (retval) |
1311 | dev_err(&port->dev, | 1313 | dev_err(&port->dev, |
1312 | "%s - failed resubmitting read urb, error %d\n", | 1314 | "%s - failed resubmitting read urb, error %d\n", |
1313 | __FUNCTION__, status); | 1315 | __FUNCTION__, retval); |
1314 | } else if (urb->actual_length > 0) { | 1316 | } else if (urb->actual_length > 0) { |
1315 | /* Continue trying to read until nothing more is received */ | 1317 | /* Continue trying to read until nothing more is received */ |
1316 | if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) { | 1318 | if (0 == (garmin_data_p->flags & FLAGS_THROTTLED)) { |
1317 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 1319 | retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
1318 | if (status) | 1320 | if (retval) |
1319 | dev_err(&port->dev, | 1321 | dev_err(&port->dev, |
1320 | "%s - failed resubmitting read urb, error %d\n", | 1322 | "%s - failed resubmitting read urb, " |
1321 | __FUNCTION__, status); | 1323 | "error %d\n", __FUNCTION__, retval); |
1322 | } | 1324 | } |
1323 | } else { | 1325 | } else { |
1324 | dbg("%s - end of bulk data", __FUNCTION__); | 1326 | dbg("%s - end of bulk data", __FUNCTION__); |
@@ -1333,13 +1335,14 @@ static void garmin_read_bulk_callback (struct urb *urb) | |||
1333 | static void garmin_read_int_callback (struct urb *urb) | 1335 | static void garmin_read_int_callback (struct urb *urb) |
1334 | { | 1336 | { |
1335 | unsigned long flags; | 1337 | unsigned long flags; |
1336 | int status; | 1338 | int retval; |
1337 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1339 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1338 | struct usb_serial *serial = port->serial; | 1340 | struct usb_serial *serial = port->serial; |
1339 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); | 1341 | struct garmin_data * garmin_data_p = usb_get_serial_port_data(port); |
1340 | unsigned char *data = urb->transfer_buffer; | 1342 | unsigned char *data = urb->transfer_buffer; |
1343 | int status = urb->status; | ||
1341 | 1344 | ||
1342 | switch (urb->status) { | 1345 | switch (status) { |
1343 | case 0: | 1346 | case 0: |
1344 | /* success */ | 1347 | /* success */ |
1345 | break; | 1348 | break; |
@@ -1348,11 +1351,11 @@ static void garmin_read_int_callback (struct urb *urb) | |||
1348 | case -ESHUTDOWN: | 1351 | case -ESHUTDOWN: |
1349 | /* this urb is terminated, clean up */ | 1352 | /* this urb is terminated, clean up */ |
1350 | dbg("%s - urb shutting down with status: %d", | 1353 | dbg("%s - urb shutting down with status: %d", |
1351 | __FUNCTION__, urb->status); | 1354 | __FUNCTION__, status); |
1352 | return; | 1355 | return; |
1353 | default: | 1356 | default: |
1354 | dbg("%s - nonzero urb status received: %d", | 1357 | dbg("%s - nonzero urb status received: %d", |
1355 | __FUNCTION__, urb->status); | 1358 | __FUNCTION__, status); |
1356 | return; | 1359 | return; |
1357 | } | 1360 | } |
1358 | 1361 | ||
@@ -1374,11 +1377,11 @@ static void garmin_read_int_callback (struct urb *urb) | |||
1374 | port->read_urb->transfer_buffer, | 1377 | port->read_urb->transfer_buffer, |
1375 | port->read_urb->transfer_buffer_length, | 1378 | port->read_urb->transfer_buffer_length, |
1376 | garmin_read_bulk_callback, port); | 1379 | garmin_read_bulk_callback, port); |
1377 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 1380 | retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
1378 | if (status) { | 1381 | if (retval) { |
1379 | dev_err(&port->dev, | 1382 | dev_err(&port->dev, |
1380 | "%s - failed submitting read urb, error %d\n", | 1383 | "%s - failed submitting read urb, error %d\n", |
1381 | __FUNCTION__, status); | 1384 | __FUNCTION__, retval); |
1382 | } else { | 1385 | } else { |
1383 | spin_lock_irqsave(&garmin_data_p->lock, flags); | 1386 | spin_lock_irqsave(&garmin_data_p->lock, flags); |
1384 | garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE; | 1387 | garmin_data_p->flags |= FLAGS_BULK_IN_ACTIVE; |
@@ -1422,11 +1425,11 @@ static void garmin_read_int_callback (struct urb *urb) | |||
1422 | } | 1425 | } |
1423 | 1426 | ||
1424 | port->interrupt_in_urb->dev = port->serial->dev; | 1427 | port->interrupt_in_urb->dev = port->serial->dev; |
1425 | status = usb_submit_urb (urb, GFP_ATOMIC); | 1428 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
1426 | if (status) | 1429 | if (retval) |
1427 | dev_err(&urb->dev->dev, | 1430 | dev_err(&urb->dev->dev, |
1428 | "%s - Error %d submitting interrupt urb\n", | 1431 | "%s - Error %d submitting interrupt urb\n", |
1429 | __FUNCTION__, status); | 1432 | __FUNCTION__, retval); |
1430 | } | 1433 | } |
1431 | 1434 | ||
1432 | 1435 | ||
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 4f8282ad7720..88a2c7dce335 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -69,6 +69,7 @@ struct usb_serial_driver usb_serial_generic_device = { | |||
69 | .shutdown = usb_serial_generic_shutdown, | 69 | .shutdown = usb_serial_generic_shutdown, |
70 | .throttle = usb_serial_generic_throttle, | 70 | .throttle = usb_serial_generic_throttle, |
71 | .unthrottle = usb_serial_generic_unthrottle, | 71 | .unthrottle = usb_serial_generic_unthrottle, |
72 | .resume = usb_serial_generic_resume, | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | static int generic_probe(struct usb_interface *interface, | 75 | static int generic_probe(struct usb_interface *interface, |
@@ -169,6 +170,23 @@ static void generic_cleanup (struct usb_serial_port *port) | |||
169 | } | 170 | } |
170 | } | 171 | } |
171 | 172 | ||
173 | int usb_serial_generic_resume(struct usb_serial *serial) | ||
174 | { | ||
175 | struct usb_serial_port *port; | ||
176 | int i, c = 0, r; | ||
177 | |||
178 | for (i = 0; i < serial->num_ports; i++) { | ||
179 | port = serial->port[i]; | ||
180 | if (port->open_count && port->read_urb) { | ||
181 | r = usb_submit_urb(port->read_urb, GFP_NOIO); | ||
182 | if (r < 0) | ||
183 | c++; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | return c ? -EIO : 0; | ||
188 | } | ||
189 | |||
172 | void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp) | 190 | void usb_serial_generic_close (struct usb_serial_port *port, struct file * filp) |
173 | { | 191 | { |
174 | dbg("%s - port %d", __FUNCTION__, port->number); | 192 | dbg("%s - port %d", __FUNCTION__, port->number); |
@@ -263,79 +281,82 @@ int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port) | |||
263 | return (chars); | 281 | return (chars); |
264 | } | 282 | } |
265 | 283 | ||
266 | /* Push data to tty layer and resubmit the bulk read URB */ | 284 | |
267 | static void flush_and_resubmit_read_urb (struct usb_serial_port *port) | 285 | static void resubmit_read_urb(struct usb_serial_port *port, gfp_t mem_flags) |
268 | { | 286 | { |
269 | struct usb_serial *serial = port->serial; | ||
270 | struct urb *urb = port->read_urb; | 287 | struct urb *urb = port->read_urb; |
271 | struct tty_struct *tty = port->tty; | 288 | struct usb_serial *serial = port->serial; |
272 | int result; | 289 | int result; |
273 | 290 | ||
274 | /* Push data to tty */ | ||
275 | if (tty && urb->actual_length) { | ||
276 | tty_buffer_request_room(tty, urb->actual_length); | ||
277 | tty_insert_flip_string(tty, urb->transfer_buffer, urb->actual_length); | ||
278 | tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */ | ||
279 | } | ||
280 | |||
281 | /* Continue reading from device */ | 291 | /* Continue reading from device */ |
282 | usb_fill_bulk_urb (port->read_urb, serial->dev, | 292 | usb_fill_bulk_urb (urb, serial->dev, |
283 | usb_rcvbulkpipe (serial->dev, | 293 | usb_rcvbulkpipe (serial->dev, |
284 | port->bulk_in_endpointAddress), | 294 | port->bulk_in_endpointAddress), |
285 | port->read_urb->transfer_buffer, | 295 | urb->transfer_buffer, |
286 | port->read_urb->transfer_buffer_length, | 296 | urb->transfer_buffer_length, |
287 | ((serial->type->read_bulk_callback) ? | 297 | ((serial->type->read_bulk_callback) ? |
288 | serial->type->read_bulk_callback : | 298 | serial->type->read_bulk_callback : |
289 | usb_serial_generic_read_bulk_callback), port); | 299 | usb_serial_generic_read_bulk_callback), port); |
290 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 300 | result = usb_submit_urb(urb, mem_flags); |
291 | if (result) | 301 | if (result) |
292 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | 302 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); |
293 | } | 303 | } |
294 | 304 | ||
305 | /* Push data to tty layer and resubmit the bulk read URB */ | ||
306 | static void flush_and_resubmit_read_urb (struct usb_serial_port *port) | ||
307 | { | ||
308 | struct urb *urb = port->read_urb; | ||
309 | struct tty_struct *tty = port->tty; | ||
310 | int room; | ||
311 | |||
312 | /* Push data to tty */ | ||
313 | if (tty && urb->actual_length) { | ||
314 | room = tty_buffer_request_room(tty, urb->actual_length); | ||
315 | if (room) { | ||
316 | tty_insert_flip_string(tty, urb->transfer_buffer, room); | ||
317 | tty_flip_buffer_push(tty); /* is this allowed from an URB callback ? */ | ||
318 | } | ||
319 | } | ||
320 | |||
321 | resubmit_read_urb(port, GFP_ATOMIC); | ||
322 | } | ||
323 | |||
295 | void usb_serial_generic_read_bulk_callback (struct urb *urb) | 324 | void usb_serial_generic_read_bulk_callback (struct urb *urb) |
296 | { | 325 | { |
297 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 326 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
298 | unsigned char *data = urb->transfer_buffer; | 327 | unsigned char *data = urb->transfer_buffer; |
299 | int is_throttled; | 328 | int status = urb->status; |
300 | unsigned long flags; | ||
301 | 329 | ||
302 | dbg("%s - port %d", __FUNCTION__, port->number); | 330 | dbg("%s - port %d", __FUNCTION__, port->number); |
303 | 331 | ||
304 | if (urb->status) { | 332 | if (unlikely(status != 0)) { |
305 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 333 | dbg("%s - nonzero read bulk status received: %d", |
334 | __FUNCTION__, status); | ||
306 | return; | 335 | return; |
307 | } | 336 | } |
308 | 337 | ||
309 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); | 338 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); |
310 | 339 | ||
311 | /* Throttle the device if requested by tty */ | 340 | /* Throttle the device if requested by tty */ |
312 | if (urb->actual_length) { | 341 | spin_lock(&port->lock); |
313 | spin_lock_irqsave(&port->lock, flags); | 342 | if (!(port->throttled = port->throttle_req)) |
314 | is_throttled = port->throttled = port->throttle_req; | 343 | /* Handle data and continue reading from device */ |
315 | spin_unlock_irqrestore(&port->lock, flags); | 344 | flush_and_resubmit_read_urb(port); |
316 | if (is_throttled) { | 345 | spin_unlock(&port->lock); |
317 | /* Let the received data linger in the read URB; | ||
318 | * usb_serial_generic_unthrottle() will pick it | ||
319 | * up later. */ | ||
320 | dbg("%s - throttling device", __FUNCTION__); | ||
321 | return; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | /* Handle data and continue reading from device */ | ||
326 | flush_and_resubmit_read_urb(port); | ||
327 | } | 346 | } |
328 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); | 347 | EXPORT_SYMBOL_GPL(usb_serial_generic_read_bulk_callback); |
329 | 348 | ||
330 | void usb_serial_generic_write_bulk_callback (struct urb *urb) | 349 | void usb_serial_generic_write_bulk_callback (struct urb *urb) |
331 | { | 350 | { |
332 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 351 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
352 | int status = urb->status; | ||
333 | 353 | ||
334 | dbg("%s - port %d", __FUNCTION__, port->number); | 354 | dbg("%s - port %d", __FUNCTION__, port->number); |
335 | 355 | ||
336 | port->write_urb_busy = 0; | 356 | port->write_urb_busy = 0; |
337 | if (urb->status) { | 357 | if (status) { |
338 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 358 | dbg("%s - nonzero write bulk status received: %d", |
359 | __FUNCTION__, status); | ||
339 | return; | 360 | return; |
340 | } | 361 | } |
341 | 362 | ||
@@ -370,8 +391,8 @@ void usb_serial_generic_unthrottle (struct usb_serial_port *port) | |||
370 | spin_unlock_irqrestore(&port->lock, flags); | 391 | spin_unlock_irqrestore(&port->lock, flags); |
371 | 392 | ||
372 | if (was_throttled) { | 393 | if (was_throttled) { |
373 | /* Handle pending data and resume reading from device */ | 394 | /* Resume reading from device */ |
374 | flush_and_resubmit_read_urb(port); | 395 | resubmit_read_urb(port, GFP_KERNEL); |
375 | } | 396 | } |
376 | } | 397 | } |
377 | 398 | ||
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 056e1923c4de..dd42f57089ff 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
@@ -599,10 +599,11 @@ static void edge_interrupt_callback (struct urb *urb) | |||
599 | int txCredits; | 599 | int txCredits; |
600 | int portNumber; | 600 | int portNumber; |
601 | int result; | 601 | int result; |
602 | int status = urb->status; | ||
602 | 603 | ||
603 | dbg("%s", __FUNCTION__); | 604 | dbg("%s", __FUNCTION__); |
604 | 605 | ||
605 | switch (urb->status) { | 606 | switch (status) { |
606 | case 0: | 607 | case 0: |
607 | /* success */ | 608 | /* success */ |
608 | break; | 609 | break; |
@@ -610,10 +611,12 @@ static void edge_interrupt_callback (struct urb *urb) | |||
610 | case -ENOENT: | 611 | case -ENOENT: |
611 | case -ESHUTDOWN: | 612 | case -ESHUTDOWN: |
612 | /* this urb is terminated, clean up */ | 613 | /* this urb is terminated, clean up */ |
613 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 614 | dbg("%s - urb shutting down with status: %d", |
615 | __FUNCTION__, status); | ||
614 | return; | 616 | return; |
615 | default: | 617 | default: |
616 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 618 | dbg("%s - nonzero urb status received: %d", |
619 | __FUNCTION__, status); | ||
617 | goto exit; | 620 | goto exit; |
618 | } | 621 | } |
619 | 622 | ||
@@ -688,13 +691,15 @@ static void edge_bulk_in_callback (struct urb *urb) | |||
688 | { | 691 | { |
689 | struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; | 692 | struct edgeport_serial *edge_serial = (struct edgeport_serial *)urb->context; |
690 | unsigned char *data = urb->transfer_buffer; | 693 | unsigned char *data = urb->transfer_buffer; |
691 | int status; | 694 | int retval; |
692 | __u16 raw_data_length; | 695 | __u16 raw_data_length; |
696 | int status = urb->status; | ||
693 | 697 | ||
694 | dbg("%s", __FUNCTION__); | 698 | dbg("%s", __FUNCTION__); |
695 | 699 | ||
696 | if (urb->status) { | 700 | if (status) { |
697 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 701 | dbg("%s - nonzero read bulk status received: %d", |
702 | __FUNCTION__, status); | ||
698 | edge_serial->read_in_progress = false; | 703 | edge_serial->read_in_progress = false; |
699 | return; | 704 | return; |
700 | } | 705 | } |
@@ -722,9 +727,11 @@ static void edge_bulk_in_callback (struct urb *urb) | |||
722 | if (edge_serial->rxBytesAvail > 0) { | 727 | if (edge_serial->rxBytesAvail > 0) { |
723 | dbg("%s - posting a read", __FUNCTION__); | 728 | dbg("%s - posting a read", __FUNCTION__); |
724 | edge_serial->read_urb->dev = edge_serial->serial->dev; | 729 | edge_serial->read_urb->dev = edge_serial->serial->dev; |
725 | status = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); | 730 | retval = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); |
726 | if (status) { | 731 | if (retval) { |
727 | dev_err(&urb->dev->dev, "%s - usb_submit_urb(read bulk) failed, status = %d\n", __FUNCTION__, status); | 732 | dev_err(&urb->dev->dev, |
733 | "%s - usb_submit_urb(read bulk) failed, " | ||
734 | "retval = %d\n", __FUNCTION__, retval); | ||
728 | edge_serial->read_in_progress = false; | 735 | edge_serial->read_in_progress = false; |
729 | } | 736 | } |
730 | } else { | 737 | } else { |
@@ -744,11 +751,13 @@ static void edge_bulk_out_data_callback (struct urb *urb) | |||
744 | { | 751 | { |
745 | struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; | 752 | struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; |
746 | struct tty_struct *tty; | 753 | struct tty_struct *tty; |
754 | int status = urb->status; | ||
747 | 755 | ||
748 | dbg("%s", __FUNCTION__); | 756 | dbg("%s", __FUNCTION__); |
749 | 757 | ||
750 | if (urb->status) { | 758 | if (status) { |
751 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 759 | dbg("%s - nonzero write bulk status received: %d", |
760 | __FUNCTION__, status); | ||
752 | } | 761 | } |
753 | 762 | ||
754 | tty = edge_port->port->tty; | 763 | tty = edge_port->port->tty; |
@@ -1504,15 +1513,6 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old | |||
1504 | } | 1513 | } |
1505 | 1514 | ||
1506 | cflag = tty->termios->c_cflag; | 1515 | cflag = tty->termios->c_cflag; |
1507 | /* check that they really want us to change something */ | ||
1508 | if (old_termios) { | ||
1509 | if (cflag == old_termios->c_cflag && | ||
1510 | tty->termios->c_iflag == old_termios->c_iflag) { | ||
1511 | dbg("%s - nothing to change", __FUNCTION__); | ||
1512 | return; | ||
1513 | } | ||
1514 | } | ||
1515 | |||
1516 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, | 1516 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, |
1517 | tty->termios->c_cflag, tty->termios->c_iflag); | 1517 | tty->termios->c_cflag, tty->termios->c_iflag); |
1518 | if (old_termios) { | 1518 | if (old_termios) { |
diff --git a/drivers/usb/serial/io_fw_down3.h b/drivers/usb/serial/io_fw_down3.h index 93b56d68a27b..4496b068c50f 100644 --- a/drivers/usb/serial/io_fw_down3.h +++ b/drivers/usb/serial/io_fw_down3.h | |||
@@ -5,7 +5,7 @@ | |||
5 | //************************************************************** | 5 | //************************************************************** |
6 | 6 | ||
7 | 7 | ||
8 | static int IMAGE_SIZE = 12749; | 8 | static int IMAGE_SIZE = 12938; |
9 | 9 | ||
10 | struct EDGE_FIRMWARE_VERSION_INFO | 10 | struct EDGE_FIRMWARE_VERSION_INFO |
11 | { | 11 | { |
@@ -16,7 +16,7 @@ struct EDGE_FIRMWARE_VERSION_INFO | |||
16 | 16 | ||
17 | static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME = | 17 | static struct EDGE_FIRMWARE_VERSION_INFO IMAGE_VERSION_NAME = |
18 | { | 18 | { |
19 | 4, 10, 0 // Major, Minor, Build | 19 | 4, 80, 0 // Major, Minor, Build |
20 | 20 | ||
21 | }; | 21 | }; |
22 | 22 | ||
@@ -27,16 +27,16 @@ static unsigned char IMAGE_ARRAY_NAME[] = | |||
27 | // WORD Length; | 27 | // WORD Length; |
28 | // BYTE CheckSum; | 28 | // BYTE CheckSum; |
29 | // }; | 29 | // }; |
30 | 0xca, 0x31, | 30 | 0x87, 0x32, |
31 | 0xa8, | 31 | 0x9a, |
32 | 32 | ||
33 | 0x02, 0x26, 0xfe, 0x02, 0x21, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, | 33 | 0x02, 0x27, 0xbf, 0x02, 0x21, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x1e, 0x00, 0x00, |
34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x3f, | 34 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x1a, 0x85, 0x3f, |
35 | 0x8c, 0x85, 0x40, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, | 35 | 0x8c, 0x85, 0x40, 0x8a, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, |
36 | 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3e, | 36 | 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0xe5, 0x3e, |
37 | 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x3e, 0x75, | 37 | 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x2b, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0xa6, 0x81, 0xe5, 0x3e, 0x75, |
38 | 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x8c, 0xe5, 0x81, | 38 | 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0x78, 0x8c, 0xe5, 0x81, |
39 | 0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0x94, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, | 39 | 0x04, 0xc3, 0x98, 0xf9, 0x94, 0x22, 0x40, 0x03, 0x02, 0x11, 0xdc, 0xe6, 0xf0, 0x08, 0xa3, 0xd9, |
40 | 0xfa, 0x74, 0x08, 0x25, 0x3e, 0xf8, 0x05, 0x3e, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x3e, | 40 | 0xfa, 0x74, 0x08, 0x25, 0x3e, 0xf8, 0x05, 0x3e, 0x08, 0xe6, 0x54, 0x80, 0x70, 0x0c, 0xe5, 0x3e, |
41 | 0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x3e, 0x00, 0x80, 0xef, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0x86, | 41 | 0xb4, 0x07, 0xf3, 0x78, 0x08, 0x75, 0x3e, 0x00, 0x80, 0xef, 0xe5, 0x3e, 0x24, 0x10, 0xf8, 0x86, |
42 | 0x81, 0xe5, 0x3e, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, | 42 | 0x81, 0xe5, 0x3e, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, |
@@ -49,387 +49,398 @@ static unsigned char IMAGE_ARRAY_NAME[] = | |||
49 | 0xc9, 0xf0, 0x69, 0x60, 0x02, 0x7e, 0x04, 0xa3, 0xe0, 0xca, 0xf0, 0x6a, 0x60, 0x02, 0x7e, 0x04, | 49 | 0xc9, 0xf0, 0x69, 0x60, 0x02, 0x7e, 0x04, 0xa3, 0xe0, 0xca, 0xf0, 0x6a, 0x60, 0x02, 0x7e, 0x04, |
50 | 0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, | 50 | 0xa3, 0xe0, 0xcb, 0xf0, 0x6b, 0x60, 0x02, 0x7e, 0x04, 0x22, 0xc0, 0xe0, 0xc0, 0xd0, 0xc0, 0xf0, |
51 | 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, | 51 | 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, |
52 | 0xc0, 0x06, 0xc0, 0x07, 0x90, 0xff, 0x93, 0x74, 0x01, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, | 52 | 0xc0, 0x06, 0xc0, 0x07, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x60, 0x23, 0x74, |
53 | 0x02, 0x11, 0x94, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xaf, 0xf5, 0x82, 0x74, 0xfa, 0xf5, | 53 | 0x66, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 0xf0, 0x70, 0x16, 0x74, 0xff, 0xf0, 0x74, |
54 | 0x83, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, | 54 | 0x1c, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x60, 0x04, 0x14, 0xf0, 0x70, 0x04, 0xc2, 0x90, |
55 | 0x90, 0xff, 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, | 55 | 0x80, 0xfc, 0x90, 0xff, 0x93, 0x74, 0x81, 0xf0, 0xe5, 0x81, 0x94, 0xfd, 0x40, 0x03, 0x02, 0x11, |
56 | 0xb4, 0x02, 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, | 56 | 0xdc, 0x85, 0x41, 0x8d, 0x85, 0x42, 0x8b, 0x74, 0xb2, 0xf5, 0x82, 0x74, 0xfa, 0xf5, 0x83, 0xe0, |
57 | 0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, | 57 | 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x4a, 0xe0, 0x30, 0xe7, 0x2c, 0x90, 0xff, |
58 | 0xa3, 0xe0, 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, | 58 | 0x4e, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x20, 0xb4, 0x02, |
59 | 0x90, 0xff, 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, | 59 | 0x1d, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x28, 0x4e, 0x80, |
60 | 0xb4, 0x02, 0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x27, | 60 | 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x04, 0xd0, 0x83, 0xd0, 0x82, 0xa3, 0xe0, |
61 | 0x8d, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, | 61 | 0xb4, 0x01, 0x1b, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x52, 0xe0, 0x30, 0xe7, 0x2c, 0x90, 0xff, |
62 | 0x80, 0x03, 0x02, 0x02, 0x62, 0x74, 0x15, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, | 62 | 0x56, 0xe0, 0x30, 0xe7, 0x25, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x02, 0xf0, 0x80, 0x25, 0xb4, 0x02, |
63 | 0xf1, 0x20, 0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, | 63 | 0x22, 0xc0, 0x82, 0xc0, 0x83, 0x90, 0xff, 0x7a, 0xe0, 0x30, 0xe7, 0x05, 0x12, 0x28, 0x4e, 0x80, |
64 | 0x14, 0xfc, 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, | 64 | 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x74, 0x03, 0xf0, 0x80, 0x09, 0xd0, 0x83, 0xd0, 0x82, 0x80, 0x03, |
65 | 0x7e, 0x01, 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x33, 0x12, 0x00, 0xc9, 0xee, | 65 | 0x02, 0x02, 0x90, 0x74, 0x16, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x20, 0x04, 0xf1, 0x20, |
66 | 0x64, 0x04, 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, | 66 | 0x02, 0x03, 0x30, 0x01, 0xeb, 0x74, 0x19, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xe0, 0x14, 0xfc, |
67 | 0x02, 0x60, 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x33, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, | 67 | 0xf0, 0xa3, 0xe0, 0xfd, 0xa3, 0xe0, 0xfe, 0x64, 0x04, 0x70, 0x0f, 0xec, 0x70, 0x62, 0x7e, 0x01, |
68 | 0x33, 0x7c, 0x0a, 0x74, 0x18, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, | 68 | 0x12, 0x00, 0xc9, 0x7c, 0x0a, 0x7d, 0xfa, 0x02, 0x02, 0x61, 0x12, 0x00, 0xc9, 0xee, 0x64, 0x04, |
69 | 0xa3, 0xee, 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, | 69 | 0x60, 0x1d, 0xec, 0x70, 0x4b, 0x7c, 0x0a, 0xed, 0x14, 0xfd, 0x70, 0x15, 0xee, 0x64, 0x02, 0x60, |
70 | 0x80, 0x10, 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, | 70 | 0x07, 0x7e, 0x02, 0x7d, 0x32, 0x02, 0x02, 0x61, 0x7e, 0x01, 0x7d, 0xfa, 0x02, 0x02, 0x61, 0x7c, |
71 | 0xd2, 0xb1, 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, | 71 | 0x0a, 0x74, 0x19, 0xf5, 0x82, 0x74, 0xf9, 0xf5, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, 0xa3, 0xee, |
72 | 0x60, 0x08, 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, | 72 | 0xf0, 0x14, 0x60, 0x18, 0x20, 0xe1, 0x0f, 0x20, 0x01, 0x06, 0xd2, 0xb1, 0xc2, 0xb0, 0x80, 0x10, |
73 | 0x60, 0x13, 0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, | 73 | 0xc2, 0xb1, 0xd2, 0xb0, 0x80, 0x0a, 0xc2, 0xb1, 0xc2, 0xb0, 0x80, 0x04, 0xd2, 0xb0, 0xd2, 0xb1, |
74 | 0x0f, 0xd2, 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, | 74 | 0x78, 0x19, 0x79, 0x09, 0x7a, 0x07, 0xe7, 0x70, 0x04, 0xa6, 0x00, 0x80, 0x0b, 0xe6, 0x60, 0x08, |
75 | 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, | 75 | 0x16, 0xe6, 0x70, 0x04, 0xe7, 0x44, 0x80, 0xf7, 0x08, 0x09, 0xda, 0xea, 0xe5, 0x3d, 0x60, 0x13, |
76 | 0x90, 0xff, 0x04, 0xe0, 0x90, 0xfa, 0xb6, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, | 76 | 0x14, 0xf5, 0x3d, 0x70, 0x0e, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x57, 0xd2, |
77 | 0xec, 0xff, 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, | 77 | 0x8c, 0xd2, 0x8d, 0xd0, 0x07, 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, |
78 | 0x01, 0x7f, 0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, | 78 | 0x01, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0xd0, 0xd0, 0xd0, 0xe0, 0x32, 0x90, 0xff, |
79 | 0xff, 0xea, 0x90, 0xfa, 0xba, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0x30, 0xe4, 0xf5, 0x4d, 0xe5, | 79 | 0x04, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x90, 0xff, 0x06, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, |
80 | 0x4d, 0xc3, 0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0x11, 0xe4, 0x12, 0x1a, 0x38, 0x05, 0x4d, 0x04, | 80 | 0xea, 0xfe, 0xef, 0xc3, 0x94, 0x08, 0xee, 0x94, 0x01, 0x50, 0x02, 0x80, 0x04, 0x7e, 0x01, 0x7f, |
81 | 0x12, 0x1c, 0x02, 0x80, 0xea, 0x12, 0x1c, 0x30, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, | 81 | 0x08, 0x8e, 0x3b, 0x8f, 0x3c, 0x90, 0xff, 0x02, 0xe0, 0xfc, 0xa3, 0xe0, 0xfa, 0xec, 0xff, 0xea, |
82 | 0xc0, 0x70, 0x03, 0x02, 0x08, 0xc5, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, | 82 | 0x90, 0xfa, 0xbd, 0xf0, 0xef, 0xa3, 0xf0, 0x12, 0x1c, 0xe0, 0xe4, 0xf5, 0x4d, 0xe5, 0x4d, 0xc3, |
83 | 0xe0, 0xfe, 0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, | 83 | 0x94, 0x02, 0x50, 0x0f, 0x12, 0x1c, 0xc1, 0xe4, 0x12, 0x1a, 0xe8, 0x05, 0x4d, 0x04, 0x12, 0x1c, |
84 | 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0x4c, 0x03, 0x56, 0x00, 0x04, 0x29, 0x01, 0x05, 0x3c, 0x03, | 84 | 0xb2, 0x80, 0xea, 0x12, 0x1c, 0xe0, 0x90, 0xff, 0x00, 0xe0, 0xff, 0x54, 0x60, 0x24, 0xc0, 0x70, |
85 | 0x06, 0x03, 0x05, 0x06, 0x45, 0x06, 0x07, 0xa7, 0x08, 0x07, 0xef, 0x09, 0x08, 0x4b, 0x0a, 0x08, | 85 | 0x03, 0x02, 0x08, 0xf3, 0x24, 0x40, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xfe, |
86 | 0x8b, 0x0b, 0x00, 0x00, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, | 86 | 0x54, 0x0f, 0xf5, 0x4d, 0xee, 0x30, 0xe7, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0a, 0x90, 0xff, |
87 | 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x02, 0x45, | 87 | 0x01, 0xe0, 0x12, 0x1b, 0xfc, 0x03, 0x84, 0x00, 0x04, 0x57, 0x01, 0x05, 0x6a, 0x03, 0x06, 0x31, |
88 | 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, | 88 | 0x05, 0x06, 0x73, 0x06, 0x07, 0xd5, 0x08, 0x08, 0x1d, 0x09, 0x08, 0x79, 0x0a, 0x08, 0xb9, 0x0b, |
89 | 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x11, 0x74, | 89 | 0x00, 0x00, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, |
90 | 0x01, 0x12, 0x1a, 0x38, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0x11, 0x74, 0x02, 0x12, | 90 | 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x64, 0x02, 0x45, 0x3b, 0x60, |
91 | 0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb6, 0xe0, | 91 | 0x03, 0x02, 0x0f, 0x6e, 0xef, 0x54, 0x1f, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x47, 0x24, 0x02, 0x60, |
92 | 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, | 92 | 0x03, 0x02, 0x0f, 0x6e, 0xee, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1c, 0xc1, 0x74, 0x01, 0x12, |
93 | 0x26, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb6, 0xe0, 0xff, | 93 | 0x1a, 0xe8, 0x78, 0x67, 0xe6, 0x30, 0xe0, 0x08, 0x12, 0x1c, 0xc1, 0x74, 0x02, 0x12, 0x1a, 0xe8, |
94 | 0x60, 0x07, 0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, | 94 | 0x7f, 0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x09, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, |
95 | 0x26, 0xe5, 0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0x0e, 0x12, 0x1a, | 95 | 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xd3, 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x7f, |
96 | 0x38, 0x80, 0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0x0e, 0x12, 0x1a, 0x38, 0x80, 0x19, 0x15, 0x4d, | 96 | 0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x0e, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x60, 0x07, |
97 | 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x80, 0x09, 0x12, 0x1c, | 97 | 0x64, 0x80, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0xfa, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe5, |
98 | 0xb3, 0x12, 0x1c, 0x0c, 0x12, 0x1a, 0x38, 0x12, 0x1c, 0x11, 0x12, 0x19, 0xf2, 0x60, 0x05, 0x74, | 98 | 0x4d, 0x70, 0x19, 0x30, 0x0a, 0x0b, 0x90, 0xff, 0x80, 0x12, 0x1c, 0xbe, 0x12, 0x1a, 0xe8, 0x80, |
99 | 0x01, 0x12, 0x1a, 0x38, 0x7f, 0x02, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, | 99 | 0x24, 0x90, 0xff, 0x82, 0x12, 0x1c, 0xbe, 0x12, 0x1a, 0xe8, 0x80, 0x19, 0x15, 0x4d, 0x30, 0x0a, |
100 | 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x14, 0x60, 0x2d, | 100 | 0x0b, 0x12, 0x1d, 0x55, 0x12, 0x1c, 0xbc, 0x12, 0x1a, 0xe8, 0x80, 0x09, 0x12, 0x1d, 0x63, 0x12, |
101 | 0x14, 0x60, 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x04, | 101 | 0x1c, 0xbc, 0x12, 0x1a, 0xe8, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xa2, 0x60, 0x05, 0x74, 0x01, 0x12, |
102 | 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, | 102 | 0x1a, 0xe8, 0x7f, 0x02, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, |
103 | 0x0f, 0x26, 0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, | 103 | 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x14, 0x60, 0x2d, 0x14, 0x60, |
104 | 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb6, | 104 | 0x59, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x04, 0xa3, 0xe0, |
105 | 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb6, 0xe0, 0xd3, | 105 | 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, |
106 | 0x94, 0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, | 106 | 0x78, 0x67, 0xe6, 0x54, 0xfe, 0xf6, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x06, |
107 | 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0xb2, 0x40, 0x03, 0x02, 0x0f, | 107 | 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x09, 0x90, 0xfa, 0xb9, 0xe0, 0x60, |
108 | 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, | 108 | 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x0c, 0x90, 0xfa, 0xb9, 0xe0, 0xd3, 0x94, 0x01, |
109 | 0x07, 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, | 109 | 0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, |
110 | 0x54, 0xf7, 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, | 110 | 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0xfa, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0xe5, |
111 | 0x20, 0x24, 0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, | 111 | 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x07, 0xe5, |
112 | 0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2d, 0xa8, 0x80, | 112 | 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x4d, 0x70, 0x0f, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, |
113 | 0x1d, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x0e, | 113 | 0xf0, 0x90, 0xff, 0x80, 0xe0, 0x54, 0xf7, 0xf0, 0x22, 0xe5, 0x4d, 0x24, 0xfe, 0x60, 0x20, 0x24, |
114 | 0xe4, 0xfd, 0x7f, 0x04, 0x12, 0x2d, 0xa8, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0x32, 0x15, 0x4d, | 114 | 0xfb, 0x60, 0x34, 0x24, 0x06, 0x70, 0x35, 0x30, 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, |
115 | 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1c, | 115 | 0x03, 0x12, 0x2e, 0x79, 0x80, 0x26, 0xe4, 0xfd, 0x7f, 0x03, 0x12, 0x2e, 0x79, 0x80, 0x1d, 0x30, |
116 | 0xb3, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, | 116 | 0x0a, 0x0c, 0xa2, 0x0a, 0xe4, 0x33, 0xfd, 0x7f, 0x04, 0x12, 0x2e, 0x79, 0x80, 0x0e, 0xe4, 0xfd, |
117 | 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, | 117 | 0x7f, 0x04, 0x12, 0x2e, 0x79, 0x80, 0x05, 0x7f, 0x87, 0x12, 0x31, 0xef, 0x15, 0x4d, 0x30, 0x0a, |
118 | 0x14, 0x60, 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, | 118 | 0x0b, 0x12, 0x1d, 0x55, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x80, 0x09, 0x12, 0x1d, 0x63, 0xf5, |
119 | 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, | 119 | 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, |
120 | 0x60, 0x03, 0x02, 0x0f, 0x26, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x31, 0xb1, | 120 | 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x14, 0x60, |
121 | 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe0, 0x07, | 121 | 0x2d, 0x14, 0x60, 0x55, 0x24, 0x02, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, |
122 | 0xe5, 0x4d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, | 122 | 0x04, 0xa3, 0xe0, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, |
123 | 0x01, 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xfa, 0xba, 0xe0, 0x70, | 123 | 0x02, 0x0f, 0x6e, 0x78, 0x67, 0xe6, 0x44, 0x01, 0xf6, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, |
124 | 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x12, 0x31, 0x82, | 124 | 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe0, 0x07, 0xe5, 0x4d, |
125 | 0x40, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x26, | 125 | 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x0a, 0xe5, 0x4d, 0xd3, 0x94, 0x01, 0x40, |
126 | 0xe5, 0x4d, 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1d, 0x64, 0x02, 0x1d, 0x2f, 0xe5, 0x35, 0x20, | 126 | 0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3, |
127 | 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1c, 0xa5, 0xf5, 0x83, 0xe0, | 127 | 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x12, 0x32, 0x3f, 0x40, 0x03, |
128 | 0x44, 0x08, 0xf0, 0x80, 0x09, 0x12, 0x1c, 0xb3, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, | 128 | 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x06, 0x20, 0xe0, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x4d, |
129 | 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, | 129 | 0x70, 0x09, 0x30, 0x0a, 0x03, 0x02, 0x1e, 0x14, 0x02, 0x1d, 0xdf, 0xe5, 0x35, 0x20, 0xe1, 0x03, |
130 | 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, | 130 | 0x02, 0x0f, 0x6e, 0x15, 0x4d, 0x30, 0x0a, 0x0b, 0x12, 0x1d, 0x55, 0xf5, 0x83, 0xe0, 0x44, 0x08, |
131 | 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xbb, | 131 | 0xf0, 0x80, 0x09, 0x12, 0x1d, 0x63, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0xe4, 0xff, 0x02, 0x32, |
132 | 0xe0, 0x90, 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, | 132 | 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, |
133 | 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, | 133 | 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03, |
134 | 0x3b, 0x70, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, | 134 | 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x30, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbe, 0xe0, 0x90, |
135 | 0xba, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, | 135 | 0xff, 0xff, 0xf0, 0xe0, 0x60, 0x05, 0x43, 0x35, 0x01, 0x80, 0x03, 0x53, 0x35, 0xfe, 0xe4, 0xff, |
136 | 0x60, 0x03, 0x02, 0x0f, 0x26, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0x30, 0x12, 0x1d, | 136 | 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x70, |
137 | 0x5d, 0x7d, 0x03, 0x12, 0x0f, 0x6d, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, | 137 | 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, |
138 | 0xb3, 0xe0, 0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, | 138 | 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0x24, 0xfe, 0x60, 0x3a, 0x14, 0x60, 0x75, 0x24, 0x02, 0x60, 0x03, |
139 | 0xaf, 0x3c, 0x02, 0x0f, 0xba, 0x12, 0x1c, 0x30, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x0d, 0x12, | 139 | 0x02, 0x0f, 0x6e, 0xed, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1c, 0xe0, 0x12, 0x1e, 0x0d, 0x7d, |
140 | 0x1d, 0x5d, 0x7d, 0x14, 0x12, 0x0f, 0x6d, 0x60, 0x10, 0x02, 0x0f, 0x26, 0x12, 0x1d, 0x5d, 0x7d, | 140 | 0x03, 0x12, 0x0f, 0xb5, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0x72, 0x90, 0xfa, 0xb6, 0xe0, |
141 | 0x04, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x0f, 0x2a, 0x90, 0xfa, 0xb3, 0xe0, | 141 | 0xfd, 0xa3, 0x12, 0x1d, 0x2b, 0x12, 0x0f, 0xd1, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, |
142 | 0xfd, 0xa3, 0x12, 0x1c, 0x7b, 0x12, 0x0f, 0x89, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, | 142 | 0x02, 0x10, 0x02, 0x12, 0x1c, 0xe0, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe4, 0x0d, 0x12, 0x1e, 0x0d, |
143 | 0x02, 0x0f, 0xba, 0x12, 0x1d, 0x5d, 0x7d, 0x05, 0x12, 0x0f, 0xc1, 0x60, 0x03, 0x02, 0x0f, 0x26, | 143 | 0x7d, 0x14, 0x12, 0x0f, 0xb5, 0x60, 0x10, 0x02, 0x0f, 0x6e, 0x12, 0x1e, 0x0d, 0x7d, 0x04, 0x12, |
144 | 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, 0x12, 0x1c, 0x78, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, | 144 | 0x10, 0x09, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x0f, 0x72, 0x90, 0xfa, 0xb6, 0xe0, 0xfd, 0xa3, |
145 | 0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb2, 0xf0, | 145 | 0x12, 0x1d, 0x2b, 0x12, 0x0f, 0xd1, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x02, 0x10, |
146 | 0xe4, 0xf5, 0x4c, 0x90, 0xfa, 0xb2, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1c, | 146 | 0x02, 0x12, 0x1e, 0x0d, 0x7d, 0x05, 0x12, 0x10, 0x09, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x7b, 0x01, |
147 | 0x72, 0x12, 0x0f, 0xcc, 0xff, 0xfd, 0x90, 0xfa, 0xb4, 0xe4, 0x8d, 0xf0, 0x12, 0x1a, 0x6c, 0x90, | 147 | 0x7a, 0xfa, 0x79, 0xb6, 0x12, 0x1d, 0x28, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb7, 0xe4, |
148 | 0xfa, 0xb3, 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x26, 0x05, 0x4c, | 148 | 0x75, 0xf0, 0x03, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xbe, 0xe0, 0x90, 0xfa, 0xb5, 0xf0, 0xe4, 0xf5, |
149 | 0x80, 0xd1, 0x12, 0x1c, 0x72, 0x12, 0x0f, 0xcc, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb3, 0xf0, 0xfd, | 149 | 0x4c, 0x90, 0xfa, 0xb5, 0xe0, 0xff, 0xe5, 0x4c, 0xc3, 0x9f, 0x50, 0x24, 0x12, 0x1d, 0x22, 0x12, |
150 | 0xa3, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0x7a, 0xf9, 0x79, 0x6f, 0x7b, 0x01, 0x8b, 0x36, | 150 | 0x10, 0x14, 0xff, 0xfd, 0x90, 0xfa, 0xb7, 0xe4, 0x8d, 0xf0, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xb6, |
151 | 0x8a, 0x37, 0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1c, 0x78, 0x12, 0x25, | 151 | 0xe0, 0xc3, 0x9f, 0xf0, 0xd3, 0x94, 0x00, 0x50, 0x03, 0x02, 0x0f, 0x6e, 0x05, 0x4c, 0x80, 0xd1, |
152 | 0xd7, 0x8f, 0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0x11, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x12, | 152 | 0x12, 0x1d, 0x22, 0x12, 0x10, 0x14, 0x24, 0xfe, 0xff, 0x90, 0xfa, 0xb6, 0xf0, 0xfd, 0xa3, 0xe4, |
153 | 0x1c, 0x11, 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0x4a, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, | 153 | 0x75, 0xf0, 0x02, 0x12, 0x1b, 0x1c, 0x7a, 0xf9, 0x79, 0x72, 0x7b, 0x01, 0x8b, 0x36, 0x8a, 0x37, |
154 | 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, | 154 | 0x89, 0x38, 0xe9, 0x24, 0x02, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, 0x1d, 0x28, 0x12, 0x26, 0x98, 0x8f, |
155 | 0x3a, 0x02, 0x2c, 0x07, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, | 155 | 0x4c, 0x05, 0x4c, 0x05, 0x4c, 0x12, 0x1c, 0xc1, 0xe5, 0x4c, 0x12, 0x1a, 0xe8, 0x12, 0x1c, 0xc1, |
156 | 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, | 156 | 0x90, 0x00, 0x01, 0x74, 0x03, 0x12, 0x1a, 0xfa, 0xaf, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x3c, |
157 | 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, | 157 | 0xee, 0x95, 0x3b, 0x50, 0x02, 0x80, 0x04, 0xae, 0x3b, 0xaf, 0x3c, 0x8e, 0x39, 0x8f, 0x3a, 0x02, |
158 | 0x12, 0x1c, 0xc9, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, | 158 | 0x2c, 0xd8, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x64, |
159 | 0x02, 0x0f, 0x26, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xa9, 0xe5, | 159 | 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, |
160 | 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, | 160 | 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, |
161 | 0x90, 0xfa, 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, 0xe0, 0x94, 0x01, | 161 | 0x79, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, |
162 | 0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x60, 0x03, | 162 | 0x6e, 0x75, 0x36, 0x00, 0x75, 0x37, 0x00, 0x75, 0x38, 0x32, 0x02, 0x0f, 0xf1, 0xe5, 0x35, 0x30, |
163 | 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, | 163 | 0xe7, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, |
164 | 0xbb, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, | 164 | 0xb9, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xd3, 0x90, 0xfa, 0xbe, 0xe0, 0x94, 0x01, 0x90, 0xfa, |
165 | 0x53, 0x35, 0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x20, 0xe7, 0x03, | 165 | 0xbd, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x60, 0x03, 0x02, 0x0f, |
166 | 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, | 166 | 0x6e, 0xe5, 0x35, 0x20, 0xe0, 0x06, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbe, 0xe0, |
167 | 0xb6, 0xe0, 0x60, 0x03, 0x02, 0x0f, 0x26, 0x90, 0xfa, 0xba, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, | 167 | 0xf5, 0x32, 0xe5, 0x32, 0x70, 0x08, 0x43, 0x35, 0x01, 0x53, 0x35, 0xfd, 0x80, 0x06, 0x53, 0x35, |
168 | 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, 0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, | 168 | 0xfe, 0x43, 0x35, 0x02, 0xe4, 0xff, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x20, 0xe7, 0x03, 0x02, 0x0f, |
169 | 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, 0x7f, 0x01, 0x02, 0x31, 0xb1, 0xe5, 0x35, 0x30, 0xe7, 0x03, | 169 | 0x6e, 0xe5, 0x3c, 0x64, 0x01, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xb9, 0xe0, |
170 | 0x02, 0x0f, 0x26, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xd3, 0x90, 0xfa, 0xbb, | 170 | 0x60, 0x03, 0x02, 0x0f, 0x6e, 0x90, 0xfa, 0xbd, 0xe0, 0x70, 0x02, 0xa3, 0xe0, 0x60, 0x03, 0x02, |
171 | 0xe0, 0x94, 0x00, 0x90, 0xfa, 0xba, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x26, 0x12, 0x1c, | 171 | 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1, |
172 | 0xc9, 0x64, 0x01, 0x60, 0x03, 0x02, 0x0f, 0x26, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x26, | 172 | 0x03, 0x02, 0x0f, 0x6e, 0x7f, 0x01, 0x02, 0x32, 0x6e, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, |
173 | 0xe4, 0xff, 0x02, 0x31, 0xb1, 0x90, 0xff, 0x01, 0x12, 0x1d, 0x74, 0xef, 0x12, 0x1a, 0x38, 0x90, | 173 | 0x6e, 0xe5, 0x3c, 0x45, 0x3b, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xd3, 0x90, 0xfa, 0xbe, 0xe0, 0x94, |
174 | 0xfa, 0xb6, 0x12, 0x1d, 0x74, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0x4a, 0x90, 0x00, 0x02, 0xe4, | 174 | 0x00, 0x90, 0xfa, 0xbd, 0xe0, 0x94, 0x00, 0x40, 0x03, 0x02, 0x0f, 0x6e, 0x12, 0x1d, 0x79, 0x64, |
175 | 0x12, 0x1a, 0x4a, 0x74, 0x03, 0x12, 0x1c, 0x02, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0xa3, 0xe0, 0x85, | 175 | 0x01, 0x60, 0x03, 0x02, 0x0f, 0x6e, 0xe5, 0x35, 0x20, 0xe1, 0x03, 0x02, 0x0f, 0x6e, 0xe4, 0xff, |
176 | 0x38, 0x82, 0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, | 176 | 0x02, 0x32, 0x6e, 0x90, 0xff, 0x01, 0x12, 0x1e, 0x24, 0xef, 0x12, 0x1a, 0xe8, 0x90, 0xfa, 0xb9, |
177 | 0x4c, 0x09, 0x4a, 0x02, 0x09, 0x6c, 0x04, 0x09, 0x8e, 0x05, 0x09, 0xba, 0x06, 0x09, 0xd8, 0x07, | 177 | 0x12, 0x1e, 0x24, 0x90, 0x00, 0x01, 0xef, 0x12, 0x1a, 0xfa, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a, |
178 | 0x09, 0xf6, 0x08, 0x0a, 0x14, 0x09, 0x0a, 0x32, 0x0b, 0x0a, 0xe7, 0x80, 0x0d, 0x6f, 0x81, 0x0d, | 178 | 0xfa, 0x74, 0x03, 0x12, 0x1c, 0xb2, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0xa3, 0xe0, 0x85, 0x38, 0x82, |
179 | 0xa0, 0x82, 0x0b, 0x2e, 0x83, 0x0b, 0x77, 0x84, 0x0b, 0x96, 0x85, 0x0b, 0xdb, 0x86, 0x0c, 0x26, | 179 | 0x85, 0x37, 0x83, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xff, 0x01, 0xe0, 0x12, 0x1b, 0xfc, 0x09, |
180 | 0x87, 0x0c, 0xb7, 0x88, 0x0d, 0x42, 0x89, 0x0a, 0x50, 0x92, 0x0a, 0x50, 0x93, 0x0e, 0x53, 0xc0, | 180 | 0x7b, 0x02, 0x09, 0x9d, 0x04, 0x09, 0xbf, 0x05, 0x09, 0xeb, 0x06, 0x0a, 0x09, 0x07, 0x0a, 0x27, |
181 | 0x0e, 0x7f, 0xc1, 0x0e, 0x90, 0xc2, 0x00, 0x00, 0x0f, 0x15, 0xe5, 0x35, 0x20, 0xe7, 0x05, 0x7f, | 181 | 0x08, 0x0a, 0x45, 0x09, 0x0a, 0x63, 0x0b, 0x0b, 0x18, 0x80, 0x0d, 0xb7, 0x81, 0x0d, 0xe8, 0x82, |
182 | 0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, | 182 | 0x0b, 0x5f, 0x83, 0x0b, 0xa8, 0x84, 0x0b, 0xc7, 0x85, 0x0c, 0x0c, 0x86, 0x0c, 0x57, 0x87, 0x0c, |
183 | 0x7f, 0x07, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, 0x20, 0xe7, | 183 | 0xe8, 0x88, 0x0d, 0x73, 0x89, 0x0a, 0x81, 0x92, 0x0a, 0x81, 0x93, 0x0d, 0xa0, 0xb0, 0x0e, 0x9b, |
184 | 0x05, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, | 184 | 0xc0, 0x0e, 0xc7, 0xc1, 0x0e, 0xd8, 0xc2, 0x00, 0x00, 0x0f, 0x5d, 0xe5, 0x35, 0x20, 0xe7, 0x05, |
185 | 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x16, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0x18, 0xe5, 0x35, | 185 | 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, |
186 | 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1d, 0x92, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b, 0x70, | 186 | 0x00, 0x7f, 0x07, 0x02, 0x11, 0x5e, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0xb4, 0xe5, 0x35, 0x20, |
187 | 0x05, 0x7f, 0x02, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50, 0x02, | 187 | 0xe7, 0x05, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, |
188 | 0x80, 0x03, 0x02, 0x31, 0x6f, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, | 188 | 0xfd, 0x7c, 0x00, 0x7f, 0x0c, 0x02, 0x11, 0x5e, 0xe4, 0xfd, 0x7f, 0x07, 0x02, 0x2f, 0xb4, 0xe5, |
189 | 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x08, | 189 | 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1e, 0x42, 0x50, 0x06, 0xe5, 0x3c, 0x45, 0x3b, |
190 | 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, | 190 | 0x70, 0x05, 0x7f, 0x02, 0x02, 0x31, 0xa9, 0x90, 0xfa, 0xb9, 0xe0, 0x24, 0xfe, 0x24, 0xfd, 0x50, |
191 | 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02, 0x11, | 191 | 0x02, 0x80, 0x03, 0x02, 0x32, 0x2c, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, |
192 | 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, | 192 | 0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, |
193 | 0xc1, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x16, 0x7f, | 193 | 0x08, 0x02, 0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, |
194 | 0x07, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, | 194 | 0x71, 0x12, 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x09, 0x02, |
195 | 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, | 195 | 0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, |
196 | 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x29, 0x12, 0x1c, 0xc1, 0x60, 0x03, 0x04, | 196 | 0x1d, 0x71, 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0a, 0x02, 0x11, 0x5e, |
197 | 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x16, 0x7f, 0x07, 0x02, 0x30, 0xec, | 197 | 0x7f, 0x07, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71, |
198 | 0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1c, 0xc9, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, | 198 | 0x60, 0x03, 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0b, 0x02, 0x11, 0x5e, 0x7f, 0x07, |
199 | 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, | 199 | 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x03, 0x02, 0x0f, 0x71, 0x12, 0x1d, 0x71, 0x60, 0x03, |
200 | 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1b, 0x72, 0x12, | 200 | 0x04, 0x70, 0x09, 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0e, 0x02, 0x11, 0x5e, 0x7f, 0x07, 0x02, 0x31, |
201 | 0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, 0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x05, 0x12, 0x31, 0xbd, | 201 | 0xa9, 0xe5, 0x35, 0x30, 0xe7, 0x56, 0x12, 0x1d, 0x79, 0x70, 0x4a, 0x90, 0xff, 0x02, 0xe0, 0xf5, |
202 | 0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, | 202 | 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, 0x4c, 0xb4, 0x83, 0x05, |
203 | 0x72, 0x02, 0x2c, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0x18, 0x12, 0x1c, 0xc9, 0x60, 0x05, | 203 | 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, 0x4c, 0x12, 0x1c, 0x22, |
204 | 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x1d, 0x92, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x30, 0xec, 0x90, | 204 | 0x12, 0x1e, 0x3b, 0x12, 0x25, 0xfa, 0x12, 0x1d, 0x89, 0x12, 0x1a, 0xbb, 0x60, 0x05, 0x12, 0x32, |
205 | 0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, 0xe5, | 205 | 0x7a, 0x80, 0x06, 0x85, 0x33, 0x39, 0x85, 0x34, 0x3a, 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, |
206 | 0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, 0xf5, | 206 | 0x38, 0x75, 0x02, 0x2c, 0xd8, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0xb4, 0x12, 0x1d, 0x79, 0x60, |
207 | 0x4c, 0x12, 0x1b, 0x72, 0x02, 0x31, 0x6f, 0x12, 0x1d, 0x9c, 0x12, 0x2a, 0x06, 0x12, 0x1c, 0x83, | 207 | 0x05, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x1e, 0x42, 0x40, 0x05, 0x7f, 0x03, 0x02, 0x31, 0xa9, |
208 | 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x78, 0x68, 0x12, 0x1b, | 208 | 0x90, 0xff, 0x02, 0xe0, 0xf5, 0x4c, 0xe5, 0x4c, 0xb4, 0x82, 0x05, 0x75, 0x4c, 0x61, 0x80, 0x12, |
209 | 0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12, 0x1a, | 209 | 0xe5, 0x4c, 0xb4, 0x83, 0x05, 0x75, 0x4c, 0x62, 0x80, 0x08, 0xe5, 0x4c, 0xc4, 0x54, 0xf0, 0x04, |
210 | 0x4a, 0x90, 0xfa, 0xb7, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6, 0x8c, | 210 | 0xf5, 0x4c, 0x12, 0x1c, 0x22, 0x02, 0x32, 0x2c, 0x12, 0x1e, 0x4c, 0x12, 0x2a, 0xc7, 0x12, 0x1d, |
211 | 0x83, 0x12, 0x1c, 0x8b, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, | 211 | 0x33, 0xe0, 0x54, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0xe0, 0x90, 0xfa, 0xba, 0xf0, 0x78, 0x68, 0x12, |
212 | 0xb6, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, | 212 | 0x1b, 0xd8, 0x90, 0x00, 0x02, 0x12, 0x1a, 0xbb, 0x30, 0xe7, 0xf2, 0x90, 0x00, 0x02, 0xe4, 0x12, |
213 | 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbb, 0xe0, 0x42, | 213 | 0x1a, 0xfa, 0x90, 0xfa, 0xba, 0xe0, 0x44, 0x80, 0xff, 0xf0, 0x78, 0x7c, 0xe6, 0xfc, 0x08, 0xe6, |
214 | 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xba, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, 0xe0, | 214 | 0x8c, 0x83, 0x12, 0x1d, 0x3b, 0xef, 0xf0, 0x12, 0x32, 0x84, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x90, |
215 | 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbb, 0xe0, 0x42, 0xb0, | 215 | 0xfa, 0xb9, 0xe0, 0x64, 0x01, 0x70, 0x1f, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, |
216 | 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0xb4, 0x01, | 216 | 0xa3, 0xe0, 0xf5, 0x90, 0x80, 0x2d, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0x90, 0x90, 0xfa, 0xbe, 0xe0, |
217 | 0x0a, 0x12, 0x1c, 0x11, 0xe5, 0x90, 0x12, 0x1a, 0x38, 0x80, 0x08, 0x12, 0x1c, 0x11, 0xe5, 0xb0, | 217 | 0x42, 0x90, 0xd2, 0xaf, 0x80, 0x1d, 0x90, 0xfa, 0xbd, 0xe0, 0xff, 0x7e, 0x00, 0x70, 0x06, 0xa3, |
218 | 0x12, 0x1a, 0x38, 0x02, 0x0f, 0xa9, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0x12, 0x12, 0x1c, 0x41, | 218 | 0xe0, 0xf5, 0xb0, 0x80, 0x0e, 0xc2, 0xaf, 0xef, 0xf4, 0x52, 0xb0, 0x90, 0xfa, 0xbe, 0xe0, 0x42, |
219 | 0x20, 0xe1, 0x33, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, 0xfa, | 219 | 0xb0, 0xd2, 0xaf, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1c, 0xe0, 0x90, 0xfa, 0xb9, 0xe0, 0xb4, |
220 | 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1d, 0xa6, | 220 | 0x01, 0x0a, 0x12, 0x1c, 0xc1, 0xe5, 0x90, 0x12, 0x1a, 0xe8, 0x80, 0x08, 0x12, 0x1c, 0xc1, 0xe5, |
221 | 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0xf0, | 221 | 0xb0, 0x12, 0x1a, 0xe8, 0x02, 0x0f, 0xf1, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x24, 0x13, 0x12, 0x1c, |
222 | 0x80, 0x04, 0x12, 0x1d, 0xad, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x90, 0xfa, 0xb6, 0xe0, 0xff, | 222 | 0xf1, 0x20, 0xe1, 0x33, 0x12, 0x1d, 0x80, 0xef, 0x24, 0xfc, 0x60, 0x18, 0x04, 0x70, 0x28, 0x90, |
223 | 0x24, 0x12, 0x12, 0x1c, 0x41, 0x20, 0xe1, 0x39, 0x12, 0x1c, 0xd0, 0xef, 0x24, 0xfc, 0x60, 0x1b, | 223 | 0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x19, 0x12, 0x1e, |
224 | 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, | 224 | 0x56, 0xf0, 0x80, 0x13, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, |
225 | 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xb7, 0xe0, 0x60, | 225 | 0xf0, 0x80, 0x04, 0x12, 0x1e, 0x5d, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x90, 0xfa, 0xb9, 0xe0, |
226 | 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, | 226 | 0xff, 0x24, 0x13, 0x12, 0x1c, 0xf1, 0x20, 0xe1, 0x39, 0x12, 0x1d, 0x80, 0xef, 0x24, 0xfc, 0x60, |
227 | 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x12, 0x1c, 0xc1, 0x60, 0x4d, 0x04, 0x60, | 227 | 0x1b, 0x04, 0x70, 0x2e, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, |
228 | 0x03, 0x02, 0x0c, 0xb2, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c, 0x3a, | 228 | 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x16, 0x90, 0xfa, 0xba, 0xe0, |
229 | 0x30, 0xe1, 0x6f, 0x12, 0x1d, 0x7c, 0x02, 0x0c, 0xb2, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb, 0x12, | 229 | 0x60, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, |
230 | 0x1c, 0x3d, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1d, 0x7c, 0x80, | 230 | 0xdf, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x12, 0x1d, 0x71, 0x60, 0x4d, 0x04, |
231 | 0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1d, 0x7c, | 231 | 0x60, 0x03, 0x02, 0x0c, 0xe3, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x0f, 0x90, 0xff, 0xa4, 0x12, 0x1c, |
232 | 0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xb7, 0xe0, 0x60, | 232 | 0xea, 0x30, 0xe1, 0x6f, 0x12, 0x1e, 0x2c, 0x02, 0x0c, 0xe3, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfb, |
233 | 0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0x3a, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, | 233 | 0x12, 0x1c, 0xed, 0xfe, 0x30, 0xe1, 0x5c, 0x30, 0xe2, 0x11, 0x30, 0xb4, 0x05, 0x12, 0x1e, 0x2c, |
234 | 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0x3d, 0x30, 0xe1, 0x13, 0x30, | 234 | 0x80, 0x51, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x48, 0x30, 0x95, 0x05, 0x12, 0x1e, |
235 | 0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, | 235 | 0x2c, 0x80, 0x40, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xfd, 0xf0, 0x80, 0x37, 0x90, 0xfa, 0xba, 0xe0, |
236 | 0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, | 236 | 0x60, 0x12, 0x90, 0xff, 0xb4, 0x12, 0x1c, 0xea, 0x30, 0xe1, 0x28, 0x90, 0xff, 0xb4, 0xe0, 0x44, |
237 | 0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0, 0x44, | 237 | 0x02, 0xf0, 0x80, 0x1f, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xfb, 0x12, 0x1c, 0xed, 0x30, 0xe1, 0x13, |
238 | 0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, | 238 | 0x30, 0x93, 0x09, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, |
239 | 0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0, 0x44, | 239 | 0x54, 0xfd, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x90, 0xfa, 0xb9, 0xe0, 0x24, |
240 | 0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, | 240 | 0xfc, 0x60, 0x40, 0x04, 0x70, 0x78, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xa2, 0xe0, |
241 | 0x80, 0x3b, 0x90, 0xfa, 0xb7, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0, 0xa3, | 241 | 0x44, 0x40, 0xf0, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x65, 0xd2, 0x03, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, |
242 | 0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3, 0xef, | 242 | 0x90, 0xff, 0xa3, 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x55, 0x30, 0x03, 0x0e, 0x90, 0xff, 0xa3, 0xe0, |
243 | 0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0, 0xc2, | 243 | 0x44, 0x80, 0xf0, 0xc2, 0x03, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x54, 0xbf, |
244 | 0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, 0x02, | 244 | 0xf0, 0x80, 0x3b, 0x90, 0xfa, 0xba, 0xe0, 0x60, 0x1d, 0x90, 0xff, 0xb2, 0xe0, 0x44, 0x40, 0xf0, |
245 | 0x30, 0xec, 0x12, 0x1c, 0x30, 0x90, 0xfa, 0xb6, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70, 0x16, | 245 | 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x28, 0xd2, 0x04, 0xa3, 0xe0, 0x54, 0xdf, 0xf0, 0x90, 0xff, 0xb3, |
246 | 0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x80, 0x0a, 0x90, 0xff, 0xb6, 0xe0, | 246 | 0xef, 0x54, 0x7f, 0xf0, 0x80, 0x18, 0x30, 0x04, 0x0e, 0x90, 0xff, 0xb3, 0xe0, 0x44, 0x80, 0xf0, |
247 | 0x12, 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0x07, 0xe4, | 247 | 0xc2, 0x04, 0xa3, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x54, 0xbf, 0xf0, 0xe4, 0xff, |
248 | 0xff, 0x12, 0x30, 0xec, 0x12, 0x1d, 0x37, 0x7f, 0x03, 0x12, 0x12, 0x19, 0x90, 0xf9, 0x15, 0xe0, | 248 | 0x02, 0x31, 0xa9, 0x12, 0x1c, 0xe0, 0x90, 0xfa, 0xb9, 0xe0, 0x24, 0xfc, 0x60, 0x0f, 0x04, 0x70, |
249 | 0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80, 0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, | 249 | 0x16, 0x90, 0xff, 0xa6, 0xe0, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x80, 0x0a, 0x90, 0xff, 0xb6, |
250 | 0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30, 0x16, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, | 250 | 0xe0, 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0xd8, |
251 | 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbc, 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, | 251 | 0x90, 0xf9, 0x15, 0x74, 0x01, 0xf0, 0x90, 0xf9, 0x1c, 0x74, 0x19, 0xf0, 0x90, 0xf9, 0x66, 0x74, |
252 | 0xb4, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54, 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, | 252 | 0xff, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0xe4, 0xff, 0x12, 0x31, 0xa9, 0x12, 0x1d, 0xe7, 0x7f, |
253 | 0xb9, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e, 0x40, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, | 253 | 0x03, 0x12, 0x12, 0x61, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe4, 0x08, 0x90, 0xff, 0x93, 0x74, 0x80, |
254 | 0xb9, 0xf0, 0x12, 0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x73, 0x12, 0x1c, 0x4a, 0x90, 0xfa, | 254 | 0xf0, 0x80, 0x10, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0x7f, 0xf0, 0x7f, 0xff, 0x7e, 0x00, 0x12, 0x30, |
255 | 0xbc, 0x12, 0x1d, 0x56, 0x60, 0x27, 0xd3, 0xef, 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, | 255 | 0xd3, 0xc2, 0x90, 0xc2, 0xaf, 0x00, 0x80, 0xfd, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x90, 0xfa, 0xbf, |
256 | 0xfa, 0xb9, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xbd, 0xe0, 0x90, 0xfa, 0xb9, 0xf0, 0x12, | 256 | 0x74, 0x3e, 0xf0, 0xa3, 0xe4, 0xf0, 0x90, 0xfa, 0xb7, 0xf0, 0xa3, 0x74, 0x15, 0xf0, 0xe0, 0x54, |
257 | 0x0f, 0x50, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46, 0x12, 0x1c, 0x4a, 0x80, 0xd1, 0x75, 0x4c, 0x02, | 257 | 0x3f, 0xff, 0xc3, 0x74, 0x40, 0x9f, 0x90, 0xfa, 0xbc, 0xf0, 0xd3, 0x94, 0x00, 0xe4, 0x94, 0x3e, |
258 | 0x90, 0xfa, 0xbc, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, 0x90, 0xfa, 0xb4, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, | 258 | 0x40, 0x08, 0x90, 0xfa, 0xc0, 0xe0, 0x90, 0xfa, 0xbc, 0xf0, 0x12, 0x0f, 0x98, 0xe5, 0x31, 0x45, |
259 | 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90, 0xfa, 0xbd, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, | 259 | 0x30, 0x70, 0x73, 0x12, 0x1c, 0xfa, 0x90, 0xfa, 0xbf, 0x12, 0x1e, 0x06, 0x60, 0x27, 0xd3, 0xef, |
260 | 0x00, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, | 260 | 0x94, 0x40, 0xee, 0x94, 0x00, 0x40, 0x08, 0x90, 0xfa, 0xbc, 0x74, 0x40, 0xf0, 0x80, 0x08, 0x90, |
261 | 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, | 261 | 0xfa, 0xc0, 0xe0, 0x90, 0xfa, 0xbc, 0xf0, 0x12, 0x0f, 0x98, 0xe5, 0x31, 0x45, 0x30, 0x70, 0x46, |
262 | 0x02, 0x30, 0xec, 0x12, 0x1c, 0xd0, 0x30, 0xe7, 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x64, 0xf0, | 262 | 0x12, 0x1c, 0xfa, 0x80, 0xd1, 0x75, 0x4c, 0x02, 0x90, 0xfa, 0xbf, 0xe4, 0xf0, 0xa3, 0x04, 0xf0, |
263 | 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, 0x11, 0x90, 0xfa, 0xb7, 0xe0, 0x54, 0x0f, 0x90, | 263 | 0x90, 0xfa, 0xb7, 0xe4, 0xf0, 0xa3, 0x74, 0x0f, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0x90, |
264 | 0xf9, 0x63, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x30, 0xec, 0x12, | 264 | 0xfa, 0xc0, 0xe0, 0xf5, 0x4a, 0x7d, 0x0f, 0x7c, 0x00, 0x12, 0x29, 0x60, 0x75, 0x30, 0x00, 0x8f, |
265 | 0x1d, 0x9c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x30, 0xec, | 265 | 0x31, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x4c, 0xe4, 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, |
266 | 0x12, 0x1c, 0xd0, 0x54, 0x03, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, | 266 | 0x98, 0xe4, 0xf5, 0x30, 0xf5, 0x31, 0xaf, 0x31, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x30, 0xe7, |
267 | 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, 0x80, 0x23, 0x12, 0x1d, 0xa6, 0x12, 0x0f, 0x78, | 267 | 0x10, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x67, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x15, 0xc2, 0x95, 0x80, |
268 | 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0x78, 0xff, | 268 | 0x11, 0x90, 0xfa, 0xba, 0xe0, 0x54, 0x0f, 0x90, 0xf9, 0x65, 0xf0, 0xd3, 0x94, 0x00, 0x40, 0x02, |
269 | 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, 0x91, 0x12, 0x1d, 0xa6, 0xf0, 0x90, 0xfa, 0xb7, | 269 | 0xc2, 0x94, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1e, 0x4c, 0xbf, 0x01, 0x04, 0xd2, 0x93, 0x80, |
270 | 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, | 270 | 0x02, 0xc2, 0x93, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0x12, 0x1d, 0x80, 0x54, 0x03, 0x14, 0x60, 0x0a, |
271 | 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, 0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1d, 0xad, | 271 | 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x91, 0x80, 0x27, 0xc2, 0x91, |
272 | 0x12, 0x0f, 0x98, 0x60, 0x04, 0xd2, 0x92, 0x80, 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, | 272 | 0x80, 0x23, 0x12, 0x1e, 0x56, 0x12, 0x0f, 0xc0, 0x60, 0x04, 0xd2, 0x91, 0x80, 0x17, 0x90, 0xff, |
273 | 0x0f, 0x98, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, 0x80, 0x02, 0xd2, 0x92, 0x12, 0x1d, 0xad, 0xf0, | 273 | 0xa4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0xc0, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x91, 0x80, 0x02, 0xd2, |
274 | 0xe4, 0xff, 0x02, 0x30, 0xec, 0xe5, 0x35, 0x30, 0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, | 274 | 0x91, 0x12, 0x1e, 0x56, 0xf0, 0x90, 0xfa, 0xba, 0xe0, 0x54, 0x0c, 0xff, 0x13, 0x13, 0x54, 0x3f, |
275 | 0x18, 0x7f, 0x05, 0x02, 0x30, 0xec, 0x12, 0x31, 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb3, | 275 | 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14, 0x60, 0x08, 0x24, 0x03, 0x70, 0x2b, 0xd2, 0x92, 0x80, |
276 | 0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, | 276 | 0x27, 0xc2, 0x92, 0x80, 0x23, 0x12, 0x1e, 0x5d, 0x12, 0x0f, 0xe0, 0x60, 0x04, 0xd2, 0x92, 0x80, |
277 | 0xfa, 0xb4, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, | 277 | 0x17, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x10, 0x12, 0x0f, 0xe0, 0xff, 0xbf, 0xa0, 0x04, 0xc2, 0x92, |
278 | 0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa, 0xb4, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, | 278 | 0x80, 0x02, 0xd2, 0x92, 0x12, 0x1e, 0x5d, 0xf0, 0xe4, 0xff, 0x02, 0x31, 0xa9, 0xe5, 0x35, 0x30, |
279 | 0xb9, 0xe0, 0xf5, 0x4a, 0x12, 0x28, 0x9f, 0x75, 0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x22, 0xa0, | 279 | 0xe7, 0x07, 0xe4, 0xfd, 0x7f, 0x05, 0x02, 0x2f, 0xb4, 0x7f, 0x05, 0x02, 0x31, 0xa9, 0x12, 0x32, |
280 | 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, | 280 | 0x7a, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb6, 0x90, 0xfa, 0xb7, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, |
281 | 0xa6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x12, 0x25, 0xd7, 0x8f, 0x4c, 0x7e, 0x00, | 281 | 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb7, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1b, |
282 | 0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22, 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x19, 0x90, 0xff, | 282 | 0x1c, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xaa, 0x4e, 0xa9, 0x4f, 0x7b, 0xff, 0x90, 0xfa, |
283 | 0xb6, 0xe0, 0x90, 0xfa, 0xb8, 0xf0, 0x54, 0xa0, 0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, | 283 | 0xb7, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xbc, 0xe0, 0xf5, 0x4a, 0x12, 0x29, 0x60, 0x75, |
284 | 0x2c, 0x07, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x02, 0x31, 0x82, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, | 284 | 0x30, 0x00, 0x8f, 0x31, 0x22, 0x12, 0x23, 0x61, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, |
285 | 0x07, 0x12, 0x22, 0xa0, 0x7e, 0x00, 0x8e, 0x30, 0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x25, | 285 | 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x61, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xbb, 0xf0, 0x54, 0xa0, |
286 | 0xd7, 0x90, 0xfa, 0xb1, 0xe0, 0x22, 0xef, 0x90, 0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, | 286 | 0x22, 0x12, 0x26, 0x98, 0x8f, 0x4c, 0x7e, 0x00, 0xc3, 0xef, 0x95, 0x3c, 0xee, 0x95, 0x3b, 0x22, |
287 | 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, 0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, | 287 | 0xf0, 0x7f, 0x01, 0x12, 0x12, 0x61, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xbb, 0xf0, 0x54, 0xa0, |
288 | 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, 0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, | 288 | 0x22, 0x75, 0x39, 0x00, 0x75, 0x3a, 0x01, 0x02, 0x2c, 0xd8, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x02, |
289 | 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, | 289 | 0x32, 0x3f, 0x8e, 0x39, 0x8f, 0x3a, 0x02, 0x2c, 0xd8, 0x12, 0x23, 0x61, 0x7e, 0x00, 0x8e, 0x30, |
290 | 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, 0xff, 0x12, 0x10, 0x78, 0x7f, 0x00, 0x7e, 0x00, | 290 | 0x8f, 0x31, 0xef, 0x22, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xb4, 0xe0, 0x22, 0xef, 0x90, |
291 | 0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, | 291 | 0xf8, 0x04, 0xf0, 0x22, 0xc0, 0xa8, 0xc2, 0xaf, 0xee, 0x60, 0x0a, 0xc0, 0x05, 0x7d, 0x7f, 0xdd, |
292 | 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, | 292 | 0xfe, 0xde, 0xfa, 0xd0, 0x05, 0xef, 0xc3, 0x94, 0x15, 0x50, 0x03, 0xd0, 0xa8, 0x22, 0x13, 0x70, |
293 | 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, | 293 | 0x03, 0xd0, 0xa8, 0x22, 0xff, 0xd5, 0x07, 0xfd, 0xd0, 0xa8, 0x22, 0xc0, 0x00, 0xc0, 0x01, 0xc0, |
294 | 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, | 294 | 0x02, 0xc0, 0x04, 0xc0, 0x05, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x86, 0x05, 0x53, 0x05, 0x7f, 0x7c, |
295 | 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x12, 0x11, 0x0f, 0xd0, 0x05, 0xd0, | 295 | 0xff, 0x12, 0x10, 0xc0, 0x7f, 0x00, 0x7e, 0x00, 0xe5, 0x43, 0x60, 0x46, 0xfc, 0x90, 0xf9, 0x1d, |
296 | 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, | 296 | 0xe0, 0x54, 0x7f, 0x6d, 0x70, 0x0f, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, |
297 | 0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0x66, | 297 | 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xdc, 0xe6, 0x80, 0x26, 0xdc, 0x06, 0xd0, 0x82, |
298 | 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, | 298 | 0xd0, 0x83, 0x80, 0x1e, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, |
299 | 0x78, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, | 299 | 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, |
300 | 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43, 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, | 300 | 0x80, 0xda, 0x12, 0x11, 0x57, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, |
301 | 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, 0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, | 301 | 0x85, 0xa8, 0x44, 0x75, 0xa8, 0x88, 0xec, 0x70, 0x02, 0x7c, 0x3f, 0x8c, 0x3d, 0x22, 0xe5, 0x3e, |
302 | 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, | 302 | 0x24, 0x08, 0xf8, 0x76, 0x00, 0x12, 0x11, 0xae, 0x80, 0xfb, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, |
303 | 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, 0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, | 303 | 0xc0, 0x04, 0xc0, 0x06, 0x7c, 0xff, 0x12, 0x10, 0xc0, 0xe5, 0x43, 0x60, 0x42, 0xfe, 0x90, 0xf9, |
304 | 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, 0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, | 304 | 0x1d, 0xe0, 0x54, 0x7f, 0x6f, 0x70, 0x0b, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x15, 0x43, |
305 | 0xee, 0x12, 0x11, 0x0f, 0xd0, 0x06, 0xd0, 0x04, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, | 305 | 0x80, 0x07, 0xa3, 0xa3, 0xa3, 0xde, 0xea, 0x80, 0x26, 0xde, 0x06, 0xd0, 0x82, 0xd0, 0x83, 0x80, |
306 | 0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, | 306 | 0xd8, 0xe0, 0xf8, 0xa3, 0xe0, 0xf9, 0xa3, 0xe0, 0xfa, 0xd0, 0x82, 0xd0, 0x83, 0xe8, 0xf0, 0xa3, |
307 | 0xe8, 0x50, 0x05, 0x12, 0x11, 0x66, 0x80, 0xf4, 0xef, 0x60, 0x31, 0x90, 0x30, 0x54, 0xe4, 0x93, | 307 | 0xe9, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xa3, 0xa3, 0x80, 0xda, 0x78, |
308 | 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, 0x12, 0x10, 0x78, 0xd0, 0x04, 0x43, 0x07, 0x80, | 308 | 0x08, 0x08, 0x79, 0x18, 0x09, 0x7c, 0x01, 0xe6, 0x54, 0x7f, 0x6f, 0x70, 0x06, 0x76, 0x00, 0x77, |
309 | 0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, | 309 | 0x00, 0x80, 0x06, 0x08, 0x09, 0x0c, 0xbc, 0x08, 0xee, 0x12, 0x11, 0x57, 0xd0, 0x06, 0xd0, 0x04, |
310 | 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, 0x43, 0x12, 0x11, 0x0f, 0xd0, 0x83, 0xd0, 0x82, | 310 | 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0x22, 0x75, 0x3d, 0x00, 0x85, 0x44, 0xa8, 0x22, 0xc0, 0xf0, |
311 | 0xd0, 0xf0, 0x22, 0x02, 0x11, 0x94, 0xc0, 0x04, 0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, | 311 | 0xc0, 0x82, 0xc0, 0x83, 0xc3, 0xe5, 0x43, 0x24, 0xe8, 0x50, 0x05, 0x12, 0x11, 0xae, 0x80, 0xf4, |
312 | 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, 0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, | 312 | 0xef, 0x60, 0x31, 0x90, 0x31, 0x11, 0xe4, 0x93, 0xc3, 0x9f, 0x40, 0x2f, 0xc0, 0x04, 0x7c, 0xff, |
313 | 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, 0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, | 313 | 0x12, 0x10, 0xc0, 0xd0, 0x04, 0x43, 0x07, 0x80, 0xe5, 0x43, 0x75, 0xf0, 0x03, 0xa4, 0x24, 0x1d, |
314 | 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, 0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, | 314 | 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xef, 0xf0, 0xec, 0xa3, 0xf0, 0xed, 0xa3, 0xf0, 0x05, |
315 | 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, | 315 | 0x43, 0x12, 0x11, 0x57, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x02, 0x11, 0xdc, 0xc0, 0x04, |
316 | 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, | 316 | 0x7c, 0x20, 0xd2, 0x8c, 0xd2, 0x8d, 0xd5, 0x04, 0xfd, 0xd0, 0x04, 0x22, 0x75, 0xa8, 0x00, 0x75, |
317 | 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0xd2, 0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, | 317 | 0x88, 0x00, 0x75, 0xb8, 0x00, 0x75, 0xf0, 0x00, 0x75, 0xd0, 0x00, 0xe4, 0xf8, 0x90, 0xf8, 0x04, |
318 | 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x0f, 0xdc, | 318 | 0xf0, 0x90, 0x00, 0x00, 0xf6, 0x08, 0xb8, 0x00, 0xfb, 0x02, 0x00, 0x00, 0xc2, 0xaf, 0xe4, 0x90, |
319 | 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, | 319 | 0xff, 0x48, 0xf0, 0x90, 0xff, 0x50, 0xf0, 0x90, 0xff, 0x08, 0xf0, 0x90, 0xff, 0x10, 0xf0, 0x90, |
320 | 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, | 320 | 0xff, 0x80, 0xf0, 0xa3, 0xa3, 0xf0, 0xd2, 0xb1, 0xc2, 0xb0, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, |
321 | 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, 0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, | 321 | 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0xd2, |
322 | 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f, 0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, | 322 | 0xb0, 0xd2, 0xb1, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, |
323 | 0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8, 0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, | 323 | 0x24, 0x7e, 0xff, 0x7f, 0xff, 0x12, 0x10, 0x24, 0x80, 0xcc, 0xc3, 0xee, 0x94, 0x02, 0x50, 0x04, |
324 | 0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7, 0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0x66, 0x80, | 324 | 0x7e, 0x03, 0x7f, 0xe8, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, |
325 | 0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, | 325 | 0x42, 0x8e, 0x41, 0x22, 0xc3, 0xef, 0x94, 0xbc, 0xee, 0x94, 0x02, 0x50, 0x04, 0x7e, 0x07, 0x7f, |
326 | 0x12, 0x11, 0x66, 0x80, 0xee, 0xd0, 0x00, 0x22, 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, | 326 | 0xd0, 0xef, 0xf4, 0xff, 0xee, 0xf4, 0xfe, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0x8f, 0x40, 0x8e, 0x3f, |
327 | 0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, 0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, | 327 | 0x22, 0xef, 0x70, 0x01, 0x22, 0xc0, 0x00, 0xc0, 0xa8, 0xc2, 0xaf, 0xe5, 0x3e, 0x24, 0x18, 0xf8, |
328 | 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, | 328 | 0xa6, 0x07, 0xe5, 0x3e, 0x24, 0x08, 0xf8, 0xc6, 0x54, 0x7f, 0xf6, 0xd0, 0xa8, 0xe6, 0x30, 0xe7, |
329 | 0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, 0x75, 0xf0, 0x02, 0xa4, 0x24, 0x36, 0xf5, 0x82, | 329 | 0x03, 0xd0, 0x00, 0x22, 0x12, 0x11, 0xae, 0x80, 0xf4, 0xc0, 0x00, 0x7f, 0x01, 0xef, 0x24, 0x08, |
330 | 0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, | 330 | 0xf8, 0xe6, 0x60, 0x09, 0x0f, 0xbf, 0x08, 0xf5, 0x12, 0x11, 0xae, 0x80, 0xee, 0xd0, 0x00, 0x22, |
331 | 0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, | 331 | 0xc0, 0xf0, 0xc0, 0x82, 0xc0, 0x83, 0xc0, 0x00, 0xc0, 0x06, 0xc0, 0x04, 0xed, 0x24, 0x10, 0xf8, |
332 | 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, 0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, | 332 | 0x76, 0x9a, 0xed, 0x75, 0xf0, 0x21, 0xa4, 0x24, 0x05, 0xf5, 0x82, 0xe4, 0x34, 0xf8, 0xf5, 0x83, |
333 | 0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, | 333 | 0xc0, 0x82, 0xc0, 0x83, 0xa3, 0xa3, 0xe4, 0x78, 0x0d, 0xf0, 0xa3, 0xd8, 0xfc, 0xef, 0x54, 0x7f, |
334 | 0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x30, 0x54, 0xe4, 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, | 334 | 0x75, 0xf0, 0x02, 0xa4, 0x24, 0xf3, 0xf5, 0x82, 0xe5, 0xf0, 0x34, 0x30, 0xf5, 0x83, 0xe4, 0x93, |
335 | 0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, | 335 | 0xfe, 0x74, 0x01, 0x93, 0xfc, 0xd0, 0x83, 0xd0, 0x82, 0xec, 0xf0, 0xa3, 0xee, 0xf0, 0xed, 0x24, |
336 | 0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, 0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, | 336 | 0x08, 0xf8, 0xef, 0x44, 0x80, 0xf6, 0xd0, 0x04, 0xd0, 0x06, 0xd0, 0x00, 0xd0, 0x83, 0xd0, 0x82, |
337 | 0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1b, 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, | 337 | 0xd0, 0xf0, 0x22, 0x75, 0x3e, 0x00, 0x75, 0x43, 0x00, 0x7a, 0x08, 0x79, 0x18, 0x78, 0x08, 0x76, |
338 | 0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, | 338 | 0x00, 0x77, 0x00, 0x08, 0x09, 0xda, 0xf8, 0x90, 0xf8, 0x04, 0xe0, 0xfc, 0x90, 0x31, 0x11, 0xe4, |
339 | 0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, 0x07, 0x12, 0x12, 0x41, 0xad, 0x07, 0xaf, 0x02, | 339 | 0x93, 0xc3, 0x9c, 0x50, 0x05, 0xe4, 0x90, 0xf8, 0x04, 0xf0, 0x78, 0x08, 0x74, 0x80, 0x44, 0x7f, |
340 | 0x12, 0x12, 0x58, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, 0xdf, 0xce, 0x12, 0x11, 0x66, 0x80, 0xc1, 0x8f, | 340 | 0xf6, 0x74, 0x01, 0x44, 0x10, 0xf5, 0x89, 0x75, 0xb8, 0x00, 0xd2, 0xab, 0xd2, 0xa9, 0x22, 0x75, |
341 | 0x24, 0x12, 0x2a, 0x06, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, | 341 | 0x81, 0x8b, 0xd2, 0x8e, 0xd2, 0x8c, 0xd2, 0xaf, 0xe5, 0x43, 0x60, 0x36, 0xff, 0x90, 0xf9, 0x1d, |
342 | 0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xed, 0xf0, | 342 | 0xe0, 0x54, 0x80, 0x60, 0x28, 0x78, 0x08, 0x79, 0x08, 0xe0, 0x54, 0x7f, 0xfa, 0x7b, 0x00, 0xe6, |
343 | 0x12, 0x22, 0x56, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x12, 0x22, 0x99, 0x24, 0x09, 0x12, | 343 | 0x54, 0x7f, 0xb5, 0x02, 0x02, 0x7b, 0xff, 0x08, 0xd9, 0xf5, 0xeb, 0x70, 0x10, 0xea, 0xf0, 0xc0, |
344 | 0x21, 0xf3, 0xef, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0x09, 0xc0, | 344 | 0x07, 0x12, 0x12, 0x89, 0xad, 0x07, 0xaf, 0x02, 0x12, 0x12, 0xa0, 0xd0, 0x07, 0xa3, 0xa3, 0xa3, |
345 | 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25, 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, | 345 | 0xdf, 0xce, 0x12, 0x11, 0xae, 0x80, 0xc1, 0x8f, 0x24, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xb5, 0xa3, |
346 | 0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x78, 0x80, 0x12, 0x22, 0x09, | 346 | 0xa3, 0xe0, 0xa3, 0x30, 0xe7, 0x28, 0x78, 0x7e, 0x12, 0x22, 0x99, 0xe0, 0x44, 0x01, 0xf0, 0x12, |
347 | 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12, 0x22, 0x8a, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x21, | 347 | 0x22, 0xfa, 0x12, 0x22, 0x9d, 0xe0, 0x20, 0xe0, 0xf6, 0x12, 0x23, 0x50, 0x74, 0x02, 0xf0, 0x12, |
348 | 0xf3, 0xef, 0xf0, 0xed, 0x12, 0x22, 0x99, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xed, 0xf0, 0x12, 0x21, | 348 | 0x22, 0xda, 0xe0, 0xa3, 0x30, 0xe5, 0x07, 0x12, 0x23, 0x50, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x80, |
349 | 0xfb, 0xe0, 0xff, 0x30, 0xe7, 0x19, 0x12, 0x22, 0x6e, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x09, 0x12, | 349 | 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x08, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0x12, 0x23, |
350 | 0x21, 0xfb, 0xef, 0x44, 0x02, 0xf0, 0x80, 0x07, 0x12, 0x21, 0xfb, 0xef, 0x54, 0xfd, 0xf0, 0x78, | 350 | 0x39, 0x8a, 0x83, 0x24, 0x0a, 0x12, 0x22, 0xa1, 0xed, 0xf0, 0x12, 0x23, 0x06, 0x24, 0x07, 0x12, |
351 | 0x7e, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, | 351 | 0x22, 0xa1, 0xe0, 0xff, 0x12, 0x23, 0x5a, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0x90, 0xf9, |
352 | 0xfd, 0x12, 0x22, 0x43, 0xa3, 0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, | 352 | 0x16, 0xe0, 0x30, 0xe4, 0x20, 0x08, 0x12, 0x22, 0xb7, 0xc0, 0x83, 0xc0, 0x82, 0xa3, 0xe0, 0x25, |
353 | 0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x31, 0x94, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x78, 0x80, | 353 | 0xe0, 0xff, 0x05, 0x82, 0xd5, 0x82, 0x02, 0x15, 0x83, 0x15, 0x82, 0xe0, 0x33, 0xd0, 0x82, 0xd0, |
354 | 0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x06, 0x12, 0x21, 0xf3, 0xe0, 0x60, 0x03, 0x43, 0x07, | 354 | 0x83, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x22, 0xb5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xec, 0xff, 0x12, |
355 | 0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x22, 0x7a, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x42, | 355 | 0x23, 0x39, 0x8a, 0x83, 0x24, 0x08, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0xed, 0x12, 0x23, 0x5a, 0x24, |
356 | 0x07, 0x43, 0x07, 0x80, 0x12, 0x22, 0x8a, 0xf5, 0x82, 0x8a, 0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, | 356 | 0x07, 0x12, 0x22, 0xa1, 0xed, 0xf0, 0x12, 0x22, 0xa9, 0xe0, 0x30, 0xe6, 0x0a, 0x12, 0x23, 0x41, |
357 | 0x22, 0x99, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0xff, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, | 357 | 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe4, 0xf0, 0x12, 0x22, 0xa9, 0xe0, 0xff, 0x30, 0xe7, 0x1b, 0x12, |
358 | 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, 0x80, 0x03, 0x43, 0x07, 0x20, 0xec, | 358 | 0x23, 0x1e, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x60, 0x09, 0x12, 0x22, 0xa9, 0xef, 0x44, 0x02, |
359 | 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, 0x10, 0x12, 0x21, 0xfb, 0xe0, 0xfe, | 359 | 0xf0, 0x80, 0x07, 0x12, 0x22, 0xa9, 0xef, 0x54, 0xfd, 0xf0, 0x78, 0x7e, 0x12, 0x22, 0xb7, 0xa3, |
360 | 0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, 0x69, 0x78, 0x80, 0x12, 0x22, 0x6f, | 360 | 0xa3, 0xe0, 0xff, 0x53, 0x07, 0xc7, 0x08, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x12, 0x22, 0xe0, 0xa3, |
361 | 0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x14, 0xa6, 0x00, 0x14, 0xda, 0x01, 0x14, 0xdf, 0x03, | 361 | 0xe0, 0x30, 0xe3, 0x12, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x05, 0x12, 0x22, 0xa1, 0xe0, |
362 | 0x14, 0xda, 0x05, 0x14, 0xdf, 0x07, 0x14, 0xda, 0x09, 0x14, 0xdf, 0x0b, 0x14, 0xda, 0x0d, 0x14, | 362 | 0x90, 0x32, 0x51, 0x93, 0x42, 0x07, 0x53, 0x07, 0xfb, 0x12, 0x23, 0x1e, 0x24, 0x06, 0x12, 0x22, |
363 | 0xdf, 0x0f, 0x00, 0x00, 0x14, 0xe7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x21, 0x90, 0xf9, 0x15, 0xe0, | 363 | 0xa1, 0xe0, 0x60, 0x03, 0x43, 0x07, 0x04, 0x53, 0x07, 0xfc, 0x78, 0x80, 0x12, 0x23, 0x29, 0x24, |
364 | 0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80, 0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, | 364 | 0x04, 0x12, 0x22, 0xa1, 0xe0, 0x42, 0x07, 0x43, 0x07, 0x80, 0x12, 0x23, 0x39, 0xf5, 0x82, 0x8a, |
365 | 0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, | 365 | 0x83, 0xa3, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x5a, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0xff, 0x8d, |
366 | 0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, | 366 | 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe1, 0x05, 0x53, 0x07, 0xdf, |
367 | 0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x22, 0x78, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xef, | 367 | 0x80, 0x03, 0x43, 0x07, 0x20, 0xec, 0x30, 0xe4, 0x05, 0x53, 0x07, 0xef, 0x80, 0x03, 0x43, 0x07, |
368 | 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, 0x12, 0x21, 0xfb, 0xe0, 0xfe, 0x54, | 368 | 0x10, 0x12, 0x22, 0xa9, 0xe0, 0xfe, 0x54, 0x03, 0x60, 0x73, 0x53, 0x07, 0xdf, 0xee, 0x30, 0xe1, |
369 | 0x03, 0x70, 0x03, 0x02, 0x15, 0xd7, 0xee, 0x20, 0xe1, 0x03, 0x02, 0x15, 0xd4, 0x12, 0x22, 0x6e, | 369 | 0x69, 0x12, 0x23, 0x1e, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x12, 0x1b, 0xfc, 0x15, 0x2c, 0x00, |
370 | 0x12, 0x21, 0xf3, 0xe0, 0x12, 0x1b, 0x4c, 0x15, 0x36, 0x00, 0x15, 0x6c, 0x01, 0x15, 0x6c, 0x03, | 370 | 0x15, 0x60, 0x01, 0x15, 0x65, 0x03, 0x15, 0x60, 0x05, 0x15, 0x65, 0x07, 0x15, 0x60, 0x09, 0x15, |
371 | 0x15, 0xa0, 0x05, 0x15, 0xa0, 0x07, 0x15, 0x86, 0x09, 0x15, 0x86, 0x0b, 0x15, 0xba, 0x0d, 0x15, | 371 | 0x65, 0x0b, 0x15, 0x60, 0x0d, 0x15, 0x65, 0x0f, 0x00, 0x00, 0x15, 0x6d, 0xe5, 0x24, 0x64, 0x03, |
372 | 0xba, 0x0f, 0x00, 0x00, 0x15, 0xd7, 0xe5, 0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x15, 0xe0, | 372 | 0x70, 0x21, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe2, 0x0d, 0x30, 0xb4, 0x05, 0x43, 0x07, 0x02, 0x80, |
373 | 0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53, 0x07, 0x7f, 0x02, 0x15, 0xd7, 0x43, 0x07, 0x80, 0x02, | 373 | 0x2c, 0x53, 0x07, 0xfd, 0x80, 0x27, 0x30, 0x95, 0x05, 0x43, 0x07, 0x02, 0x80, 0x1f, 0x53, 0x07, |
374 | 0x15, 0xd7, 0x30, 0x94, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, | 374 | 0xfd, 0x80, 0x1a, 0x30, 0x93, 0x05, 0x43, 0x07, 0x02, 0x80, 0x12, 0x53, 0x07, 0xfd, 0x80, 0x0d, |
375 | 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70, 0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, | 375 | 0x43, 0x07, 0x02, 0x80, 0x08, 0x53, 0x07, 0xfd, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x12, 0x23, 0x27, |
376 | 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, | 376 | 0x24, 0x04, 0x12, 0x22, 0xa1, 0xef, 0xf0, 0x8d, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xff, |
377 | 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, | 377 | 0x12, 0x22, 0xa9, 0xe0, 0xfe, 0x54, 0x03, 0x70, 0x03, 0x02, 0x16, 0x60, 0xee, 0x20, 0xe1, 0x03, |
378 | 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, | 378 | 0x02, 0x16, 0x5d, 0x08, 0x12, 0x23, 0x20, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0x12, 0x1b, 0xfc, |
379 | 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, | 379 | 0x15, 0xbf, 0x00, 0x15, 0xf5, 0x01, 0x15, 0xf5, 0x03, 0x16, 0x29, 0x05, 0x16, 0x29, 0x07, 0x16, |
380 | 0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, | 380 | 0x0f, 0x09, 0x16, 0x0f, 0x0b, 0x16, 0x43, 0x0d, 0x16, 0x43, 0x0f, 0x00, 0x00, 0x16, 0x60, 0xe5, |
381 | 0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, | 381 | 0x24, 0x64, 0x03, 0x70, 0x23, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe2, 0x0f, 0x30, 0xb1, 0x06, 0x53, |
382 | 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, 0x78, 0x80, 0x12, 0x22, 0x3f, 0xe0, 0xfc, 0xa3, 0xe0, | 382 | 0x07, 0x7f, 0x02, 0x16, 0x60, 0x43, 0x07, 0x80, 0x02, 0x16, 0x60, 0x30, 0x94, 0x05, 0x53, 0x07, |
383 | 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, 0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, | 383 | 0x7f, 0x80, 0x7d, 0x43, 0x07, 0x80, 0x80, 0x78, 0x30, 0x92, 0x05, 0x53, 0x07, 0x7f, 0x80, 0x70, |
384 | 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, | 384 | 0x43, 0x07, 0x80, 0x80, 0x6b, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xef, |
385 | 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, 0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, | 385 | 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x51, 0xe5, |
386 | 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, 0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, | 386 | 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, |
387 | 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, 0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, | 387 | 0xe0, 0x44, 0x20, 0xf0, 0x53, 0x07, 0x7f, 0x80, 0x37, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, |
388 | 0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0x3f, 0xa3, 0xef, 0xf0, 0x12, 0x31, 0xc7, 0x7f, | 388 | 0x9e, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xdf, 0xf0, 0x43, 0x07, |
389 | 0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, | 389 | 0x80, 0x80, 0x1d, 0xe5, 0x24, 0xb4, 0x03, 0x09, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x10, 0xf0, 0x80, |
390 | 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, | 390 | 0x07, 0x90, 0xff, 0x9e, 0xe0, 0x44, 0x20, 0xf0, 0x43, 0x07, 0x80, 0x80, 0x03, 0x53, 0x07, 0x7f, |
391 | 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1a, 0x6c, 0x12, 0x18, 0xe2, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, | 391 | 0x12, 0x22, 0xda, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x30, 0xe0, 0x05, 0x43, 0x07, 0x20, 0x80, 0x03, |
392 | 0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa, 0xcc, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, | 392 | 0x53, 0x07, 0xdf, 0xec, 0x30, 0xe3, 0x05, 0x43, 0x07, 0x40, 0x80, 0x03, 0x53, 0x07, 0xbf, 0xec, |
393 | 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, | 393 | 0x30, 0xe0, 0x05, 0x43, 0x07, 0x10, 0x80, 0x03, 0x53, 0x07, 0xef, 0xed, 0x30, 0xe4, 0x05, 0x43, |
394 | 0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0xe5, | 394 | 0x07, 0x08, 0x80, 0x03, 0x53, 0x07, 0xf7, 0xed, 0x30, 0xe5, 0x05, 0x43, 0x07, 0x04, 0x80, 0x03, |
395 | 0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23, 0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, | 395 | 0x53, 0x07, 0xfb, 0xed, 0x30, 0xe6, 0x05, 0x43, 0x07, 0x01, 0x80, 0x03, 0x53, 0x07, 0xfe, 0xed, |
396 | 0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12, 0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, | 396 | 0x30, 0xe7, 0x05, 0x43, 0x07, 0x02, 0x80, 0x03, 0x53, 0x07, 0xfd, 0x78, 0x7e, 0x12, 0x22, 0xdc, |
397 | 0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02, 0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, | 397 | 0xa3, 0xef, 0xf0, 0x12, 0x32, 0x84, 0x7f, 0x00, 0x22, 0x90, 0xff, 0xfa, 0x74, 0x08, 0xf0, 0xa3, |
398 | 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x02, 0xf0, 0xa3, | 398 | 0x74, 0x16, 0xf0, 0x90, 0xff, 0xf9, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcf, 0xe4, |
399 | 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4, 0x41, 0x12, 0x90, 0xf9, 0x15, 0xe0, 0x44, | 399 | 0xfd, 0x12, 0x23, 0x61, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x03, 0x12, 0x1b, 0x1c, 0x12, 0x19, |
400 | 0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1, 0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x15, | 400 | 0x92, 0xe5, 0x23, 0x30, 0xe7, 0x02, 0xd2, 0x02, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x24, 0x90, 0xfa, |
401 | 0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, | 401 | 0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xcf, |
402 | 0x05, 0xe5, 0x23, 0xb4, 0x43, 0x0c, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x80, 0xf0, 0xa3, 0xe0, 0x44, | 402 | 0xe4, 0xf0, 0xa3, 0x74, 0x0b, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x75, 0x2d, 0x00, 0xf5, |
403 | 0x80, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x18, 0xe2, 0x90, 0xff, | 403 | 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0xe5, 0x23, 0x24, 0x80, 0x90, 0xff, 0xf8, 0xf0, 0xe5, 0x23, |
404 | 0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1d, 0x84, | 404 | 0x64, 0x07, 0x60, 0x1e, 0xe5, 0x23, 0x64, 0x06, 0x60, 0x18, 0xe5, 0x23, 0x64, 0x14, 0x60, 0x12, |
405 | 0x12, 0x1c, 0x30, 0x12, 0x1d, 0x8b, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x43, 0x90, 0xf9, 0x6c, 0x12, | 405 | 0xe5, 0x23, 0x64, 0x41, 0x60, 0x0c, 0xe5, 0x23, 0x64, 0x1a, 0x70, 0x46, 0xe5, 0x24, 0x64, 0x02, |
406 | 0x1b, 0x43, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, | 406 | 0x70, 0x40, 0xe5, 0x23, 0xb4, 0x07, 0x16, 0xd2, 0x94, 0xd2, 0x95, 0xd2, 0x92, 0xd2, 0x93, 0x90, |
407 | 0xf9, 0x16, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1e, 0xe5, 0x23, 0xb4, | ||
408 | 0x41, 0x12, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x06, 0xf0, 0xa3, 0xe0, 0x44, 0x06, 0xf0, 0xd2, 0xb1, | ||
409 | 0xd2, 0xb4, 0x80, 0x07, 0x90, 0xf9, 0x16, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x44, | ||
410 | 0x01, 0xf0, 0xe5, 0x23, 0x64, 0x42, 0x60, 0x0c, 0xe5, 0x23, 0x64, 0x43, 0x60, 0x06, 0xe5, 0x23, | ||
411 | 0x64, 0x44, 0x70, 0x2e, 0x90, 0xf9, 0x16, 0xe0, 0xff, 0xe5, 0x23, 0xb4, 0x44, 0x04, 0x7e, 0x40, | ||
412 | 0x80, 0x02, 0x7e, 0x00, 0xee, 0x24, 0x80, 0x4f, 0x90, 0xf9, 0x16, 0xf0, 0xa3, 0xe0, 0xff, 0xe5, | ||
413 | 0x23, 0xb4, 0x44, 0x04, 0x7e, 0x40, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x24, 0x80, 0x4f, 0x90, 0xf9, | ||
414 | 0x17, 0xf0, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x0d, 0xf0, 0x12, 0x19, 0x92, 0x90, 0xff, | ||
415 | 0xf5, 0xe5, 0x23, 0xf0, 0xe4, 0xf5, 0x35, 0xf5, 0x33, 0xf5, 0x34, 0xf5, 0x32, 0x12, 0x1e, 0x34, | ||
416 | 0x12, 0x1c, 0xe0, 0x12, 0x1e, 0x3b, 0x90, 0xf9, 0x6a, 0x12, 0x1b, 0xf3, 0x90, 0xf9, 0x6f, 0x12, | ||
417 | 0x1b, 0xf3, 0x90, 0xff, 0xff, 0xe4, 0xf0, 0x90, 0xff, 0x83, 0xe0, 0xe4, 0xf0, 0x90, 0xff, 0x81, | ||
407 | 0x74, 0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x23, 0xe5, 0x23, | 418 | 0x74, 0x80, 0xf0, 0xa3, 0x74, 0x84, 0xf0, 0x90, 0xff, 0x80, 0xf0, 0xe4, 0xf5, 0x23, 0xe5, 0x23, |
408 | 0x12, 0x1c, 0xa7, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1c, 0xb5, 0xf5, 0x83, 0xe4, 0xf0, | 419 | 0x12, 0x1d, 0x57, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x23, 0x12, 0x1d, 0x65, 0xf5, 0x83, 0xe4, 0xf0, |
409 | 0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x31, | 420 | 0x05, 0x23, 0xe5, 0x23, 0xb4, 0x07, 0xe7, 0x78, 0x7a, 0x76, 0xfe, 0x08, 0x76, 0xf0, 0x90, 0x32, |
410 | 0x4d, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x31, 0x5a, 0xe4, 0x93, 0xff, | 421 | 0x0a, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xad, 0x07, 0x90, 0x32, 0x17, 0xe4, 0x93, 0xff, |
411 | 0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1c, 0x97, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, | 422 | 0x08, 0xf6, 0xff, 0xed, 0x54, 0x0f, 0xfd, 0x12, 0x1d, 0x47, 0x74, 0x84, 0xf0, 0xed, 0x75, 0xf0, |
412 | 0x08, 0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, | 423 | 0x08, 0xa4, 0x24, 0x47, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xc3, 0x74, 0xf0, |
413 | 0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0x28, 0xce, 0xc3, 0x13, 0xce, | 424 | 0x9f, 0x78, 0x7b, 0xf6, 0x74, 0xfe, 0x94, 0x00, 0x18, 0x12, 0x1c, 0xd8, 0xce, 0xc3, 0x13, 0xce, |
414 | 0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1c, 0xf8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0x1e, 0xe4, 0xf5, | 425 | 0x13, 0xd8, 0xf9, 0xff, 0xed, 0x12, 0x1d, 0xa8, 0xef, 0xf0, 0xed, 0x12, 0x1d, 0xce, 0xe4, 0xf5, |
415 | 0x23, 0xe5, 0x23, 0x90, 0x31, 0x47, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0, | 426 | 0x23, 0xe5, 0x23, 0x90, 0x32, 0x04, 0x93, 0xff, 0x78, 0x78, 0xf6, 0xfd, 0xe5, 0x23, 0x25, 0xe0, |
416 | 0x24, 0x4e, 0xf5, 0x82, 0xe4, 0x34, 0x31, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, | 427 | 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x34, 0x32, 0xf5, 0x83, 0xe4, 0x93, 0x08, 0xf6, 0xed, 0x30, 0xe7, |
417 | 0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0x97, 0x12, 0x1d, 0x06, 0x24, 0x47, 0xf5, 0x82, | 428 | 0x53, 0x18, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1d, 0x47, 0x12, 0x1d, 0xb6, 0x24, 0x47, 0xf5, 0x82, |
418 | 0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, | 429 | 0xe4, 0x34, 0xff, 0x12, 0x1c, 0xc8, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0xff, 0xe9, 0x12, |
419 | 0x1c, 0xf8, 0xef, 0xf0, 0x12, 0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, | 430 | 0x1d, 0xa8, 0xef, 0xf0, 0x12, 0x1c, 0xcf, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, |
420 | 0x0b, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0x1e, | 431 | 0xbb, 0x24, 0x45, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x12, 0x1d, 0xce, |
421 | 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, | 432 | 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x46, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, |
422 | 0xf0, 0x02, 0x18, 0xb7, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1c, 0xea, 0x12, 0x1d, 0x06, | 433 | 0xf0, 0x02, 0x19, 0x67, 0x78, 0x78, 0xe6, 0x54, 0x0f, 0xf9, 0x12, 0x1d, 0x9a, 0x12, 0x1d, 0xb6, |
423 | 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0x18, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, | 434 | 0x24, 0x07, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0x12, 0x1c, 0xc8, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, |
424 | 0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, | 435 | 0xf9, 0x12, 0x1d, 0xbb, 0x24, 0x01, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0x12, |
425 | 0x1c, 0x1f, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0x0b, 0x24, 0x05, 0xf5, 0x82, | 436 | 0x1c, 0xcf, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x12, 0x1d, 0xbb, 0x24, 0x05, 0xf5, 0x82, |
426 | 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, | 437 | 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xef, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x02, 0xf5, 0x82, |
427 | 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, | 438 | 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0xe9, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x06, 0xf5, 0x82, |
428 | 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x23, 0xe5, 0x23, 0x64, 0x04, 0x60, 0x03, 0x02, | 439 | 0xe4, 0x34, 0xff, 0xf5, 0x83, 0xe4, 0xf0, 0x05, 0x23, 0xe5, 0x23, 0x64, 0x04, 0x60, 0x03, 0x02, |
429 | 0x17, 0xe1, 0x90, 0x31, 0x4c, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1c, 0xe8, 0xe4, 0xf0, | 440 | 0x18, 0x91, 0x90, 0x32, 0x09, 0xe4, 0x93, 0xff, 0x78, 0x78, 0xf6, 0x12, 0x1d, 0x98, 0xe4, 0xf0, |
430 | 0x90, 0x31, 0x4b, 0x93, 0xff, 0xf6, 0x12, 0x1c, 0x95, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, | 441 | 0x90, 0x32, 0x08, 0x93, 0xff, 0xf6, 0x12, 0x1d, 0x45, 0xe4, 0xf0, 0x90, 0xff, 0xfd, 0x74, 0x05, |
431 | 0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, | 442 | 0xf0, 0x22, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, |
432 | 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0xe7, 0x09, 0xf6, 0x08, | 443 | 0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x26, 0x98, 0xe7, 0x09, 0xf6, 0x08, |
433 | 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, | 444 | 0xdf, 0xfa, 0x80, 0x46, 0xe7, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x3e, 0x88, 0x82, 0x8c, 0x83, |
434 | 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, | 445 | 0xe7, 0x09, 0xf0, 0xa3, 0xdf, 0xfa, 0x80, 0x32, 0xe3, 0x09, 0xf6, 0x08, 0xdf, 0xfa, 0x80, 0x78, |
435 | 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, | 446 | 0xe3, 0x09, 0xf2, 0x08, 0xdf, 0xfa, 0x80, 0x70, 0x88, 0x82, 0x8c, 0x83, 0xe3, 0x09, 0xf0, 0xa3, |
@@ -445,7 +456,7 @@ static unsigned char IMAGE_ARRAY_NAME[] = | |||
445 | 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, | 456 | 0x82, 0x8a, 0x83, 0xe4, 0x93, 0xa3, 0xf2, 0x08, 0xdf, 0xf9, 0x80, 0xcc, 0x88, 0xf0, 0xef, 0x60, |
446 | 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, | 457 | 0x01, 0x0e, 0x4e, 0x60, 0xc3, 0x88, 0xf0, 0xed, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xb9, 0xf5, |
447 | 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x19, | 458 | 0x82, 0xeb, 0x24, 0x02, 0xb4, 0x04, 0x00, 0x50, 0xaf, 0x23, 0x23, 0x45, 0x82, 0x23, 0x90, 0x19, |
448 | 0x4c, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, | 459 | 0xfc, 0x73, 0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, |
449 | 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, | 460 | 0xfe, 0x02, 0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22, 0xbb, 0x01, 0x0c, 0xe5, 0x82, |
450 | 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, | 461 | 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50, 0x06, 0xe9, 0x25, 0x82, 0xf8, |
451 | 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, | 462 | 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22, 0xe5, 0x82, 0x29, 0xf5, 0x82, |
@@ -469,364 +480,365 @@ static unsigned char IMAGE_ARRAY_NAME[] = | |||
469 | 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, | 480 | 0xe0, 0xf9, 0x22, 0xeb, 0xf0, 0xa3, 0xea, 0xf0, 0xa3, 0xe9, 0xf0, 0x22, 0xd0, 0x83, 0xd0, 0x82, |
470 | 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, | 481 | 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, |
471 | 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, | 482 | 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, |
472 | 0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, | 483 | 0x80, 0xdf, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0xe5, 0x4c, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25, |
473 | 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0x74, 0x11, 0x12, | 484 | 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0x74, 0x11, 0x12, |
474 | 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06, | 485 | 0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x06, |
475 | 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, | 486 | 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, |
476 | 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0x38, 0x04, 0x25, | 487 | 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, 0xe8, 0x04, 0x25, |
477 | 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, | 488 | 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0xab, 0x36, 0xfa, 0xa9, 0x38, 0xe4, 0x12, 0x1a, |
478 | 0x38, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab, | 489 | 0xe8, 0x04, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x90, 0xff, 0x04, 0xe0, 0xab, |
479 | 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, | 490 | 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8, 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, |
480 | 0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0x38, | 491 | 0x37, 0xf5, 0x37, 0x90, 0xff, 0x05, 0xe0, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x12, 0x1a, 0xe8, |
481 | 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x22, 0xf5, 0x83, 0xe0, 0x54, | 492 | 0x74, 0x01, 0x25, 0x38, 0xf5, 0x38, 0xe4, 0x35, 0x37, 0xf5, 0x37, 0x22, 0xf5, 0x83, 0xe0, 0x54, |
482 | 0x08, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, | 493 | 0x08, 0xab, 0x36, 0xaa, 0x37, 0xa9, 0x38, 0x22, 0xf5, 0x83, 0xef, 0xf0, 0xfd, 0x7c, 0x00, 0xc3, |
483 | 0x78, 0x7b, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, | 494 | 0x78, 0x7b, 0xe6, 0x9d, 0xf6, 0x18, 0xe6, 0x9c, 0xf6, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x03, 0x22, |
484 | 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x6f, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x12, | 495 | 0x75, 0x36, 0x01, 0x75, 0x37, 0xf9, 0x75, 0x38, 0x72, 0x22, 0xe0, 0x44, 0x04, 0xf0, 0x74, 0x13, |
485 | 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x7e, | 496 | 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0xe0, 0x22, 0x90, 0xfa, 0xbc, 0xe0, 0xff, 0x7e, |
486 | 0x00, 0xc3, 0x90, 0xfa, 0xbd, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbc, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, | 497 | 0x00, 0xc3, 0x90, 0xfa, 0xc0, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, |
487 | 0xb4, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5, | 498 | 0xb7, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0xef, 0x25, 0x4f, 0xf5, 0x4f, 0xee, 0x35, 0x4e, 0xf5, |
488 | 0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb1, 0x90, 0xfa, 0xb4, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, | 499 | 0x4e, 0x22, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xb4, 0x90, 0xfa, 0xb7, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, |
489 | 0xf5, 0x2e, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, | 500 | 0xf5, 0x2e, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x04, 0xf5, 0x82, 0xe4, |
490 | 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, | 501 | 0x35, 0x83, 0xf5, 0x83, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x40, 0xf5, 0x82, 0xe4, |
491 | 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, | 502 | 0x34, 0xff, 0xf5, 0x83, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x48, 0xf5, 0x82, 0xe4, |
492 | 0x34, 0xff, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, | 503 | 0x34, 0xff, 0x22, 0xe5, 0x4d, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x08, 0xf5, 0x82, 0xe4, 0x34, 0xff, |
493 | 0x22, 0x90, 0xfa, 0xb6, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, | 504 | 0x22, 0x90, 0xfa, 0xb9, 0xe0, 0xff, 0x24, 0xfc, 0x22, 0x90, 0xff, 0x00, 0xe0, 0x54, 0x1f, 0x22, |
494 | 0x90, 0xfa, 0xbb, 0xe0, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9, | 505 | 0x90, 0xfa, 0xbe, 0xe0, 0x90, 0xfa, 0xba, 0xf0, 0x22, 0x75, 0x33, 0x00, 0x8f, 0x34, 0x90, 0xf9, |
495 | 0x6c, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, | 506 | 0x6f, 0x12, 0x1b, 0xea, 0x90, 0x00, 0x02, 0x22, 0x54, 0x0f, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x00, |
496 | 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, | 507 | 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x75, 0xf0, 0x08, 0xa4, 0x24, 0x41, 0xf5, 0x82, |
497 | 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, | 508 | 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x22, 0x74, 0x80, 0xf0, 0x08, 0xe6, 0xff, 0xe9, 0x75, 0xf0, 0x08, |
498 | 0xa4, 0x22, 0x74, 0xaf, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, | 509 | 0xa4, 0x22, 0x74, 0xb2, 0x25, 0x22, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0x22, 0x75, 0xf0, |
499 | 0x08, 0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, | 510 | 0x08, 0xa4, 0x24, 0x42, 0xf5, 0x82, 0xe4, 0x34, 0xff, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x22, 0x90, |
500 | 0xff, 0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, | 511 | 0xff, 0x82, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x03, 0xf0, 0x90, 0xff, |
501 | 0xfc, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x67, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, | 512 | 0xfc, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0x78, 0x67, 0xe6, 0x54, 0xfd, 0xf6, 0x90, 0xff, 0xfd, 0x74, |
502 | 0x65, 0xf0, 0x22, 0x12, 0x1b, 0x1c, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, | 513 | 0x65, 0xf0, 0x22, 0x12, 0x1b, 0xcc, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x22, 0x7b, 0x01, 0x7a, |
503 | 0xfa, 0x79, 0xb4, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, | 514 | 0xfa, 0x79, 0xb7, 0x22, 0x90, 0xff, 0x80, 0xe0, 0x44, 0x08, 0xf0, 0x22, 0x90, 0xff, 0x83, 0xe0, |
504 | 0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x67, 0x02, 0x1b, 0x3a, 0x90, 0xff, 0xa4, 0xe0, | 515 | 0x54, 0x7f, 0xf0, 0x22, 0xe0, 0xff, 0x90, 0xf9, 0x6a, 0x02, 0x1b, 0xea, 0x90, 0xff, 0xa4, 0xe0, |
505 | 0x44, 0x02, 0xf0, 0x22, 0x75, 0x39, 0x01, 0x75, 0x3a, 0x09, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 0x79, | 516 | 0x44, 0x02, 0xf0, 0x22, 0x75, 0x39, 0x01, 0x75, 0x3a, 0x09, 0x22, 0x7b, 0x01, 0x7a, 0xf9, 0x79, |
506 | 0x6f, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbb, 0xe0, | 517 | 0x72, 0x22, 0xd3, 0xe5, 0x3c, 0x94, 0x08, 0xe5, 0x3b, 0x94, 0x01, 0x22, 0x90, 0xfa, 0xbe, 0xe0, |
507 | 0xff, 0x90, 0xfa, 0xb7, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, | 518 | 0xff, 0x90, 0xfa, 0xba, 0xf0, 0x22, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xef, 0x22, 0x90, 0xff, 0xb4, |
508 | 0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0x06, 0x12, 0x22, | 519 | 0xe0, 0x54, 0xef, 0x22, 0x12, 0x10, 0x4b, 0x78, 0x88, 0xef, 0xf6, 0x12, 0x2a, 0xc7, 0x12, 0x22, |
509 | 0x4a, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x21, 0xf3, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x0a, | 520 | 0xfa, 0x8e, 0x83, 0x24, 0x09, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x0a, |
510 | 0x12, 0x22, 0x52, 0x24, 0x0a, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0x4a, 0x12, | 521 | 0x12, 0x23, 0x02, 0x24, 0x0a, 0x12, 0x22, 0xa1, 0xe0, 0x90, 0x00, 0x0b, 0x12, 0x1a, 0xfa, 0x12, |
511 | 0x22, 0x4a, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x22, 0x56, 0x24, | 522 | 0x22, 0xfa, 0xf5, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xa3, 0xe0, 0xf5, 0x53, 0x12, 0x23, 0x06, 0x24, |
512 | 0x04, 0x12, 0x21, 0xf3, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55, | 523 | 0x04, 0x12, 0x22, 0xa1, 0xe0, 0xf5, 0x54, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0xa3, 0xe0, 0xf5, 0x55, |
513 | 0xe5, 0x53, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x88, 0xf6, 0xd3, 0x94, 0x00, 0x40, 0x06, | 524 | 0xe5, 0x53, 0xc4, 0x13, 0x13, 0x13, 0x54, 0x01, 0x78, 0x88, 0xf6, 0xd3, 0x94, 0x00, 0x40, 0x06, |
514 | 0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x0c, 0xef, | 525 | 0xe5, 0x54, 0x30, 0xe1, 0x01, 0x06, 0x78, 0x88, 0xe6, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x0c, 0xef, |
515 | 0x12, 0x1a, 0x4a, 0x78, 0x80, 0x12, 0x22, 0x09, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, | 526 | 0x12, 0x1a, 0xfa, 0x12, 0x22, 0xb5, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x53, 0x07, 0x0c, |
516 | 0x07, 0x0c, 0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, | 527 | 0x53, 0x06, 0xe6, 0xe5, 0x53, 0x30, 0xe5, 0x03, 0x43, 0x07, 0x01, 0xe5, 0x54, 0x20, 0xe5, 0x0e, |
517 | 0xe5, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, | 528 | 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, 0x07, 0x02, 0xe5, 0x53, |
518 | 0xe5, 0x53, 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, | 529 | 0x30, 0xe3, 0x03, 0x43, 0x07, 0x10, 0xe5, 0x53, 0x30, 0xe2, 0x03, 0x43, 0x07, 0x20, 0xe5, 0x53, |
519 | 0xe5, 0x53, 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, | 530 | 0x54, 0x03, 0x60, 0x03, 0x43, 0x07, 0x40, 0xe5, 0x53, 0x30, 0xe1, 0x03, 0x43, 0x07, 0x80, 0xe5, |
520 | 0x80, 0xe5, 0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, | 531 | 0x53, 0x30, 0xe4, 0x03, 0x43, 0x06, 0x01, 0xe5, 0x53, 0x30, 0xe6, 0x03, 0x43, 0x06, 0x08, 0xe5, |
521 | 0x08, 0xe5, 0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, | 532 | 0x54, 0x20, 0xe4, 0x0e, 0xe5, 0x53, 0x54, 0x7f, 0x70, 0x08, 0xe5, 0x53, 0x20, 0xe7, 0x03, 0x43, |
522 | 0x03, 0x43, 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, | 533 | 0x06, 0x10, 0x53, 0x07, 0xfb, 0x53, 0x06, 0x79, 0x90, 0x00, 0x05, 0xee, 0x8f, 0xf0, 0x12, 0x1b, |
523 | 0x12, 0x1a, 0xef, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, | 534 | 0x9f, 0xe5, 0x55, 0x30, 0xe3, 0x12, 0x54, 0x30, 0xff, 0xc4, 0x54, 0x0f, 0x12, 0x22, 0xe7, 0x90, |
524 | 0x2c, 0x90, 0x00, 0x08, 0xef, 0x12, 0x1a, 0x4a, 0x80, 0x0a, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x08, | 535 | 0x00, 0x08, 0xef, 0x12, 0x1a, 0xfa, 0x80, 0x0a, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x08, 0xe4, 0x12, |
525 | 0xe4, 0x12, 0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x07, 0xef, 0x12, | 536 | 0x1a, 0xfa, 0xe5, 0x55, 0x54, 0x03, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x07, 0xef, 0x12, 0x1a, 0xfa, |
526 | 0x1a, 0x4a, 0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0x4a, 0x90, | 537 | 0xe5, 0x55, 0x54, 0x04, 0xff, 0xc3, 0x13, 0x90, 0x00, 0x09, 0x12, 0x1a, 0xfa, 0x90, 0x00, 0x07, |
527 | 0x00, 0x07, 0x12, 0x1a, 0x0b, 0x70, 0x13, 0x12, 0x22, 0x2d, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, | 538 | 0x12, 0x1a, 0xbb, 0x70, 0x13, 0x12, 0x22, 0xe8, 0xe9, 0x24, 0x09, 0xf9, 0xe4, 0x3a, 0xfa, 0x12, |
528 | 0xfa, 0x12, 0x19, 0xf2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0x38, 0x12, 0x22, 0x78, 0x24, 0x08, 0x12, | 539 | 0x1a, 0xa2, 0xff, 0xc3, 0x13, 0x12, 0x1a, 0xe8, 0x12, 0x23, 0x27, 0x24, 0x08, 0x12, 0x22, 0xa1, |
529 | 0x21, 0xf3, 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x21, 0xf3, 0xe0, | 540 | 0xe0, 0xfe, 0x8d, 0x82, 0x8c, 0x83, 0xe5, 0x82, 0x24, 0x07, 0x12, 0x22, 0xa1, 0xe0, 0xfd, 0xee, |
530 | 0xfd, 0xee, 0xed, 0x12, 0x22, 0x2c, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0xef, 0x12, | 541 | 0xed, 0x12, 0x22, 0xe7, 0x90, 0x00, 0x03, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x9f, 0x12, 0x32, 0x84, |
531 | 0x31, 0xc7, 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0x90, 0xfa, 0xe3, 0xe0, | 542 | 0x7d, 0x0a, 0xe4, 0xff, 0x12, 0x2f, 0xb4, 0x02, 0x10, 0xce, 0x90, 0xfa, 0xe6, 0xe0, 0xb4, 0x03, |
532 | 0xb4, 0x03, 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xd7, | 543 | 0x06, 0x7e, 0x00, 0x7f, 0x40, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x08, 0x90, 0xfa, 0xda, 0xee, 0xf0, |
533 | 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xff, 0x7e, 0x00, 0x90, 0xfa, | 544 | 0xa3, 0xef, 0xf0, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb, 0xff, 0x7e, 0x00, 0x90, 0xfa, 0xd6, 0xee, |
534 | 0xd3, 0xee, 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1a, | 545 | 0xf0, 0xa3, 0xef, 0xf0, 0x70, 0x03, 0x7f, 0x08, 0x22, 0x90, 0x00, 0x08, 0x12, 0x1b, 0x48, 0xff, |
535 | 0x98, 0xff, 0x90, 0xfa, 0xd5, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, | 546 | 0x90, 0xfa, 0xd8, 0xe5, 0xf0, 0xf0, 0xa3, 0xef, 0xf0, 0xae, 0x02, 0xaf, 0x01, 0x8e, 0x50, 0x8f, |
536 | 0x50, 0x8f, 0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, | 547 | 0x51, 0x74, 0x0a, 0x25, 0x51, 0xf5, 0x51, 0xe4, 0x35, 0x50, 0xf5, 0x50, 0x90, 0xfa, 0xdb, 0xe0, |
537 | 0xd8, 0xe0, 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd6, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, | 548 | 0xff, 0x14, 0xfe, 0x90, 0xfa, 0xd9, 0xe0, 0x5e, 0xfe, 0xc3, 0xef, 0x9e, 0xff, 0x90, 0xfa, 0xdd, |
538 | 0xfa, 0xda, 0xf0, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0x90, 0xfa, 0xd3, 0xe0, 0x94, 0x00, 0x50, | 549 | 0xf0, 0xc3, 0x90, 0xfa, 0xd7, 0xe0, 0x9f, 0x90, 0xfa, 0xd6, 0xe0, 0x94, 0x00, 0x50, 0x06, 0xa3, |
539 | 0x06, 0xa3, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, | 550 | 0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x12, 0x20, 0xa9, 0x60, 0x03, 0xe0, 0xff, 0x22, 0x12, 0x2e, 0x2b, |
540 | 0x2d, 0x5a, 0x90, 0xfa, 0xd3, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xd7, | 551 | 0x90, 0xfa, 0xd6, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0x4e, 0x60, 0x2b, 0x90, 0xfa, 0xda, 0xe0, 0xfc, |
541 | 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xda, | 552 | 0xa3, 0xe0, 0xfd, 0xd3, 0xef, 0x9d, 0xee, 0x9c, 0x40, 0x07, 0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x80, |
542 | 0xf0, 0x80, 0x08, 0x90, 0xfa, 0xd4, 0xe0, 0x90, 0xfa, 0xda, 0xf0, 0x12, 0x1f, 0xfb, 0x60, 0x03, | 553 | 0x08, 0x90, 0xfa, 0xd7, 0xe0, 0x90, 0xfa, 0xdd, 0xf0, 0x12, 0x20, 0xa9, 0x60, 0x03, 0xe0, 0xff, |
543 | 0xe0, 0xff, 0x22, 0x12, 0x2d, 0x5a, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, | 554 | 0x22, 0x12, 0x2e, 0x2b, 0x80, 0xca, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x52, 0xe4, 0xf5, 0x2d, 0xf5, |
544 | 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, | 555 | 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x7f, 0x00, 0x22, 0xaa, 0x50, 0xa9, 0x51, 0x7b, 0x01, 0x90, |
545 | 0x01, 0x90, 0xfa, 0xd5, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xda, 0xe0, 0xf5, 0x4a, 0x12, | 556 | 0xfa, 0xd8, 0xe0, 0xfc, 0xa3, 0xe0, 0xfd, 0x90, 0xfa, 0xdd, 0xe0, 0xf5, 0x4a, 0x12, 0x29, 0x60, |
546 | 0x28, 0x9f, 0x90, 0xfa, 0xd9, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, | 557 | 0x90, 0xfa, 0xdc, 0xef, 0xf0, 0x22, 0xef, 0x24, 0xae, 0x60, 0x52, 0x24, 0xfe, 0x60, 0x2e, 0x24, |
547 | 0x2e, 0x24, 0xfe, 0x70, 0x03, 0x02, 0x20, 0xbb, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0x03, 0x78, | 558 | 0xfe, 0x70, 0x03, 0x02, 0x21, 0x69, 0x24, 0x06, 0x60, 0x03, 0x02, 0x21, 0xb1, 0x78, 0x71, 0xe6, |
548 | 0x71, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, | 559 | 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xa5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x33, 0x90, 0xfa, |
549 | 0x90, 0xfa, 0x91, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xaf, 0x74, 0x01, 0xf0, 0x22, 0x78, | 560 | 0x94, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb2, 0x74, 0x01, 0xf0, 0x22, 0x78, 0x72, 0xe6, |
550 | 0x72, 0xe6, 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, | 561 | 0x54, 0xfb, 0xf6, 0x90, 0xff, 0xb5, 0xe0, 0xf5, 0x22, 0x44, 0x0f, 0xf0, 0x74, 0x43, 0x90, 0xfa, |
551 | 0x90, 0xfa, 0x93, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb0, 0x74, 0x01, 0xf0, 0x22, 0x90, | 562 | 0x96, 0xf0, 0xe5, 0x22, 0xa3, 0xf0, 0x90, 0xfa, 0xb3, 0x74, 0x01, 0xf0, 0x22, 0x90, 0xfa, 0xa0, |
552 | 0xfa, 0x9d, 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0x03, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, | 563 | 0xe0, 0xa3, 0x20, 0xe5, 0x03, 0x02, 0x21, 0xb1, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0, |
553 | 0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, | 564 | 0xa3, 0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xa6, 0x12, |
554 | 0xa6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, | 565 | 0x23, 0x0d, 0x90, 0xff, 0xa6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xce, 0xe0, |
555 | 0xcb, 0xe0, 0xff, 0x74, 0x34, 0xfe, 0x12, 0x2c, 0xb4, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xcb, 0xe0, | 566 | 0xff, 0x74, 0x34, 0xfe, 0x12, 0x2d, 0x85, 0xef, 0x70, 0x57, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74, |
556 | 0xff, 0x74, 0x34, 0x90, 0xfa, 0x95, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xa7, 0xe0, 0xa3, | 567 | 0x34, 0x90, 0xfa, 0x98, 0xf0, 0xef, 0xa3, 0xf0, 0x22, 0x90, 0xfa, 0xaa, 0xe0, 0xa3, 0x30, 0xe5, |
557 | 0x30, 0xe5, 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xca, | 568 | 0x40, 0x90, 0xff, 0xb6, 0xe0, 0x90, 0xfa, 0xcd, 0xf0, 0xa3, 0xf0, 0x90, 0xfa, 0xcd, 0xe0, 0xff, |
558 | 0xe0, 0xff, 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x22, 0x5d, 0x90, 0xff, 0xb6, | 569 | 0x54, 0x0f, 0xfe, 0x60, 0x10, 0x90, 0xff, 0xb6, 0x12, 0x23, 0x0d, 0x90, 0xff, 0xb6, 0xe0, 0x90, |
559 | 0xe0, 0x90, 0xfa, 0xca, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, | 570 | 0xfa, 0xcd, 0xf0, 0x80, 0xe6, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74, 0x44, 0xfe, 0x12, 0x2d, 0x85, |
560 | 0x2c, 0xb4, 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xcb, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x97, 0xf0, | 571 | 0xef, 0x70, 0x0e, 0x90, 0xfa, 0xce, 0xe0, 0xff, 0x74, 0x44, 0x90, 0xfa, 0x9a, 0xf0, 0xef, 0xa3, |
561 | 0xef, 0xa3, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, | 572 | 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x00, 0xc0, |
562 | 0x00, 0xc0, 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, | 573 | 0x00, 0xc0, 0x01, 0xc0, 0x02, 0xc0, 0x03, 0xc0, 0x04, 0xc0, 0x05, 0xc0, 0x06, 0xc0, 0x07, 0x90, |
563 | 0x07, 0x90, 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xc9, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, | 574 | 0xff, 0x92, 0xe0, 0xff, 0x90, 0xfa, 0xcc, 0xf0, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0xef, 0x12, 0x1b, |
564 | 0x12, 0x1b, 0x4c, 0x21, 0xbb, 0x26, 0x21, 0xbb, 0x2e, 0x21, 0x5e, 0x30, 0x21, 0x5e, 0x32, 0x21, | 575 | 0xfc, 0x22, 0x69, 0x26, 0x22, 0x69, 0x2e, 0x22, 0x0c, 0x30, 0x22, 0x0c, 0x32, 0x22, 0x1a, 0x38, |
565 | 0x6c, 0x38, 0x21, 0x7e, 0x3a, 0x21, 0xb0, 0x3e, 0x21, 0x9b, 0x44, 0x21, 0x90, 0x46, 0x21, 0xa6, | 576 | 0x22, 0x2c, 0x3a, 0x22, 0x5e, 0x3e, 0x22, 0x49, 0x44, 0x22, 0x3e, 0x46, 0x22, 0x54, 0x50, 0x22, |
566 | 0x50, 0x21, 0xa6, 0x52, 0x21, 0xa6, 0x54, 0x21, 0xa6, 0x56, 0x00, 0x00, 0x21, 0xc0, 0x90, 0xfa, | 577 | 0x54, 0x52, 0x22, 0x54, 0x54, 0x22, 0x54, 0x56, 0x00, 0x00, 0x22, 0x6e, 0x90, 0xfa, 0xcc, 0xe0, |
567 | 0xc9, 0xe0, 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x16, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, | 578 | 0xfd, 0x7c, 0x00, 0x7f, 0x01, 0x12, 0x11, 0x5e, 0x80, 0x62, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x03, |
568 | 0x7f, 0x03, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, | 579 | 0x12, 0x11, 0x5e, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x20, 0xf0, 0x80, 0x50, 0x7c, 0x00, 0x7d, 0x01, |
569 | 0x7d, 0x01, 0x7f, 0x02, 0x12, 0x11, 0x16, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, | 580 | 0x7f, 0x02, 0x12, 0x11, 0x5e, 0x90, 0xff, 0xfe, 0xe0, 0x44, 0x40, 0xf0, 0x80, 0x3e, 0x7c, 0x00, |
570 | 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x16, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, | 581 | 0x7d, 0x01, 0x7f, 0x05, 0x12, 0x11, 0x5e, 0x80, 0x33, 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x06, 0x12, |
571 | 0x06, 0x12, 0x11, 0x16, 0x80, 0x28, 0x90, 0xfa, 0xc9, 0xe0, 0xff, 0x12, 0x20, 0x18, 0x80, 0x1e, | 582 | 0x11, 0x5e, 0x80, 0x28, 0x90, 0xfa, 0xcc, 0xe0, 0xff, 0x12, 0x20, 0xc6, 0x80, 0x1e, 0x7c, 0x00, |
572 | 0x7c, 0x00, 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x16, 0x80, 0x13, 0x12, 0x27, 0x8d, 0x80, 0x0e, | 583 | 0x7d, 0x01, 0x7f, 0x04, 0x12, 0x11, 0x5e, 0x80, 0x13, 0x12, 0x28, 0x4e, 0x80, 0x0e, 0x90, 0xfa, |
573 | 0x90, 0xfa, 0xc9, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2c, 0xb4, 0xd0, 0x07, | 584 | 0xcc, 0xe0, 0x24, 0x00, 0xff, 0xe4, 0x34, 0xff, 0xfe, 0x12, 0x2d, 0x85, 0xd0, 0x07, 0xd0, 0x06, |
574 | 0xd0, 0x06, 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, | 585 | 0xd0, 0x05, 0xd0, 0x04, 0xd0, 0x03, 0xd0, 0x02, 0xd0, 0x01, 0xd0, 0x00, 0xd0, 0xd0, 0xd0, 0x82, |
575 | 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, | 586 | 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0x24, 0x04, 0x8e, |
576 | 0x04, 0x8e, 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x12, 0x25, 0x24, 0xf5, | 587 | 0x83, 0xf5, 0x82, 0xe4, 0x35, 0x83, 0xf5, 0x83, 0x22, 0x74, 0x13, 0x25, 0x24, 0xf5, 0x82, 0xe4, |
577 | 0x82, 0xe4, 0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, | 588 | 0x34, 0xf9, 0xf5, 0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0x22, |
578 | 0x83, 0x22, 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, | 589 | 0x78, 0x80, 0xe6, 0xfe, 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0x7b, 0xff, 0x7a, |
579 | 0xff, 0x7a, 0x31, 0x79, 0x99, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x19, 0xcc, 0xff, 0x90, 0xf9, 0x6c, | 590 | 0x32, 0x79, 0x56, 0x7e, 0x00, 0x7f, 0x0a, 0x02, 0x1a, 0x7c, 0x78, 0x80, 0xe6, 0xfc, 0x08, 0xe6, |
580 | 0x02, 0x1b, 0x3a, 0x90, 0xf9, 0x67, 0x12, 0x1b, 0x3a, 0x90, 0x00, 0x04, 0x02, 0x1a, 0x0b, 0xe6, | 591 | 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0xff, 0x90, 0xf9, 0x6f, 0x02, 0x1b, 0xea, 0x90, 0xf9, |
581 | 0xfc, 0x08, 0xe6, 0xf5, 0x82, 0x8c, 0x83, 0xa3, 0xa3, 0x22, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6, | 592 | 0x6a, 0x12, 0x1b, 0xea, 0x90, 0x00, 0x04, 0x02, 0x1a, 0xbb, 0x78, 0x7e, 0xe6, 0xfe, 0x08, 0xe6, |
582 | 0xff, 0x22, 0xed, 0x12, 0x1a, 0x4a, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, | 593 | 0xff, 0x22, 0xed, 0x12, 0x1a, 0xfa, 0x8f, 0x82, 0x8e, 0x83, 0xe5, 0x82, 0x22, 0xef, 0xf0, 0x90, |
583 | 0xfa, 0xcb, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x08, 0xe6, | 594 | 0xfa, 0xce, 0xe0, 0x54, 0x0f, 0x4e, 0xfe, 0xf0, 0xef, 0x54, 0xf0, 0x4e, 0xf0, 0x22, 0x78, 0x80, |
584 | 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x24, 0x09, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, | 595 | 0xe6, 0xfc, 0x08, 0xe6, 0x8c, 0x83, 0x22, 0x78, 0x7e, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x8c, 0x83, |
585 | 0x83, 0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, | 596 | 0x22, 0xa6, 0x07, 0xe6, 0x24, 0x6e, 0xf8, 0xe6, 0x22, 0x78, 0x7e, 0xe6, 0xfa, 0x08, 0xe6, 0xfb, |
586 | 0xfb, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82, 0x22, | 597 | 0x22, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x22, 0x26, 0xf6, 0x18, 0xee, 0x36, 0xf6, 0x22, |
587 | 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, 0xa3, 0x74, 0x02, | 598 | 0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0x22, 0x8b, 0x82, 0x8a, 0x83, 0xe5, 0x82, |
588 | 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, 0xf5, | 599 | 0x22, 0x8b, 0x25, 0x8a, 0x26, 0x89, 0x27, 0x8d, 0x28, 0x90, 0xfa, 0xd2, 0xe4, 0xf0, 0xa3, 0x74, |
589 | 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xce, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3, 0xe0, | 600 | 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xd1, 0x90, 0xfa, 0xd2, 0xe0, 0xf5, 0x2d, 0xa3, 0xe0, |
590 | 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xce, 0xe0, | 601 | 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xd1, 0xe0, 0x65, 0x28, 0x60, 0x46, 0xa3, |
591 | 0xff, 0x90, 0xfa, 0xd1, 0xe4, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0x12, 0x23, 0x2f, 0x90, 0xfa, 0xd1, | 602 | 0xe0, 0xff, 0xa3, 0xe0, 0xa3, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x12, 0x23, 0xf0, 0x90, 0xfa, 0xd1, |
592 | 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xcf, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xce, 0xe0, | 603 | 0xe0, 0xff, 0x90, 0xfa, 0xd4, 0xe4, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0x12, 0x23, 0xf0, 0x90, 0xfa, |
593 | 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x04, 0x12, 0x1a, | 604 | 0xd4, 0xe0, 0xff, 0xa3, 0xe0, 0x90, 0xfa, 0xd2, 0xcf, 0xf0, 0xa3, 0xef, 0xf0, 0x90, 0xfa, 0xd1, |
594 | 0x6c, 0x02, 0x22, 0xb1, 0x90, 0xfa, 0xd0, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xcf, 0xe0, 0x34, | 605 | 0xe0, 0xa3, 0x75, 0xf0, 0x00, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xd2, 0xe4, 0x75, 0xf0, 0x04, 0x12, |
595 | 0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1a, 0xd0, 0x7f, 0x00, 0x22, 0x7b, | 606 | 0x1b, 0x1c, 0x02, 0x23, 0x72, 0x90, 0xfa, 0xd3, 0xe0, 0x24, 0x01, 0xff, 0x90, 0xfa, 0xd2, 0xe0, |
596 | 0x01, 0x7a, 0xfa, 0x79, 0xce, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x6c, 0x85, | 607 | 0x34, 0x00, 0xab, 0x25, 0xaa, 0x26, 0xa9, 0x27, 0x8f, 0xf0, 0x12, 0x1b, 0x80, 0x7f, 0x00, 0x22, |
597 | 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x25, 0xd7, 0x8f, 0x62, 0x12, 0x2a, 0x06, 0x12, 0x22, | 608 | 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xd1, 0x90, 0xfa, 0xd2, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1b, 0x1c, |
598 | 0x4a, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0, 0x08, | 609 | 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x02, 0x26, 0x98, 0x8f, 0x62, 0x12, 0x2a, 0xc7, 0x12, |
599 | 0x12, 0x22, 0x3f, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x22, 0x56, 0x24, 0x0b, 0x12, 0x21, 0xf3, | 610 | 0x22, 0xfa, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x02, 0xf0, |
600 | 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, | 611 | 0x08, 0x12, 0x22, 0xdc, 0xe0, 0xa3, 0x30, 0xe5, 0x0c, 0x12, 0x23, 0x06, 0x24, 0x0b, 0x12, 0x22, |
601 | 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82, 0x24, | 612 | 0xa1, 0xe0, 0x44, 0x01, 0xf0, 0x78, 0x7c, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xf5, 0x82, 0x8e, 0x83, |
602 | 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, 0x74, | 613 | 0xe0, 0x54, 0xb8, 0xfd, 0xf0, 0xe5, 0x62, 0x24, 0xfe, 0x44, 0x20, 0xfc, 0x4d, 0xf0, 0xe5, 0x82, |
603 | 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x21, 0xf3, 0xc0, | 614 | 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xb8, 0xf0, 0x4c, 0xf0, 0x8f, 0x82, 0x8e, 0x83, 0xa3, |
604 | 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x96, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, | 615 | 0x74, 0x03, 0xf0, 0x18, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x8e, 0x83, 0x24, 0x05, 0x12, 0x22, 0xa1, |
605 | 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, 0x8e, | 616 | 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfd, 0x74, 0x99, 0x25, 0x62, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, |
606 | 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, | 617 | 0x83, 0xe0, 0x54, 0xfc, 0x44, 0x03, 0xfc, 0xed, 0x4c, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x8f, 0x82, |
607 | 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, | 618 | 0x8e, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, 0x44, 0x80, |
608 | 0x10, 0x03, 0x7f, 0x02, 0x12, 0x12, 0x19, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, 0xd2, | 619 | 0xf0, 0x12, 0x32, 0x84, 0x74, 0x6e, 0x25, 0x62, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, |
609 | 0xb1, 0x90, 0xf9, 0x15, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36, 0xd2, | 620 | 0x12, 0x10, 0x4b, 0x7f, 0x02, 0x12, 0x12, 0x61, 0x78, 0x67, 0xe6, 0x44, 0x02, 0xf6, 0xd2, 0xb0, |
610 | 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7b, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, 0x7c, | 621 | 0xd2, 0xb1, 0x90, 0xf9, 0x16, 0xe0, 0x30, 0xe7, 0x07, 0x90, 0xff, 0x9e, 0xe4, 0xf0, 0x80, 0x36, |
611 | 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x79, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, 0x7a, | 622 | 0xd2, 0xb3, 0x90, 0xff, 0xa4, 0xe0, 0x90, 0xfa, 0x7e, 0xf0, 0x90, 0xff, 0xb4, 0xe0, 0x90, 0xfa, |
612 | 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, 0x40, | 623 | 0x7f, 0xf0, 0x90, 0xff, 0xa2, 0xe0, 0x90, 0xfa, 0x7c, 0xf0, 0x90, 0xff, 0xb2, 0xe0, 0x90, 0xfa, |
613 | 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe4, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, 0xff, | 624 | 0x7d, 0xf0, 0x90, 0xff, 0xa4, 0x74, 0x30, 0xf0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xff, 0xa2, 0x74, |
614 | 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, 0x87, | 625 | 0x40, 0xf0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xfa, 0xe7, 0xe5, 0xa8, 0xf0, 0x75, 0xa8, 0x81, 0x90, |
615 | 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7b, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, | 626 | 0xff, 0x92, 0xe0, 0x60, 0x04, 0xe4, 0xf0, 0x80, 0xf6, 0x90, 0xff, 0xfd, 0x74, 0x3a, 0xf0, 0x43, |
616 | 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x79, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7a, 0xe0, | 627 | 0x87, 0x01, 0x00, 0x00, 0x00, 0x90, 0xfa, 0x7e, 0xe0, 0x90, 0xff, 0xa4, 0xf0, 0x90, 0xfa, 0x7f, |
617 | 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe4, 0xe0, | 628 | 0xe0, 0x90, 0xff, 0xb4, 0xf0, 0x90, 0xfa, 0x7c, 0xe0, 0x90, 0xff, 0xa2, 0xf0, 0x90, 0xfa, 0x7d, |
618 | 0xf5, 0xa8, 0x02, 0x10, 0x86, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2d, 0x3c, 0x90, 0xfa, | 629 | 0xe0, 0x90, 0xff, 0xb2, 0xf0, 0x90, 0xf9, 0x18, 0xe0, 0x60, 0x02, 0xc2, 0xb3, 0x90, 0xfa, 0xe7, |
619 | 0xc0, 0x12, 0x1b, 0x43, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x43, 0x90, 0xfa, | 630 | 0xe0, 0xf5, 0xa8, 0x02, 0x10, 0xce, 0x8b, 0x5c, 0x8a, 0x5d, 0x89, 0x5e, 0x12, 0x2e, 0x0d, 0x90, |
620 | 0xc4, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1a, 0x6c, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0x3a, 0xe9, 0x24, | 631 | 0xfa, 0xc3, 0x12, 0x1b, 0xf3, 0xaa, 0x5d, 0xa9, 0x5e, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0xf3, 0x90, |
621 | 0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xab, 0x5c, 0xaa, 0x5d, 0xa9, | 632 | 0xfa, 0xc7, 0xe4, 0x75, 0xf0, 0x0a, 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0xea, 0xe9, |
622 | 0x5e, 0x12, 0x2d, 0x48, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa, 0xbe, | 633 | 0x24, 0x01, 0xf9, 0xe4, 0x3a, 0xfa, 0x90, 0xfa, 0xc9, 0x12, 0x1b, 0xf3, 0xab, 0x5c, 0xaa, 0x5d, |
623 | 0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc0, 0x12, 0x2d, 0x1d, 0xff, | 634 | 0xa9, 0x5e, 0x12, 0x2e, 0x19, 0xe0, 0xff, 0xc3, 0x13, 0xf0, 0xe4, 0x78, 0x82, 0xf6, 0x90, 0xfa, |
624 | 0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0x1d, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83, 0xf6, | 635 | 0xc1, 0xe0, 0xff, 0x78, 0x82, 0xe6, 0xc3, 0x9f, 0x50, 0x4a, 0x90, 0xfa, 0xc3, 0x12, 0x2d, 0xee, |
625 | 0x12, 0x2d, 0x1a, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0x23, 0x75, 0xf0, 0x02, 0x12, | 636 | 0xff, 0x78, 0x83, 0xf6, 0x90, 0xfa, 0xc6, 0x12, 0x2d, 0xee, 0xfe, 0xf4, 0x5f, 0xff, 0x78, 0x83, |
626 | 0x1a, 0x6c, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1a, 0x6c, 0xab, 0x5c, 0xaa, 0x5d, | 637 | 0xf6, 0x12, 0x2d, 0xeb, 0x5e, 0x4f, 0xff, 0x78, 0x83, 0xf6, 0x12, 0x2d, 0xf4, 0x75, 0xf0, 0x02, |
627 | 0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x0b, 0x30, 0xe4, 0x03, 0x12, 0x2d, 0x32, 0x78, 0x82, | 638 | 0x12, 0x1b, 0x1c, 0x90, 0xfa, 0xc7, 0xe4, 0x75, 0xf0, 0x02, 0x12, 0x1b, 0x1c, 0xab, 0x5c, 0xaa, |
628 | 0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xbf, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58, 0x90, | 639 | 0x5d, 0xa9, 0x5e, 0x90, 0x00, 0x04, 0x12, 0x1a, 0xbb, 0x30, 0xe4, 0x03, 0x12, 0x2e, 0x03, 0x78, |
629 | 0xfa, 0xbf, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xbe, 0xf0, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, | 640 | 0x82, 0x06, 0x80, 0xaa, 0xe4, 0x90, 0xfa, 0xc2, 0xf0, 0x22, 0x8b, 0x56, 0x8a, 0x57, 0x89, 0x58, |
630 | 0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x24, 0x95, | 641 | 0x90, 0xfa, 0xc2, 0x74, 0x06, 0xf0, 0xe4, 0x90, 0xfa, 0xc1, 0xf0, 0x12, 0x1a, 0xa2, 0x24, 0x6e, |
631 | 0x80, 0x62, 0x12, 0x2d, 0x53, 0x12, 0x1f, 0x2c, 0x90, 0xfa, 0xbf, 0xef, 0xf0, 0x80, 0x55, 0x90, | 642 | 0x60, 0x26, 0x14, 0x70, 0x70, 0x12, 0x2d, 0xda, 0x60, 0x09, 0x24, 0x30, 0x70, 0x12, 0x12, 0x25, |
632 | 0xfa, 0xbf, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0x09, 0x60, 0x09, 0x24, 0x30, 0x70, 0x3e, | 643 | 0x56, 0x80, 0x62, 0x12, 0x2e, 0x24, 0x12, 0x1f, 0xda, 0x90, 0xfa, 0xc2, 0xef, 0xf0, 0x80, 0x55, |
633 | 0x12, 0x2c, 0x5f, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b, 0x01, | 644 | 0x90, 0xfa, 0xc2, 0x74, 0x81, 0xf0, 0x80, 0x4d, 0x12, 0x2d, 0xda, 0x60, 0x09, 0x24, 0x30, 0x70, |
634 | 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0xfd, | 645 | 0x3e, 0x12, 0x2d, 0x30, 0x80, 0x3f, 0xe5, 0x58, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x57, 0xfa, 0x7b, |
635 | 0x90, 0x00, 0x08, 0x12, 0x1a, 0x98, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02, 0xd0, | 646 | 0x01, 0xc0, 0x03, 0xc0, 0x02, 0xc0, 0x01, 0x12, 0x2e, 0x24, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb, |
636 | 0x03, 0x12, 0x25, 0xd7, 0x90, 0xfa, 0xbe, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, 0xfa, | 647 | 0xfd, 0x90, 0x00, 0x08, 0x12, 0x1b, 0x48, 0xf5, 0x2e, 0x85, 0xf0, 0x2d, 0xd0, 0x01, 0xd0, 0x02, |
637 | 0xbf, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xbf, 0xe0, 0x12, 0x2d, 0x53, 0x90, 0x00, 0x02, 0x12, 0x1a, | 648 | 0xd0, 0x03, 0x12, 0x26, 0x98, 0x90, 0xfa, 0xc1, 0xef, 0xf0, 0xe4, 0xa3, 0xf0, 0x80, 0x06, 0x90, |
638 | 0x4a, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c, 0xe5, | 649 | 0xfa, 0xc2, 0x74, 0x81, 0xf0, 0x90, 0xfa, 0xc2, 0xe0, 0x12, 0x2e, 0x24, 0x90, 0x00, 0x02, 0x12, |
639 | 0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2d, 0x82, 0x70, 0x16, 0x12, 0x2d, 0xa1, 0xe5, 0x2d, | 650 | 0x1a, 0xfa, 0x90, 0xfa, 0xc1, 0xe0, 0xff, 0x22, 0x8b, 0x29, 0x8a, 0x2a, 0x89, 0x2b, 0x8d, 0x2c, |
640 | 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x26, 0x64, 0x40, 0x0b, 0x7f, 0x00, | 651 | 0xe5, 0x2c, 0x70, 0x03, 0xaf, 0x2c, 0x22, 0x12, 0x2e, 0x53, 0x70, 0x16, 0x12, 0x2e, 0x72, 0xe5, |
641 | 0x22, 0x12, 0x2d, 0xa1, 0x12, 0x26, 0x64, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, 0xe5, | 652 | 0x2d, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0xd8, 0x50, 0xf2, 0x12, 0x27, 0x25, 0x40, 0x0b, 0x7f, |
642 | 0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, 0xf0, | 653 | 0x00, 0x22, 0x12, 0x2e, 0x72, 0x12, 0x27, 0x25, 0x50, 0xf8, 0x90, 0xff, 0xf3, 0x74, 0xa1, 0xf0, |
643 | 0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0x04, 0x40, | 654 | 0xe5, 0x2c, 0xb4, 0x01, 0x07, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0xf1, 0xe4, |
644 | 0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, 0xf0, | 655 | 0xf0, 0xf5, 0x2f, 0xe5, 0x2c, 0x14, 0xff, 0xe5, 0x2f, 0xc3, 0x9f, 0x50, 0x2a, 0x12, 0x31, 0xc1, |
645 | 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2d, 0x94, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b, 0xe4, | 656 | 0x40, 0x03, 0xaf, 0x2f, 0x22, 0xc3, 0xe5, 0x2c, 0x95, 0x2f, 0xff, 0xbf, 0x02, 0x07, 0x90, 0xff, |
646 | 0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0x04, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, 0x2d, | 657 | 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x12, 0x2e, 0x65, 0x05, 0x2f, 0x74, 0x01, 0x25, 0x2b, 0xf5, 0x2b, |
647 | 0x94, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0x1b, 0x12, 0x10, 0x03, | 658 | 0xe4, 0x35, 0x2a, 0xf5, 0x2a, 0x80, 0xcc, 0x12, 0x31, 0xc1, 0x40, 0x03, 0x7f, 0x18, 0x22, 0x12, |
648 | 0x78, 0x84, 0x12, 0x22, 0x82, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x30, 0xec, 0x02, 0x26, 0xfb, | 659 | 0x2e, 0x65, 0xaf, 0x2c, 0x22, 0x90, 0xff, 0xf1, 0xe5, 0x2e, 0xf0, 0x02, 0x31, 0xd8, 0x12, 0x10, |
649 | 0x78, 0x84, 0xe6, 0xf9, 0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54, 0x03, | 660 | 0x4b, 0x78, 0x84, 0x12, 0x23, 0x31, 0x30, 0xe1, 0x08, 0x7f, 0x13, 0x12, 0x31, 0xa9, 0x02, 0x27, |
650 | 0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44, 0x04, | 661 | 0xbc, 0x78, 0x84, 0xe6, 0xf9, 0x24, 0x13, 0x12, 0x22, 0xad, 0xe0, 0xff, 0x30, 0xe7, 0x40, 0x54, |
651 | 0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80, 0x39, | 662 | 0x03, 0x60, 0x1e, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x44, |
652 | 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x80, | 663 | 0x04, 0xf0, 0x80, 0x46, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfd, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x80, |
653 | 0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef, 0x54, | 664 | 0x39, 0xe9, 0xb4, 0x03, 0x0d, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xfb, 0xf0, 0xe0, 0x44, 0x01, 0xf0, |
654 | 0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, 0x07, | 665 | 0x80, 0x28, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf7, 0xf0, 0xe0, 0x44, 0x02, 0xf0, 0x80, 0x1b, 0xef, |
655 | 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x17, 0xe0, 0x04, 0xf0, 0xaf, | 666 | 0x54, 0x03, 0x60, 0x14, 0xe9, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x54, 0xdf, 0xf0, 0x80, |
656 | 0x01, 0x12, 0x22, 0x33, 0xfd, 0x12, 0x2f, 0x49, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x75, 0xa8, | 667 | 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x54, 0xdf, 0xf0, 0xc2, 0xb3, 0x90, 0xf9, 0x18, 0xe0, 0x04, 0xf0, |
657 | 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x27, 0x48, 0x02, 0x30, 0xcf, | 668 | 0xaf, 0x01, 0x12, 0x22, 0xee, 0xfd, 0x12, 0x2f, 0xe5, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, 0x75, |
658 | 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, 0xf4, | 669 | 0xa8, 0x40, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x8b, 0x02, 0x28, 0x09, 0x02, 0x31, |
659 | 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, 0x0f, | 670 | 0x8c, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2, 0x08, 0xdf, |
660 | 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, 0x0b, | 671 | 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33, 0xc4, 0x54, |
661 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0x4c, 0xe4, 0x7e, 0x01, 0x93, 0x60, | 672 | 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf, 0xe4, 0x80, |
662 | 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, 0x01, | 673 | 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x2b, 0xa9, 0xe4, 0x7e, 0x01, 0x93, |
663 | 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, 0x93, | 674 | 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93, 0xa3, 0x60, |
664 | 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, 0xc8, | 675 | 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3, 0xfa, 0xe4, |
665 | 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5, 0x22, | 676 | 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xf0, 0xa3, |
666 | 0x12, 0x1d, 0x12, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x2f, 0x77, 0x12, | 677 | 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe, 0xe4, 0xf5, |
667 | 0x1d, 0x12, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5, 0x22, | 678 | 0x22, 0x12, 0x1d, 0xc2, 0xe0, 0xb4, 0x04, 0x0d, 0xe5, 0x22, 0x24, 0x03, 0xff, 0x12, 0x30, 0x13, |
668 | 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1d, 0x53, 0x60, 0x2c, 0x12, 0x2c, 0xb4, | 679 | 0x12, 0x1d, 0xc2, 0xe4, 0xf0, 0x05, 0x22, 0xe5, 0x22, 0xc3, 0x94, 0x02, 0x40, 0xe3, 0xe4, 0xf5, |
669 | 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x91, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, | 680 | 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x94, 0x12, 0x1e, 0x03, 0x60, 0x2c, 0x12, 0x2d, |
670 | 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0x9d, 0x12, 0x1b, 0x1c, 0xe0, 0xa3, 0x30, | 681 | 0x85, 0xef, 0x60, 0x52, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, 0x94, 0x12, 0x1b, 0xcc, 0xe4, |
671 | 0xe6, 0x33, 0x12, 0x1d, 0x12, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, 0xfa, | 682 | 0xf0, 0xa3, 0xf0, 0x75, 0xf0, 0x0a, 0xe5, 0x22, 0x90, 0xfa, 0xa0, 0x12, 0x1b, 0xcc, 0xe0, 0xa3, |
672 | 0x95, 0x12, 0x1d, 0x53, 0x60, 0x16, 0x12, 0x2c, 0xb4, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02, 0xe5, | 683 | 0x30, 0xe6, 0x33, 0x12, 0x1d, 0xc2, 0x74, 0x04, 0xf0, 0x22, 0x75, 0xf0, 0x02, 0xe5, 0x22, 0x90, |
673 | 0x22, 0x90, 0xfa, 0x95, 0x12, 0x1b, 0x1c, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5, 0x22, | 684 | 0xfa, 0x98, 0x12, 0x1e, 0x03, 0x60, 0x16, 0x12, 0x2d, 0x85, 0xef, 0x60, 0x19, 0x75, 0xf0, 0x02, |
674 | 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe, 0xef, | 685 | 0xe5, 0x22, 0x90, 0xfa, 0x98, 0x12, 0x1b, 0xcc, 0xe4, 0xf0, 0xa3, 0xf0, 0x22, 0x05, 0x22, 0xe5, |
675 | 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0, 0x12, | 686 | 0x22, 0xc3, 0x94, 0x02, 0x40, 0x9b, 0x22, 0xe4, 0xff, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xfe, |
676 | 0x1c, 0x11, 0x12, 0x1a, 0x38, 0x0f, 0x12, 0x1c, 0x00, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5, 0x3a, | 687 | 0xef, 0xc3, 0x9e, 0x50, 0x17, 0x74, 0xf0, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xe0, |
677 | 0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5, 0x39, | 688 | 0x12, 0x1c, 0xc1, 0x12, 0x1a, 0xe8, 0x0f, 0x12, 0x1c, 0xb0, 0x80, 0xdd, 0xef, 0xfd, 0xc3, 0xe5, |
678 | 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x84, | 689 | 0x3a, 0x9d, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, 0xd3, 0xe5, 0x3a, 0x94, 0x00, 0xe5, |
679 | 0x12, 0x1d, 0x76, 0x12, 0x19, 0xf2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e, 0x70, | 690 | 0x39, 0x94, 0x00, 0x40, 0x06, 0xe4, 0x90, 0xff, 0x83, 0xf0, 0x22, 0x12, 0x1d, 0xdf, 0x12, 0x1e, |
680 | 0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0x0b, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f, 0xef, | 691 | 0x34, 0x12, 0x1e, 0x26, 0x12, 0x1a, 0xa2, 0x24, 0x6e, 0x60, 0x1e, 0x14, 0x60, 0x1b, 0x24, 0x8e, |
681 | 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x16, 0x12, 0x1d, 0x8b, 0x12, 0x25, 0x39, 0x12, 0x1c, | 692 | 0x70, 0x2d, 0x90, 0x00, 0x01, 0x12, 0x1a, 0xbb, 0xff, 0x24, 0xfc, 0x60, 0x03, 0x04, 0x70, 0x1f, |
682 | 0xd9, 0x12, 0x1a, 0x0b, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, 0x12, 0x31, 0xb1, 0x22, 0x8b, | 693 | 0xef, 0xfd, 0x7c, 0x00, 0x7f, 0x0d, 0x02, 0x11, 0x5e, 0x12, 0x1e, 0x3b, 0x12, 0x25, 0xfa, 0x12, |
683 | 0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2d, 0x82, 0x70, 0x16, | 694 | 0x1d, 0x89, 0x12, 0x1a, 0xbb, 0x60, 0x03, 0x02, 0x32, 0x7a, 0xe4, 0xff, 0x12, 0x32, 0x6e, 0x22, |
684 | 0x12, 0x2d, 0xa1, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0x1b, 0x50, 0xf2, 0x12, 0x29, | 695 | 0x8b, 0x45, 0x8a, 0x46, 0x89, 0x47, 0x8c, 0x48, 0x8d, 0x49, 0xd2, 0x00, 0x12, 0x2e, 0x53, 0x70, |
685 | 0x14, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2d, 0xa1, 0x12, 0x29, 0x14, 0x50, 0xf8, 0xe4, 0xf5, | 696 | 0x16, 0x12, 0x2e, 0x72, 0xe5, 0x48, 0x90, 0xff, 0xf1, 0xf0, 0x12, 0x31, 0xd8, 0x50, 0xf2, 0x12, |
686 | 0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0x04, 0x40, 0x03, | 697 | 0x29, 0xd5, 0x40, 0x0b, 0x7f, 0x18, 0x22, 0x12, 0x2e, 0x72, 0x12, 0x29, 0xd5, 0x50, 0xf8, 0xe4, |
687 | 0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5, 0x46, | 698 | 0xf5, 0x4b, 0xe5, 0x4a, 0x14, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, 0x17, 0x12, 0x29, 0xc5, 0x40, |
688 | 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0x04, 0x40, 0x03, 0x7f, 0x18, | 699 | 0x03, 0x7f, 0x18, 0x22, 0x05, 0x4b, 0x74, 0x01, 0x25, 0x47, 0xf5, 0x47, 0xe4, 0x35, 0x46, 0xf5, |
689 | 0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x19, 0xf2, 0x90, 0xff, 0xf1, | 700 | 0x46, 0x80, 0xdf, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x29, 0xc5, 0x40, 0x03, 0x7f, |
690 | 0xf0, 0x02, 0x31, 0x1b, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0x1b, 0x7b, 0x01, 0x7a, | 701 | 0x18, 0x22, 0x7f, 0x00, 0x22, 0xab, 0x45, 0xaa, 0x46, 0xa9, 0x47, 0x12, 0x1a, 0xa2, 0x90, 0xff, |
691 | 0xfa, 0x79, 0xcc, 0xe4, 0xfd, 0x12, 0x22, 0xa0, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x09, 0x12, | 702 | 0xf1, 0xf0, 0x02, 0x31, 0xd8, 0x90, 0xff, 0xf1, 0xe5, 0x49, 0xf0, 0x02, 0x31, 0xd8, 0x7b, 0x01, |
692 | 0x1a, 0x6c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, | 703 | 0x7a, 0xfa, 0x79, 0xcf, 0xe4, 0xfd, 0x12, 0x23, 0x61, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x09, |
693 | 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x90, 0xff, 0xf7, 0xe5, | 704 | 0x12, 0x1b, 0x1c, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, |
694 | 0x23, 0x12, 0x29, 0x78, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcc, 0xe4, 0xf0, 0xa3, | 705 | 0x12, 0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x90, 0xff, 0xf7, |
695 | 0x74, 0x06, 0x12, 0x29, 0x78, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94, 0xf0, | 706 | 0xe5, 0x23, 0x12, 0x2a, 0x39, 0x90, 0xff, 0xf6, 0xe5, 0x23, 0xf0, 0x90, 0xfa, 0xcf, 0xe4, 0xf0, |
696 | 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, 0x90, | 707 | 0xa3, 0x74, 0x06, 0x12, 0x2a, 0x39, 0xe5, 0x23, 0x30, 0xe0, 0x07, 0x90, 0xff, 0xfc, 0x74, 0x94, |
697 | 0xfa, 0xcc, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1a, 0x82, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, 0x01, | 708 | 0xf0, 0x22, 0x90, 0xff, 0xfc, 0x74, 0x90, 0xf0, 0x22, 0xf0, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x23, |
698 | 0x02, 0x25, 0xd7, 0x90, 0xff, 0x93, 0x74, 0x2a, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, 0x90, | 709 | 0x90, 0xfa, 0xcf, 0xe4, 0x75, 0xf0, 0x01, 0x12, 0x1b, 0x32, 0x85, 0xf0, 0x2e, 0xf5, 0x2d, 0x7d, |
699 | 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9, 0x15, | 710 | 0x01, 0x02, 0x26, 0x98, 0x90, 0xff, 0x93, 0x74, 0x81, 0xf0, 0x90, 0xff, 0xff, 0xe0, 0x60, 0x06, |
700 | 0xf0, 0xa3, 0xf0, 0x12, 0x2a, 0x78, 0x12, 0x16, 0x42, 0x12, 0x2f, 0xcd, 0x7e, 0x07, 0x7f, 0xd0, | 711 | 0x90, 0xff, 0xfc, 0x74, 0x10, 0xf0, 0x90, 0xff, 0x91, 0xe0, 0x44, 0x90, 0xf0, 0xe4, 0x90, 0xf9, |
701 | 0x12, 0x11, 0xe2, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x11, 0xfc, 0xe4, 0x78, 0x77, 0xf6, 0x78, 0x77, | 712 | 0x16, 0xf0, 0xa3, 0xf0, 0x12, 0x2b, 0x39, 0x12, 0x16, 0xc9, 0x12, 0x30, 0x69, 0x7e, 0x07, 0x7f, |
702 | 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77, 0x06, | 713 | 0xd0, 0x12, 0x12, 0x2a, 0x7e, 0x0f, 0x7f, 0xa0, 0x12, 0x12, 0x44, 0xe4, 0x78, 0x77, 0xf6, 0x78, |
703 | 0x80, 0xec, 0x7f, 0x03, 0x12, 0x2e, 0xb3, 0x90, 0xf9, 0x15, 0xe0, 0x20, 0xe4, 0x05, 0x7f, 0x04, | 714 | 0x77, 0xe6, 0xff, 0xc3, 0x94, 0x06, 0x50, 0x0b, 0x74, 0x6e, 0x2f, 0xf8, 0xe4, 0xf6, 0x78, 0x77, |
704 | 0x12, 0x2e, 0xb3, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, 0xe0, | 715 | 0x06, 0x80, 0xec, 0x7f, 0x03, 0x12, 0x30, 0xb2, 0x90, 0xf9, 0x16, 0xe0, 0x20, 0xe4, 0x05, 0x7f, |
705 | 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05, 0x12, | 716 | 0x04, 0x12, 0x30, 0xb2, 0x90, 0xff, 0x9b, 0xe4, 0xf0, 0x90, 0xff, 0x9a, 0xf0, 0x90, 0xff, 0xe8, |
706 | 0x11, 0x66, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c, 0x76, | 717 | 0xe0, 0x54, 0x1f, 0xf0, 0xd2, 0xa8, 0x22, 0x15, 0x65, 0xa8, 0x65, 0xa6, 0x07, 0x30, 0x08, 0x05, |
707 | 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76, 0xff, | 718 | 0x12, 0x11, 0xae, 0x80, 0xf8, 0xd2, 0x08, 0xa8, 0x65, 0xe6, 0xff, 0xb4, 0x03, 0x0f, 0x78, 0x7c, |
708 | 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76, 0x9b, | 719 | 0x76, 0xff, 0x08, 0x76, 0xe0, 0x08, 0x76, 0xff, 0x08, 0x76, 0xa0, 0x80, 0x0d, 0x78, 0x7c, 0x76, |
709 | 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x22, 0x92, 0x7b, 0x01, 0x7a, 0xff, | 720 | 0xff, 0x08, 0x76, 0xe2, 0x08, 0x76, 0xff, 0x08, 0x76, 0xb0, 0x78, 0x80, 0x76, 0xfa, 0x08, 0x76, |
710 | 0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0x31, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08, 0xa4, | 721 | 0x9e, 0xef, 0x24, 0xfd, 0x75, 0xf0, 0x0a, 0xa4, 0xae, 0xf0, 0x12, 0x23, 0x49, 0x7b, 0x01, 0x7a, |
711 | 0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x22, 0x92, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0x31, 0x78, | 722 | 0xff, 0x79, 0x48, 0x78, 0x68, 0x12, 0x1b, 0xe1, 0xa8, 0x65, 0xe6, 0x24, 0xfd, 0x75, 0xf0, 0x08, |
712 | 0x6d, 0xef, 0x12, 0x22, 0x92, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0, 0xe0, | 723 | 0xa4, 0xff, 0xae, 0xf0, 0x78, 0x6a, 0x12, 0x23, 0x49, 0x79, 0x08, 0x78, 0x6b, 0x12, 0x1b, 0xe1, |
713 | 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe3, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcc, 0xe4, | 724 | 0x78, 0x6d, 0xef, 0x12, 0x23, 0x49, 0x05, 0x65, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xab, 0xf0, |
714 | 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x25, 0xd7, 0x7e, 0x00, 0x90, 0xfa, 0xe1, 0xee, 0xf0, | 725 | 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xfa, 0xe6, 0x74, 0x02, 0xf0, 0x7b, 0x01, 0x7a, 0xfa, 0x79, 0xcf, |
715 | 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x52, 0x09, 0x90, 0xf9, | 726 | 0xe4, 0xf5, 0x2d, 0xf5, 0x2e, 0x7d, 0x01, 0x12, 0x26, 0x98, 0x7e, 0x00, 0x90, 0xfa, 0xe4, 0xee, |
716 | 0x15, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe1, 0xe0, 0x70, 0x04, 0xa3, 0xe0, 0x64, | 727 | 0xf0, 0xa3, 0xef, 0xf0, 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcf, 0xe0, 0xb4, 0x52, 0x09, 0x90, |
717 | 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcc, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x15, 0xe0, 0x44, 0x10, | 728 | 0xf9, 0x16, 0xe0, 0x54, 0xef, 0xf0, 0x80, 0x29, 0x90, 0xfa, 0xe4, 0xe0, 0x70, 0x04, 0xa3, 0xe0, |
718 | 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe3, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x15, 0xe0, 0x54, 0xef, 0xf0, | 729 | 0x64, 0x01, 0x70, 0x10, 0x90, 0xfa, 0xcf, 0xe0, 0xb4, 0x10, 0x09, 0x90, 0xf9, 0x16, 0xe0, 0x44, |
719 | 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x12, 0x10, 0x03, 0x78, 0x8a, 0xef, 0xf6, 0x12, | 730 | 0x10, 0xf0, 0x80, 0x0d, 0x90, 0xfa, 0xe6, 0x74, 0x03, 0xf0, 0x90, 0xf9, 0x16, 0xe0, 0x54, 0xef, |
720 | 0x2a, 0x06, 0x12, 0x22, 0x33, 0x30, 0xe0, 0x25, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x7f, 0xf0, 0x78, | 731 | 0xf0, 0x90, 0xff, 0xf0, 0xe0, 0x44, 0x20, 0xf0, 0x22, 0x03, 0x68, 0x01, 0xff, 0x48, 0x03, 0x6b, |
721 | 0x6b, 0x12, 0x1b, 0x28, 0x90, 0x00, 0x02, 0x12, 0x1a, 0x0b, 0x30, 0xe7, 0x09, 0x90, 0x00, 0x02, | 732 | 0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x98, 0x00, 0x00, 0x00, 0x00, 0x44, 0xfa, |
722 | 0xe4, 0x12, 0x1a, 0x4a, 0x80, 0xe9, 0x12, 0x22, 0x07, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x22, 0x33, | 733 | 0x94, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xb2, 0x00, 0x00, 0x42, 0xfa, 0x7e, 0x00, 0x00, 0x42, |
723 | 0x30, 0xe1, 0x1e, 0x12, 0x21, 0xe9, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x31, 0x5c, 0x78, 0x68, 0x12, | 734 | 0xfa, 0x7c, 0x00, 0x00, 0x42, 0xf9, 0x6d, 0xff, 0xff, 0x42, 0xfa, 0x7a, 0x00, 0x00, 0x41, 0xf9, |
724 | 0x1b, 0x28, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0x4a, 0x12, 0x21, 0xe9, 0xe0, 0x44, 0x80, | 735 | 0x66, 0xff, 0x41, 0xf9, 0x1c, 0x19, 0x41, 0xf9, 0x15, 0x00, 0x43, 0xf9, 0x19, 0x0a, 0x32, 0x02, |
725 | 0xf0, 0x12, 0x31, 0xc7, 0xe4, 0xff, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x03, 0x68, 0x01, 0xff, | 736 | 0x41, 0xf9, 0x68, 0x20, 0x41, 0xf9, 0x69, 0x20, 0x41, 0xf9, 0x65, 0x00, 0x41, 0xf9, 0x67, 0x00, |
726 | 0x48, 0x03, 0x6b, 0x01, 0xff, 0x08, 0x02, 0x66, 0x00, 0x00, 0x44, 0xfa, 0x95, 0x00, 0x00, 0x00, | 737 | 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, 0x16, 0x00, 0x00, 0x41, 0xf9, 0x18, 0x00, |
727 | 0x00, 0x44, 0xfa, 0x91, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfa, 0xaf, 0x00, 0x00, 0x42, 0xfa, 0x7b, | 738 | 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, 0x10, 0x4b, 0x78, 0x8a, 0xef, 0xf6, 0x12, |
728 | 0x00, 0x00, 0x42, 0xfa, 0x79, 0x00, 0x00, 0x42, 0xf9, 0x6a, 0xff, 0xff, 0x42, 0xfa, 0x77, 0x00, | 739 | 0x2a, 0xc7, 0x12, 0x22, 0xee, 0x30, 0xe0, 0x29, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x54, 0x7f, |
729 | 0x00, 0x43, 0xf9, 0x18, 0x0a, 0x32, 0x02, 0x41, 0xf9, 0x65, 0x20, 0x41, 0xf9, 0x66, 0x20, 0x41, | 740 | 0xf0, 0x78, 0x6b, 0x12, 0x1b, 0xd8, 0x90, 0x00, 0x02, 0x12, 0x1a, 0xbb, 0x30, 0xe7, 0x09, 0x90, |
730 | 0xf9, 0x63, 0x00, 0x41, 0xf9, 0x64, 0x00, 0x44, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xf9, | 741 | 0x00, 0x02, 0xe4, 0x12, 0x1a, 0xfa, 0x80, 0xe9, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x44, 0x80, |
731 | 0x15, 0x00, 0x00, 0x41, 0xf9, 0x17, 0x00, 0x01, 0x20, 0x00, 0x41, 0xf8, 0x04, 0x00, 0x00, 0x12, | 742 | 0xf0, 0x12, 0x22, 0xee, 0x30, 0xe1, 0x1e, 0x12, 0x22, 0x97, 0xe0, 0x54, 0x7f, 0xf0, 0x12, 0x32, |
732 | 0x10, 0x03, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x30, 0x93, 0x12, 0x30, 0xec, 0x78, 0x85, 0xe6, 0xff, | 743 | 0x19, 0x78, 0x68, 0x12, 0x1b, 0xd8, 0x90, 0x00, 0x02, 0x74, 0x80, 0x12, 0x1a, 0xfa, 0x12, 0x22, |
733 | 0x24, 0x12, 0x12, 0x21, 0xff, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, | 744 | 0x97, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x32, 0x84, 0xe4, 0xff, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, |
734 | 0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80, 0x19, | 745 | 0x12, 0x10, 0x4b, 0x78, 0x85, 0xef, 0xf6, 0x12, 0x31, 0x50, 0x12, 0x31, 0xa9, 0x78, 0x85, 0xe6, |
735 | 0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, 0xf0, | 746 | 0xff, 0x24, 0x13, 0x12, 0x22, 0xad, 0xe0, 0xfe, 0x30, 0xe7, 0x16, 0xef, 0xb4, 0x03, 0x09, 0x90, |
736 | 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x17, 0xe0, 0x14, 0xf0, 0xe0, | 747 | 0xff, 0x9e, 0xe0, 0x54, 0xfa, 0xf0, 0x80, 0x22, 0x90, 0xff, 0x9e, 0xe0, 0x54, 0xf5, 0xf0, 0x80, |
737 | 0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0x86, 0x12, 0x1d, 0x6c, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, | 748 | 0x19, 0xee, 0x54, 0x03, 0x60, 0x14, 0xef, 0xb4, 0x03, 0x09, 0x90, 0xff, 0xa4, 0xe0, 0x44, 0x20, |
738 | 0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00, 0x40, | 749 | 0xf0, 0x80, 0x07, 0x90, 0xff, 0xb4, 0xe0, 0x44, 0x20, 0xf0, 0x90, 0xf9, 0x18, 0xe0, 0x14, 0xf0, |
739 | 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, 0x39, | 750 | 0xe0, 0x70, 0x02, 0xd2, 0xb3, 0x02, 0x10, 0xce, 0x12, 0x1e, 0x1c, 0xe5, 0x3a, 0x64, 0x09, 0x70, |
740 | 0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1d, 0x84, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12, 0x1c, | 751 | 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x48, 0xc3, 0xe5, 0x3a, 0x94, 0x08, 0xe5, 0x39, 0x94, 0x00, |
741 | 0x11, 0x12, 0x19, 0xf2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, 0xed, | 752 | 0x40, 0x11, 0x7f, 0x08, 0xef, 0xe5, 0x3a, 0x94, 0x08, 0xf5, 0x3a, 0xe5, 0x39, 0x94, 0x00, 0xf5, |
742 | 0xf0, 0x0e, 0x12, 0x1c, 0x00, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22, 0x8b, | 753 | 0x39, 0x80, 0x05, 0xaf, 0x3a, 0x12, 0x1e, 0x34, 0xe4, 0xfe, 0xee, 0xc3, 0x9f, 0x50, 0x19, 0x12, |
743 | 0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2d, 0x48, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22, 0xab, | 754 | 0x1c, 0xc1, 0x12, 0x1a, 0xa2, 0xfd, 0x74, 0xf8, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfe, 0xf5, 0x83, |
744 | 0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2d, 0x3c, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x43, 0xe5, 0x5b, | 755 | 0xed, 0xf0, 0x0e, 0x12, 0x1c, 0xb0, 0x80, 0xe2, 0xef, 0x54, 0x7f, 0x90, 0xff, 0x81, 0xf0, 0x22, |
745 | 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x43, 0xe4, 0x90, 0xfa, | 756 | 0x8b, 0x59, 0x8a, 0x5a, 0x89, 0x5b, 0x12, 0x2e, 0x19, 0x70, 0x05, 0xa3, 0x74, 0x08, 0xf0, 0x22, |
746 | 0xbf, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xbe, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f, 0x50, | 757 | 0xab, 0x59, 0xaa, 0x5a, 0xa9, 0x5b, 0x12, 0x2e, 0x0d, 0x90, 0xfa, 0xc9, 0x12, 0x1b, 0xf3, 0xe5, |
747 | 0x12, 0x12, 0x2d, 0x1a, 0xff, 0x12, 0x2d, 0x23, 0x12, 0x2d, 0x36, 0x78, 0x8b, 0x06, 0x12, 0x2d, | 758 | 0x5b, 0x24, 0x03, 0xf9, 0xe4, 0x35, 0x5a, 0xfa, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0xf3, 0xe4, 0x90, |
748 | 0x32, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x31, 0x4d, 0xe4, 0x93, 0xff, 0x78, 0x74, | 759 | 0xfa, 0xc2, 0xf0, 0x78, 0x8b, 0xf6, 0x90, 0xfa, 0xc1, 0xe0, 0xff, 0x78, 0x8b, 0xe6, 0xc3, 0x9f, |
749 | 0xf6, 0x54, 0x0f, 0x12, 0x1c, 0xf8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c, 0x29, | 760 | 0x50, 0x12, 0x12, 0x2d, 0xeb, 0xff, 0x12, 0x2d, 0xf4, 0x12, 0x2e, 0x07, 0x78, 0x8b, 0x06, 0x12, |
750 | 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6, 0xee, | 761 | 0x2e, 0x03, 0x80, 0xe2, 0x22, 0xad, 0x07, 0xac, 0x06, 0x90, 0x32, 0x0a, 0xe4, 0x93, 0xff, 0x78, |
751 | 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f, 0x00, | 762 | 0x74, 0xf6, 0x54, 0x0f, 0x12, 0x1d, 0xa8, 0xe0, 0x08, 0x76, 0x00, 0x08, 0xf6, 0x18, 0x12, 0x1c, |
752 | 0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed, 0xf0, | 763 | 0xd9, 0xc3, 0x33, 0xce, 0x33, 0xce, 0xd8, 0xf9, 0xff, 0x78, 0x75, 0xee, 0xf6, 0x08, 0xef, 0xf6, |
753 | 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x90, | 764 | 0xee, 0x44, 0xf8, 0x18, 0xf6, 0xef, 0x08, 0xf6, 0x90, 0xff, 0x7a, 0xe0, 0x20, 0xe7, 0x03, 0x7f, |
754 | 0x00, 0x03, 0x12, 0x1a, 0x0b, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc6, 0x12, 0x1b, 0x3a, | 765 | 0x00, 0x22, 0x78, 0x75, 0xe6, 0xfe, 0x08, 0xe6, 0xf5, 0x82, 0x8e, 0x83, 0xec, 0xf0, 0xa3, 0xed, |
755 | 0x02, 0x19, 0xf2, 0x90, 0xfa, 0xc0, 0x12, 0x1b, 0x3a, 0xef, 0x12, 0x1a, 0x38, 0x90, 0xfa, 0xc7, | 766 | 0xf0, 0x90, 0xff, 0x7a, 0x74, 0x02, 0xf0, 0x7f, 0x01, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, |
756 | 0xe4, 0x22, 0x90, 0xfa, 0xc1, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1a, 0x6c, 0x90, 0x00, 0x08, 0x12, | 767 | 0x90, 0x00, 0x03, 0x12, 0x1a, 0xbb, 0x54, 0xf0, 0x24, 0xa0, 0x22, 0x90, 0xfa, 0xc9, 0x12, 0x1b, |
757 | 0x1a, 0x98, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0x0b, 0x90, 0xfa, | 768 | 0xea, 0x02, 0x1a, 0xa2, 0x90, 0xfa, 0xc3, 0x12, 0x1b, 0xea, 0xef, 0x12, 0x1a, 0xe8, 0x90, 0xfa, |
758 | 0xbe, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xda, 0xe0, 0xff, 0x7e, | 769 | 0xca, 0xe4, 0x22, 0x90, 0xfa, 0xc4, 0xe4, 0x75, 0xf0, 0x01, 0x02, 0x1b, 0x1c, 0x90, 0x00, 0x08, |
759 | 0x00, 0xc3, 0x90, 0xfa, 0xd4, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd3, 0xe0, 0x9e, 0xf0, 0x90, 0xfa, | 770 | 0x12, 0x1b, 0x48, 0xaa, 0xf0, 0xf9, 0x7b, 0x01, 0x22, 0x90, 0x00, 0x05, 0x12, 0x1a, 0xbb, 0x90, |
760 | 0xd5, 0xee, 0x8f, 0xf0, 0x12, 0x1a, 0x6c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50, 0xf5, | 771 | 0xfa, 0xc1, 0xf0, 0x22, 0xab, 0x56, 0xaa, 0x57, 0xa9, 0x58, 0x22, 0x90, 0xfa, 0xdd, 0xe0, 0xff, |
761 | 0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa, 0xe3, | 772 | 0x7e, 0x00, 0xc3, 0x90, 0xfa, 0xd7, 0xe0, 0x9f, 0xf0, 0x90, 0xfa, 0xd6, 0xe0, 0x9e, 0xf0, 0x90, |
762 | 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02, 0x1a, | 773 | 0xfa, 0xd8, 0xee, 0x8f, 0xf0, 0x12, 0x1b, 0x1c, 0xef, 0x25, 0x51, 0xf5, 0x51, 0xee, 0x35, 0x50, |
763 | 0x38, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64, 0xb4, | 774 | 0xf5, 0x50, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x54, 0xfd, 0xf0, 0x90, 0xfa, |
764 | 0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0x32, 0x7f, 0x02, 0x02, 0x31, 0x32, 0xaf, 0x64, 0x12, 0x2a, | 775 | 0xe6, 0xe0, 0x64, 0x03, 0x22, 0x90, 0xff, 0xf2, 0xe0, 0xab, 0x29, 0xaa, 0x2a, 0xa9, 0x2b, 0x02, |
765 | 0x06, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1c, 0x83, 0xe0, | 776 | 0x1a, 0xe8, 0x90, 0xff, 0xf3, 0x74, 0xa0, 0xf0, 0x22, 0x8f, 0x64, 0xed, 0x70, 0x0f, 0xe5, 0x64, |
766 | 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12, 0x31, | 777 | 0xb4, 0x03, 0x05, 0x7f, 0x01, 0x02, 0x31, 0xef, 0x7f, 0x02, 0x02, 0x31, 0xef, 0xaf, 0x64, 0x12, |
767 | 0x32, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0x32, 0x30, 0x09, 0x07, 0x12, 0x1c, 0x83, 0xe0, 0x44, | 778 | 0x2a, 0xc7, 0x74, 0x6e, 0x25, 0x64, 0xf8, 0xe6, 0x30, 0xe2, 0x0b, 0xd2, 0x09, 0x12, 0x1d, 0x33, |
768 | 0x80, 0xf0, 0x12, 0x31, 0xc7, 0x22, 0x12, 0x10, 0x03, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60, 0xf0, | 779 | 0xe0, 0x54, 0x7f, 0xf0, 0x80, 0x02, 0xc2, 0x09, 0xe5, 0x64, 0xb4, 0x03, 0x07, 0x7f, 0x81, 0x12, |
769 | 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7, 0x13, | 780 | 0x31, 0xef, 0x80, 0x05, 0x7f, 0x82, 0x12, 0x31, 0xef, 0x30, 0x09, 0x07, 0x12, 0x1d, 0x33, 0xe0, |
770 | 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x01, | 781 | 0x44, 0x80, 0xf0, 0x12, 0x32, 0x84, 0x22, 0x12, 0x10, 0x4b, 0x90, 0xff, 0xfd, 0xe0, 0x44, 0x60, |
771 | 0xf0, 0x80, 0x0d, 0x12, 0x1d, 0x2f, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe, 0xf0, | 782 | 0xf0, 0xd2, 0x01, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x02, 0xf0, 0x90, 0xff, 0x00, 0xe0, 0x30, 0xe7, |
772 | 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xb0, 0x12, 0x1d, 0x37, 0x02, 0x10, 0x86, | 783 | 0x13, 0x90, 0xff, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x35, 0x80, 0x90, 0xff, 0xfc, 0xe0, 0x44, |
773 | 0x12, 0x10, 0x03, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0x06, 0x90, 0xf9, 0x67, 0x12, | 784 | 0x01, 0xf0, 0x80, 0x0d, 0x12, 0x1d, 0xdf, 0x53, 0x35, 0x7f, 0x90, 0xff, 0xfc, 0xe0, 0x54, 0xfe, |
774 | 0x1b, 0x3a, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe, 0x08, | 785 | 0xf0, 0x90, 0xff, 0x81, 0xe0, 0x44, 0x80, 0xf0, 0x12, 0x02, 0xde, 0x12, 0x1d, 0xe7, 0x02, 0x10, |
775 | 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0x25, 0x12, 0x31, 0xc7, | 786 | 0xce, 0x12, 0x10, 0x4b, 0x78, 0x89, 0xef, 0xf6, 0xd2, 0x00, 0x12, 0x2a, 0xc7, 0x90, 0xf9, 0x6a, |
776 | 0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x3f, 0x12, 0x30, 0xec, 0x02, 0x10, 0x86, 0x8f, 0x63, 0x12, | 787 | 0x12, 0x1b, 0xea, 0xe9, 0x24, 0x03, 0xf9, 0xe4, 0x3a, 0xfa, 0xc0, 0x02, 0x78, 0x80, 0xe6, 0xfe, |
777 | 0x2a, 0x06, 0x12, 0x22, 0x07, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x21, 0xf3, | 788 | 0x08, 0xe6, 0xaa, 0x06, 0xf8, 0xac, 0x02, 0x7d, 0x01, 0xd0, 0x02, 0x12, 0x22, 0xd3, 0x12, 0x32, |
778 | 0xe0, 0x54, 0x3f, 0xf0, 0x08, 0xe6, 0xfe, 0x08, 0xe6, 0x8e, 0x83, 0x24, 0x0b, 0x12, 0x21, 0xf3, | 789 | 0x84, 0x78, 0x89, 0xe6, 0xff, 0x12, 0x13, 0x87, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, 0x8f, 0x63, |
779 | 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, | 790 | 0x12, 0x2a, 0xc7, 0x78, 0x7c, 0x12, 0x22, 0xb7, 0xe0, 0x54, 0x3f, 0xf0, 0xe5, 0x82, 0x24, 0x04, |
780 | 0x7f, 0x00, 0x22, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, 0x78, 0x7e, 0x12, | 791 | 0x12, 0x22, 0xa1, 0xe0, 0x54, 0x3f, 0xf0, 0x12, 0x23, 0x41, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0, |
781 | 0x21, 0xeb, 0xe0, 0x44, 0x01, 0xf0, 0x12, 0x22, 0x4a, 0x12, 0x21, 0xef, 0xe0, 0x20, 0xe0, 0xf6, | 792 | 0x54, 0xf8, 0xf0, 0x12, 0x32, 0x84, 0x74, 0x6e, 0x25, 0x63, 0xf8, 0x74, 0xfb, 0x56, 0xf6, 0x7f, |
782 | 0xef, 0x24, 0x0b, 0xf5, 0x82, 0xe4, 0x3e, 0xf5, 0x83, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x31, 0xc7, | 793 | 0x00, 0x22, 0x12, 0x10, 0x4b, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xfa, 0x24, 0x06, 0x12, 0x22, 0x9f, |
783 | 0xaf, 0x23, 0x12, 0x13, 0x3f, 0x22, 0x12, 0x10, 0x03, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x4a, 0x24, | 794 | 0xe0, 0xfd, 0x12, 0x22, 0xe8, 0x90, 0x00, 0x03, 0x12, 0x23, 0x02, 0x24, 0x05, 0x12, 0x22, 0xa1, |
784 | 0x06, 0x12, 0x21, 0xf1, 0xe0, 0xfd, 0x12, 0x22, 0x2d, 0x90, 0x00, 0x03, 0x12, 0x22, 0x52, 0x24, | 795 | 0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0xfa, 0x12, 0x32, 0x84, 0x7d, 0x02, 0xe4, 0xff, 0x12, 0x2f, |
785 | 0x05, 0x12, 0x21, 0xf3, 0xe0, 0x90, 0x00, 0x04, 0x12, 0x1a, 0x4a, 0x12, 0x31, 0xc7, 0x7d, 0x02, | 796 | 0xb4, 0x02, 0x10, 0xce, 0xae, 0x05, 0x12, 0x1d, 0x8e, 0xef, 0x12, 0x1a, 0xfa, 0x0e, 0x0e, 0x0e, |
786 | 0xe4, 0xff, 0x12, 0x2f, 0x18, 0x02, 0x10, 0x86, 0xae, 0x05, 0x12, 0x1c, 0xde, 0xef, 0x12, 0x1a, | 797 | 0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, 0xd3, 0x94, 0x08, 0x74, |
787 | 0x4a, 0x0e, 0x0e, 0x0e, 0xee, 0xd3, 0x95, 0x3c, 0xe4, 0x95, 0x3b, 0x40, 0x02, 0xae, 0x3c, 0xee, | 798 | 0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, 0x12, 0x1a, 0xfa, 0xaf, |
788 | 0xd3, 0x94, 0x08, 0x74, 0x80, 0x94, 0x81, 0x40, 0x0a, 0x7e, 0x03, 0x90, 0x00, 0x02, 0x74, 0x02, | 799 | 0x06, 0x12, 0x32, 0x6e, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, 0x60, 0x03, 0x7f, 0x10, |
789 | 0x12, 0x1a, 0x4a, 0xaf, 0x06, 0x12, 0x31, 0xb1, 0x22, 0xae, 0x07, 0xed, 0x54, 0x03, 0x64, 0x01, | 800 | 0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, 0x74, 0x6e, 0x2e, 0xf8, |
790 | 0x60, 0x03, 0x7f, 0x10, 0x22, 0xed, 0x54, 0x7c, 0xc3, 0x94, 0x04, 0x50, 0x03, 0x7f, 0x0b, 0x22, | 801 | 0x74, 0x02, 0x46, 0xf6, 0x74, 0x99, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, 0xf5, 0x83, 0xed, 0xf0, |
791 | 0x74, 0x6e, 0x2e, 0xf8, 0x74, 0x02, 0x46, 0xf6, 0x74, 0x96, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0xfa, | 802 | 0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, 0x7c, 0xff, 0x7d, 0xe2, |
792 | 0xf5, 0x83, 0xed, 0xf0, 0x7f, 0x00, 0x22, 0xbf, 0x03, 0x06, 0x7c, 0xff, 0x7d, 0xe0, 0x80, 0x04, | 803 | 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, 0x12, 0x22, 0xa1, 0xe0, |
793 | 0x7c, 0xff, 0x7d, 0xe2, 0x8d, 0x82, 0x8c, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0xe5, 0x82, 0x24, 0x04, | 804 | 0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, 0x00, 0x22, 0x12, 0x10, |
794 | 0x12, 0x21, 0xf3, 0xe0, 0x44, 0x80, 0xf0, 0x74, 0x6e, 0x2f, 0xf8, 0x74, 0x04, 0x46, 0xf6, 0x7f, | 805 | 0x4b, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x16, 0x90, 0xff, 0x83, |
795 | 0x00, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, | 806 | 0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, 0x40, 0x05, 0x12, 0x28, |
796 | 0x16, 0x90, 0xff, 0x83, 0xe0, 0x54, 0x0f, 0xff, 0xc3, 0xe5, 0x3a, 0x9f, 0xe5, 0x39, 0x94, 0x00, | 807 | 0xd7, 0x80, 0x03, 0x12, 0x32, 0x7a, 0x02, 0x10, 0xce, 0x90, 0xff, 0xfc, 0xe0, 0x20, 0xe7, 0x1f, |
797 | 0x40, 0x05, 0x12, 0x28, 0x16, 0x80, 0x03, 0x12, 0x31, 0xbd, 0x02, 0x10, 0x86, 0x90, 0xff, 0xfc, | 808 | 0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, 0x7f, 0x00, 0xef, 0x1f, |
798 | 0xe0, 0x20, 0xe7, 0x1f, 0xc2, 0xaf, 0x7d, 0xff, 0xac, 0x05, 0x1d, 0xec, 0x60, 0x15, 0x7e, 0x04, | 809 | 0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, 0xf0, 0x80, 0xef, 0x22, |
799 | 0x7f, 0x00, 0xef, 0x1f, 0xaa, 0x06, 0x70, 0x01, 0x1e, 0x4a, 0x60, 0xec, 0x90, 0xff, 0x92, 0xe4, | 810 | 0x12, 0x10, 0x4b, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, 0x12, 0x30, 0xe1, 0x0f, |
800 | 0xf0, 0x80, 0xef, 0x22, 0x12, 0x10, 0x03, 0x78, 0x66, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x30, 0xe0, | 811 | 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x61, 0x12, 0x1d, 0xf6, 0x02, |
801 | 0x12, 0x30, 0xe1, 0x0f, 0x90, 0xff, 0xfc, 0xe0, 0x44, 0x20, 0xf0, 0x7f, 0x04, 0x12, 0x12, 0x19, | 812 | 0x10, 0xce, 0x8f, 0x23, 0xc2, 0x08, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xc0, 0x78, 0x7e, 0x12, 0x23, |
802 | 0x12, 0x1d, 0x46, 0x02, 0x10, 0x86, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, | 813 | 0x42, 0x24, 0x0b, 0x12, 0x22, 0xa1, 0xe0, 0x54, 0xf8, 0xf0, 0x12, 0x32, 0x84, 0xaf, 0x23, 0x12, |
803 | 0x70, 0x02, 0x15, 0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, | 814 | 0x13, 0x87, 0x22, 0x8e, 0x5f, 0x8f, 0x60, 0xe5, 0x60, 0x15, 0x60, 0xae, 0x5f, 0x70, 0x02, 0x15, |
804 | 0x12, 0x0f, 0xdc, 0x80, 0xe5, 0x22, 0x11, 0x94, 0x2d, 0xf6, 0x23, 0xef, 0x31, 0xa3, 0x2f, 0xf4, | 815 | 0x5f, 0xd3, 0x94, 0x00, 0xee, 0x94, 0x00, 0x40, 0x09, 0x7e, 0x07, 0x7f, 0xd0, 0x12, 0x10, 0x24, |
805 | 0x2f, 0xa2, 0x30, 0xb2, 0x2e, 0xe6, 0x26, 0x6d, 0x2b, 0xaf, 0x30, 0x55, 0x30, 0x74, 0x1d, 0xb4, | 816 | 0x80, 0xe5, 0x22, 0x11, 0xdc, 0x2e, 0xc7, 0x24, 0xb0, 0x32, 0x60, 0x30, 0x90, 0x30, 0x3e, 0x31, |
806 | 0x2e, 0x40, 0x2a, 0xe8, 0x0e, 0x12, 0x10, 0x03, 0x78, 0x86, 0x12, 0x22, 0x82, 0x20, 0xe1, 0x07, | 817 | 0x6f, 0x2f, 0x82, 0x27, 0x2e, 0x2c, 0x80, 0x31, 0x12, 0x31, 0x31, 0x1e, 0x64, 0x2f, 0x11, 0x2c, |
807 | 0x7f, 0x12, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x23, 0x49, 0x12, 0x30, | 818 | 0x18, 0x0e, 0x12, 0x10, 0x4b, 0x78, 0x86, 0x12, 0x23, 0x31, 0x20, 0xe1, 0x07, 0x7f, 0x12, 0x12, |
808 | 0xec, 0x02, 0x10, 0x86, 0x12, 0x10, 0x03, 0x78, 0x87, 0x12, 0x22, 0x82, 0x20, 0xe2, 0x07, 0x7f, | 819 | 0x31, 0xa9, 0x80, 0x0a, 0x78, 0x86, 0xe6, 0xff, 0x12, 0x24, 0x0a, 0x12, 0x31, 0xa9, 0x02, 0x10, |
809 | 0x11, 0x12, 0x30, 0xec, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2e, 0x7d, 0x12, 0x30, 0xec, | 820 | 0xce, 0x12, 0x10, 0x4b, 0x78, 0x87, 0x12, 0x23, 0x31, 0x20, 0xe2, 0x07, 0x7f, 0x11, 0x12, 0x31, |
810 | 0x02, 0x10, 0x86, 0x8f, 0x61, 0x12, 0x2e, 0x7d, 0xaf, 0x61, 0x12, 0x2a, 0x06, 0x12, 0x22, 0x12, | 821 | 0xa9, 0x80, 0x0a, 0x78, 0x87, 0xe6, 0xff, 0x12, 0x2f, 0x4e, 0x12, 0x31, 0xa9, 0x02, 0x10, 0xce, |
811 | 0x12, 0x31, 0xc7, 0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, | 822 | 0x8f, 0x61, 0x12, 0x2f, 0x4e, 0xaf, 0x61, 0x12, 0x2a, 0xc7, 0x12, 0x22, 0xc0, 0x12, 0x32, 0x84, |
812 | 0x3f, 0x22, 0x12, 0x10, 0x03, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, | 823 | 0x74, 0x6e, 0x25, 0x61, 0xf8, 0x74, 0xfd, 0x56, 0xf6, 0xaf, 0x61, 0x12, 0x13, 0x87, 0x22, 0x12, |
813 | 0x05, 0x12, 0x2c, 0x07, 0x80, 0x06, 0x12, 0x1d, 0x64, 0x12, 0x1d, 0x6c, 0x02, 0x10, 0x86, 0x12, | 824 | 0x10, 0x4b, 0xe5, 0x3a, 0x64, 0x09, 0x70, 0x04, 0xe5, 0x39, 0x64, 0x01, 0x60, 0x05, 0x12, 0x2c, |
814 | 0x29, 0x93, 0x12, 0x12, 0xbb, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, | 825 | 0xd8, 0x80, 0x06, 0x12, 0x1e, 0x14, 0x12, 0x1e, 0x1c, 0x02, 0x10, 0xce, 0x12, 0x2a, 0x54, 0x12, |
815 | 0x58, 0x12, 0x29, 0x1d, 0x12, 0x12, 0xf7, 0x12, 0x11, 0x74, 0x80, 0xe3, 0x12, 0x1c, 0xde, 0xef, | 826 | 0x13, 0x03, 0x90, 0xf8, 0x04, 0xe0, 0xff, 0x60, 0x05, 0x7d, 0x01, 0x12, 0x12, 0xa0, 0x12, 0x29, |
816 | 0x12, 0x1a, 0x4a, 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x31, 0xbd, 0xe4, 0xff, | 827 | 0xde, 0x12, 0x13, 0x3f, 0x12, 0x11, 0xbc, 0x80, 0xe3, 0x12, 0x1d, 0x8e, 0xef, 0x12, 0x1a, 0xfa, |
817 | 0x12, 0x31, 0xb1, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, | 828 | 0xe4, 0xf5, 0x33, 0xf5, 0x34, 0xef, 0x60, 0x03, 0x02, 0x32, 0x7a, 0xe4, 0xff, 0x12, 0x32, 0x6e, |
818 | 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, | 829 | 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0xa0, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, |
819 | 0x54, 0x28, 0x60, 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, | 830 | 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0x90, 0xff, 0xf0, 0xe0, 0xff, 0x54, 0x28, 0x60, |
820 | 0xd3, 0x22, 0xef, 0x30, 0xe7, 0x08, 0x12, 0x1c, 0x95, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, | 831 | 0xf7, 0xef, 0x30, 0xe5, 0x08, 0x90, 0xff, 0xf0, 0x44, 0x20, 0xf0, 0xc3, 0x22, 0xd3, 0x22, 0xef, |
821 | 0x1c, 0xe8, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, | 832 | 0x30, 0xe7, 0x08, 0x12, 0x1d, 0x45, 0xe0, 0x54, 0xdf, 0xf0, 0x22, 0xef, 0x12, 0x1d, 0x98, 0xe0, |
822 | 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, | 833 | 0x54, 0xdf, 0xf0, 0x22, 0x81, 0x01, 0x82, 0x02, 0x83, 0x03, 0x87, 0x40, 0x00, 0x40, 0x00, 0x40, |
823 | 0x09, 0xa3, 0xa3, 0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, | 834 | 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x08, 0x00, 0x78, 0x7e, 0x12, 0x22, 0xb7, 0xa3, 0xa3, |
824 | 0x3b, 0x39, 0x85, 0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, | 835 | 0xe0, 0xff, 0x30, 0xe7, 0x06, 0x54, 0x7f, 0xf0, 0x44, 0x80, 0xf0, 0x22, 0x85, 0x3b, 0x39, 0x85, |
825 | 0xf0, 0x22, 0xe4, 0xfe, 0xee, 0x90, 0x31, 0x47, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, | 836 | 0x3c, 0x3a, 0x90, 0xff, 0x82, 0xe0, 0x54, 0xf7, 0xf0, 0xa3, 0xe0, 0x54, 0x7f, 0xf0, 0x22, 0xe4, |
826 | 0x07, 0xf2, 0xc3, 0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x10, 0x0a, 0x02, 0x00, 0x00, | 837 | 0xfe, 0xee, 0x90, 0x32, 0x04, 0x93, 0xb5, 0x07, 0x02, 0xd3, 0x22, 0x0e, 0xbe, 0x07, 0xf2, 0xc3, |
827 | 0x00, 0x00, 0x00, 0x12, 0x10, 0x03, 0x7f, 0x02, 0x12, 0x10, 0x92, 0x12, 0x1d, 0x46, 0x02, 0x10, | 838 | 0x22, 0x00, 0x08, 0x18, 0x28, 0x38, 0x01, 0x81, 0x90, 0x0a, 0x02, 0x00, 0x00, 0x11, 0x13, 0x00, |
828 | 0x86, 0x75, 0x39, 0x00, 0x8f, 0x3a, 0x12, 0x1c, 0x30, 0x12, 0x2c, 0x07, 0x22, 0x12, 0x1d, 0x6c, | 839 | 0x12, 0x10, 0x4b, 0x7f, 0x02, 0x12, 0x10, 0xda, 0x12, 0x1d, 0xf6, 0x02, 0x10, 0xce, 0x75, 0x39, |
829 | 0x12, 0x1d, 0x2f, 0x12, 0x1d, 0x64, 0x22, 0xc2, 0x08, 0x22, | 840 | 0x00, 0x8f, 0x3a, 0x12, 0x1c, 0xe0, 0x12, 0x2c, 0xd8, 0x22, 0x12, 0x1e, 0x1c, 0x12, 0x1d, 0xdf, |
841 | 0x12, 0x1e, 0x14, 0x22, 0xc2, 0x08, 0x22, | ||
830 | }; | 842 | }; |
831 | 843 | ||
832 | #undef IMAGE_VERSION_NAME | 844 | #undef IMAGE_VERSION_NAME |
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 544098d2b775..0d3903691e8c 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -48,7 +48,7 @@ | |||
48 | /* | 48 | /* |
49 | * Version Information | 49 | * Version Information |
50 | */ | 50 | */ |
51 | #define DRIVER_VERSION "v0.7" | 51 | #define DRIVER_VERSION "v0.7mode043006" |
52 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli" | 52 | #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com> and David Iacovelli" |
53 | #define DRIVER_DESC "Edgeport USB Serial Driver" | 53 | #define DRIVER_DESC "Edgeport USB Serial Driver" |
54 | 54 | ||
@@ -173,8 +173,12 @@ static struct usb_device_id edgeport_2port_id_table [] = { | |||
173 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) }, | 173 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_221C) }, |
174 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, | 174 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, |
175 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) }, | 175 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) }, |
176 | // The 4-port shows up as two 2-port devices | 176 | /* The 4, 8 and 16 port devices show up as multiple 2 port devices */ |
177 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, | 177 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, |
178 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) }, | ||
179 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) }, | ||
180 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) }, | ||
181 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) }, | ||
178 | { } | 182 | { } |
179 | }; | 183 | }; |
180 | 184 | ||
@@ -209,6 +213,10 @@ static struct usb_device_id id_table_combined [] = { | |||
209 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, | 213 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_22C) }, |
210 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) }, | 214 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_21C) }, |
211 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, | 215 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_4S) }, |
216 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8) }, | ||
217 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_8S) }, | ||
218 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416) }, | ||
219 | { USB_DEVICE(USB_VENDOR_ID_ION, ION_DEVICE_ID_TI_EDGEPORT_416B) }, | ||
212 | { } | 220 | { } |
213 | }; | 221 | }; |
214 | 222 | ||
@@ -231,6 +239,7 @@ static int TIStayInBootMode = 0; | |||
231 | static int low_latency = EDGE_LOW_LATENCY; | 239 | static int low_latency = EDGE_LOW_LATENCY; |
232 | static int closing_wait = EDGE_CLOSING_WAIT; | 240 | static int closing_wait = EDGE_CLOSING_WAIT; |
233 | static int ignore_cpu_rev = 0; | 241 | static int ignore_cpu_rev = 0; |
242 | static int default_uart_mode = 0; /* RS232 */ | ||
234 | 243 | ||
235 | 244 | ||
236 | static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length); | 245 | static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length); |
@@ -241,6 +250,10 @@ static int restart_read(struct edgeport_port *edge_port); | |||
241 | static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); | 250 | static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); |
242 | static void edge_send(struct usb_serial_port *port); | 251 | static void edge_send(struct usb_serial_port *port); |
243 | 252 | ||
253 | /* sysfs attributes */ | ||
254 | static int edge_create_sysfs_attrs(struct usb_serial_port *port); | ||
255 | static int edge_remove_sysfs_attrs(struct usb_serial_port *port); | ||
256 | |||
244 | /* circular buffer */ | 257 | /* circular buffer */ |
245 | static struct edge_buf *edge_buf_alloc(unsigned int size); | 258 | static struct edge_buf *edge_buf_alloc(unsigned int size); |
246 | static void edge_buf_free(struct edge_buf *eb); | 259 | static void edge_buf_free(struct edge_buf *eb); |
@@ -1706,13 +1719,14 @@ static void edge_interrupt_callback (struct urb *urb) | |||
1706 | int length = urb->actual_length; | 1719 | int length = urb->actual_length; |
1707 | int port_number; | 1720 | int port_number; |
1708 | int function; | 1721 | int function; |
1709 | int status; | 1722 | int retval; |
1710 | __u8 lsr; | 1723 | __u8 lsr; |
1711 | __u8 msr; | 1724 | __u8 msr; |
1725 | int status = urb->status; | ||
1712 | 1726 | ||
1713 | dbg("%s", __FUNCTION__); | 1727 | dbg("%s", __FUNCTION__); |
1714 | 1728 | ||
1715 | switch (urb->status) { | 1729 | switch (status) { |
1716 | case 0: | 1730 | case 0: |
1717 | /* success */ | 1731 | /* success */ |
1718 | break; | 1732 | break; |
@@ -1720,10 +1734,12 @@ static void edge_interrupt_callback (struct urb *urb) | |||
1720 | case -ENOENT: | 1734 | case -ENOENT: |
1721 | case -ESHUTDOWN: | 1735 | case -ESHUTDOWN: |
1722 | /* this urb is terminated, clean up */ | 1736 | /* this urb is terminated, clean up */ |
1723 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 1737 | dbg("%s - urb shutting down with status: %d", |
1738 | __FUNCTION__, status); | ||
1724 | return; | 1739 | return; |
1725 | default: | 1740 | default: |
1726 | dev_err(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __FUNCTION__, urb->status); | 1741 | dev_err(&urb->dev->dev, "%s - nonzero urb status received: " |
1742 | "%d\n", __FUNCTION__, status); | ||
1727 | goto exit; | 1743 | goto exit; |
1728 | } | 1744 | } |
1729 | 1745 | ||
@@ -1781,10 +1797,10 @@ static void edge_interrupt_callback (struct urb *urb) | |||
1781 | } | 1797 | } |
1782 | 1798 | ||
1783 | exit: | 1799 | exit: |
1784 | status = usb_submit_urb (urb, GFP_ATOMIC); | 1800 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
1785 | if (status) | 1801 | if (retval) |
1786 | dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", | 1802 | dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", |
1787 | __FUNCTION__, status); | 1803 | __FUNCTION__, retval); |
1788 | } | 1804 | } |
1789 | 1805 | ||
1790 | static void edge_bulk_in_callback (struct urb *urb) | 1806 | static void edge_bulk_in_callback (struct urb *urb) |
@@ -1792,12 +1808,13 @@ static void edge_bulk_in_callback (struct urb *urb) | |||
1792 | struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; | 1808 | struct edgeport_port *edge_port = (struct edgeport_port *)urb->context; |
1793 | unsigned char *data = urb->transfer_buffer; | 1809 | unsigned char *data = urb->transfer_buffer; |
1794 | struct tty_struct *tty; | 1810 | struct tty_struct *tty; |
1795 | int status = 0; | 1811 | int retval = 0; |
1796 | int port_number; | 1812 | int port_number; |
1813 | int status = urb->status; | ||
1797 | 1814 | ||
1798 | dbg("%s", __FUNCTION__); | 1815 | dbg("%s", __FUNCTION__); |
1799 | 1816 | ||
1800 | switch (urb->status) { | 1817 | switch (status) { |
1801 | case 0: | 1818 | case 0: |
1802 | /* success */ | 1819 | /* success */ |
1803 | break; | 1820 | break; |
@@ -1805,17 +1822,18 @@ static void edge_bulk_in_callback (struct urb *urb) | |||
1805 | case -ENOENT: | 1822 | case -ENOENT: |
1806 | case -ESHUTDOWN: | 1823 | case -ESHUTDOWN: |
1807 | /* this urb is terminated, clean up */ | 1824 | /* this urb is terminated, clean up */ |
1808 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 1825 | dbg("%s - urb shutting down with status: %d", |
1826 | __FUNCTION__, status); | ||
1809 | return; | 1827 | return; |
1810 | default: | 1828 | default: |
1811 | dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n", | 1829 | dev_err (&urb->dev->dev,"%s - nonzero read bulk status received: %d\n", |
1812 | __FUNCTION__, urb->status ); | 1830 | __FUNCTION__, status); |
1813 | } | 1831 | } |
1814 | 1832 | ||
1815 | if (urb->status == -EPIPE) | 1833 | if (status == -EPIPE) |
1816 | goto exit; | 1834 | goto exit; |
1817 | 1835 | ||
1818 | if (urb->status) { | 1836 | if (status) { |
1819 | dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__); | 1837 | dev_err(&urb->dev->dev,"%s - stopping read!\n", __FUNCTION__); |
1820 | return; | 1838 | return; |
1821 | } | 1839 | } |
@@ -1849,14 +1867,14 @@ exit: | |||
1849 | spin_lock(&edge_port->ep_lock); | 1867 | spin_lock(&edge_port->ep_lock); |
1850 | if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) { | 1868 | if (edge_port->ep_read_urb_state == EDGE_READ_URB_RUNNING) { |
1851 | urb->dev = edge_port->port->serial->dev; | 1869 | urb->dev = edge_port->port->serial->dev; |
1852 | status = usb_submit_urb(urb, GFP_ATOMIC); | 1870 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
1853 | } else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) { | 1871 | } else if (edge_port->ep_read_urb_state == EDGE_READ_URB_STOPPING) { |
1854 | edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED; | 1872 | edge_port->ep_read_urb_state = EDGE_READ_URB_STOPPED; |
1855 | } | 1873 | } |
1856 | spin_unlock(&edge_port->ep_lock); | 1874 | spin_unlock(&edge_port->ep_lock); |
1857 | if (status) | 1875 | if (retval) |
1858 | dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", | 1876 | dev_err (&urb->dev->dev, "%s - usb_submit_urb failed with result %d\n", |
1859 | __FUNCTION__, status); | 1877 | __FUNCTION__, retval); |
1860 | } | 1878 | } |
1861 | 1879 | ||
1862 | static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length) | 1880 | static void edge_tty_recv(struct device *dev, struct tty_struct *tty, unsigned char *data, int length) |
@@ -1883,12 +1901,13 @@ static void edge_bulk_out_callback (struct urb *urb) | |||
1883 | { | 1901 | { |
1884 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1902 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1885 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | 1903 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); |
1904 | int status = urb->status; | ||
1886 | 1905 | ||
1887 | dbg ("%s - port %d", __FUNCTION__, port->number); | 1906 | dbg ("%s - port %d", __FUNCTION__, port->number); |
1888 | 1907 | ||
1889 | edge_port->ep_write_urb_in_use = 0; | 1908 | edge_port->ep_write_urb_in_use = 0; |
1890 | 1909 | ||
1891 | switch (urb->status) { | 1910 | switch (status) { |
1892 | case 0: | 1911 | case 0: |
1893 | /* success */ | 1912 | /* success */ |
1894 | break; | 1913 | break; |
@@ -1896,11 +1915,12 @@ static void edge_bulk_out_callback (struct urb *urb) | |||
1896 | case -ENOENT: | 1915 | case -ENOENT: |
1897 | case -ESHUTDOWN: | 1916 | case -ESHUTDOWN: |
1898 | /* this urb is terminated, clean up */ | 1917 | /* this urb is terminated, clean up */ |
1899 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 1918 | dbg("%s - urb shutting down with status: %d", |
1919 | __FUNCTION__, status); | ||
1900 | return; | 1920 | return; |
1901 | default: | 1921 | default: |
1902 | dev_err (&urb->dev->dev,"%s - nonzero write bulk status received: %d\n", | 1922 | dev_err(&urb->dev->dev, "%s - nonzero write bulk status " |
1903 | __FUNCTION__, urb->status); | 1923 | "received: %d\n", __FUNCTION__, status); |
1904 | } | 1924 | } |
1905 | 1925 | ||
1906 | /* send any buffered data */ | 1926 | /* send any buffered data */ |
@@ -2351,7 +2371,7 @@ static int restart_read(struct edgeport_port *edge_port) | |||
2351 | urb->complete = edge_bulk_in_callback; | 2371 | urb->complete = edge_bulk_in_callback; |
2352 | urb->context = edge_port; | 2372 | urb->context = edge_port; |
2353 | urb->dev = edge_port->port->serial->dev; | 2373 | urb->dev = edge_port->port->serial->dev; |
2354 | status = usb_submit_urb(urb, GFP_KERNEL); | 2374 | status = usb_submit_urb(urb, GFP_ATOMIC); |
2355 | } | 2375 | } |
2356 | edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING; | 2376 | edge_port->ep_read_urb_state = EDGE_READ_URB_RUNNING; |
2357 | edge_port->shadow_mcr |= MCR_RTS; | 2377 | edge_port->shadow_mcr |= MCR_RTS; |
@@ -2524,14 +2544,6 @@ static void edge_set_termios (struct usb_serial_port *port, struct ktermios *old | |||
2524 | } | 2544 | } |
2525 | 2545 | ||
2526 | cflag = tty->termios->c_cflag; | 2546 | cflag = tty->termios->c_cflag; |
2527 | /* check that they really want us to change something */ | ||
2528 | if (old_termios) { | ||
2529 | if (cflag == old_termios->c_cflag && | ||
2530 | tty->termios->c_iflag == old_termios->c_iflag) { | ||
2531 | dbg ("%s - nothing to change", __FUNCTION__); | ||
2532 | return; | ||
2533 | } | ||
2534 | } | ||
2535 | 2547 | ||
2536 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, | 2548 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, |
2537 | tty->termios->c_cflag, tty->termios->c_iflag); | 2549 | tty->termios->c_cflag, tty->termios->c_iflag); |
@@ -2758,7 +2770,7 @@ static int edge_startup (struct usb_serial *serial) | |||
2758 | edge_port->port = serial->port[i]; | 2770 | edge_port->port = serial->port[i]; |
2759 | edge_port->edge_serial = edge_serial; | 2771 | edge_port->edge_serial = edge_serial; |
2760 | usb_set_serial_port_data(serial->port[i], edge_port); | 2772 | usb_set_serial_port_data(serial->port[i], edge_port); |
2761 | edge_port->bUartMode = 0; /* Default is RS232 */ | 2773 | edge_port->bUartMode = default_uart_mode; |
2762 | } | 2774 | } |
2763 | 2775 | ||
2764 | return 0; | 2776 | return 0; |
@@ -2784,6 +2796,7 @@ static void edge_shutdown (struct usb_serial *serial) | |||
2784 | 2796 | ||
2785 | for (i=0; i < serial->num_ports; ++i) { | 2797 | for (i=0; i < serial->num_ports; ++i) { |
2786 | edge_port = usb_get_serial_port_data(serial->port[i]); | 2798 | edge_port = usb_get_serial_port_data(serial->port[i]); |
2799 | edge_remove_sysfs_attrs(edge_port->port); | ||
2787 | if (edge_port) { | 2800 | if (edge_port) { |
2788 | edge_buf_free(edge_port->ep_out_buf); | 2801 | edge_buf_free(edge_port->ep_out_buf); |
2789 | kfree(edge_port); | 2802 | kfree(edge_port); |
@@ -2795,6 +2808,48 @@ static void edge_shutdown (struct usb_serial *serial) | |||
2795 | } | 2808 | } |
2796 | 2809 | ||
2797 | 2810 | ||
2811 | /* Sysfs Attributes */ | ||
2812 | |||
2813 | static ssize_t show_uart_mode(struct device *dev, | ||
2814 | struct device_attribute *attr, char *buf) | ||
2815 | { | ||
2816 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
2817 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2818 | |||
2819 | return sprintf(buf, "%d\n", edge_port->bUartMode); | ||
2820 | } | ||
2821 | |||
2822 | static ssize_t store_uart_mode(struct device *dev, | ||
2823 | struct device_attribute *attr, const char *valbuf, size_t count) | ||
2824 | { | ||
2825 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
2826 | struct edgeport_port *edge_port = usb_get_serial_port_data(port); | ||
2827 | unsigned int v = simple_strtoul(valbuf, NULL, 0); | ||
2828 | |||
2829 | dbg("%s: setting uart_mode = %d", __FUNCTION__, v); | ||
2830 | |||
2831 | if (v < 256) | ||
2832 | edge_port->bUartMode = v; | ||
2833 | else | ||
2834 | dev_err(dev, "%s - uart_mode %d is invalid\n", __FUNCTION__, v); | ||
2835 | |||
2836 | return count; | ||
2837 | } | ||
2838 | |||
2839 | static DEVICE_ATTR(uart_mode, S_IWUSR | S_IRUGO, show_uart_mode, store_uart_mode); | ||
2840 | |||
2841 | static int edge_create_sysfs_attrs(struct usb_serial_port *port) | ||
2842 | { | ||
2843 | return device_create_file(&port->dev, &dev_attr_uart_mode); | ||
2844 | } | ||
2845 | |||
2846 | static int edge_remove_sysfs_attrs(struct usb_serial_port *port) | ||
2847 | { | ||
2848 | device_remove_file(&port->dev, &dev_attr_uart_mode); | ||
2849 | return 0; | ||
2850 | } | ||
2851 | |||
2852 | |||
2798 | /* Circular Buffer */ | 2853 | /* Circular Buffer */ |
2799 | 2854 | ||
2800 | /* | 2855 | /* |
@@ -2991,6 +3046,7 @@ static struct usb_serial_driver edgeport_1port_device = { | |||
2991 | .unthrottle = edge_unthrottle, | 3046 | .unthrottle = edge_unthrottle, |
2992 | .attach = edge_startup, | 3047 | .attach = edge_startup, |
2993 | .shutdown = edge_shutdown, | 3048 | .shutdown = edge_shutdown, |
3049 | .port_probe = edge_create_sysfs_attrs, | ||
2994 | .ioctl = edge_ioctl, | 3050 | .ioctl = edge_ioctl, |
2995 | .set_termios = edge_set_termios, | 3051 | .set_termios = edge_set_termios, |
2996 | .tiocmget = edge_tiocmget, | 3052 | .tiocmget = edge_tiocmget, |
@@ -3022,6 +3078,7 @@ static struct usb_serial_driver edgeport_2port_device = { | |||
3022 | .unthrottle = edge_unthrottle, | 3078 | .unthrottle = edge_unthrottle, |
3023 | .attach = edge_startup, | 3079 | .attach = edge_startup, |
3024 | .shutdown = edge_shutdown, | 3080 | .shutdown = edge_shutdown, |
3081 | .port_probe = edge_create_sysfs_attrs, | ||
3025 | .ioctl = edge_ioctl, | 3082 | .ioctl = edge_ioctl, |
3026 | .set_termios = edge_set_termios, | 3083 | .set_termios = edge_set_termios, |
3027 | .tiocmget = edge_tiocmget, | 3084 | .tiocmget = edge_tiocmget, |
@@ -3085,3 +3142,6 @@ MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs"); | |||
3085 | module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR); | 3142 | module_param(ignore_cpu_rev, bool, S_IRUGO | S_IWUSR); |
3086 | MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device"); | 3143 | MODULE_PARM_DESC(ignore_cpu_rev, "Ignore the cpu revision when connecting to a device"); |
3087 | 3144 | ||
3145 | module_param(default_uart_mode, int, S_IRUGO | S_IWUSR); | ||
3146 | MODULE_PARM_DESC(default_uart_mode, "Default uart_mode, 0=RS232, ..."); | ||
3147 | |||
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h index e57fa117e486..8e1a491e52a9 100644 --- a/drivers/usb/serial/io_usbvend.h +++ b/drivers/usb/serial/io_usbvend.h | |||
@@ -131,7 +131,7 @@ | |||
131 | #define ION_DEVICE_ID_TI_EDGEPORT_2I 0x0207 // Edgeport/2i RS422/RS485 | 131 | #define ION_DEVICE_ID_TI_EDGEPORT_2I 0x0207 // Edgeport/2i RS422/RS485 |
132 | #define ION_DEVICE_ID_TI_EDGEPORT_421 0x020C // Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port) | 132 | #define ION_DEVICE_ID_TI_EDGEPORT_421 0x020C // Edgeport/421 4 hub 2 RS232 + Parallel (lucent on a different hub port) |
133 | #define ION_DEVICE_ID_TI_EDGEPORT_21 0x020D // Edgeport/21 2 RS232 + Parallel (lucent on a different hub port) | 133 | #define ION_DEVICE_ID_TI_EDGEPORT_21 0x020D // Edgeport/21 2 RS232 + Parallel (lucent on a different hub port) |
134 | #define ION_DEVICE_ID_TI_EDGEPORT_8 0x020F // Edgeport/8 (single-CPU) | 134 | #define ION_DEVICE_ID_TI_EDGEPORT_416 0x0212 // Edgeport/416 |
135 | #define ION_DEVICE_ID_TI_EDGEPORT_1 0x0215 // Edgeport/1 RS232 | 135 | #define ION_DEVICE_ID_TI_EDGEPORT_1 0x0215 // Edgeport/1 RS232 |
136 | #define ION_DEVICE_ID_TI_EDGEPORT_42 0x0217 // Edgeport/42 4 hub 2 RS232 | 136 | #define ION_DEVICE_ID_TI_EDGEPORT_42 0x0217 // Edgeport/42 4 hub 2 RS232 |
137 | #define ION_DEVICE_ID_TI_EDGEPORT_22I 0x021A // Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 | 137 | #define ION_DEVICE_ID_TI_EDGEPORT_22I 0x021A // Edgeport/22I is an Edgeport/4 with ports 1&2 RS422 and ports 3&4 RS232 |
@@ -143,12 +143,14 @@ | |||
143 | #define ION_DEVICE_ID_TI_EDGEPORT_21C 0x021E // Edgeport/21c is a TI based Edgeport/2 with lucent chip | 143 | #define ION_DEVICE_ID_TI_EDGEPORT_21C 0x021E // Edgeport/21c is a TI based Edgeport/2 with lucent chip |
144 | 144 | ||
145 | // Generation 3 devices -- 3410 based edgport/1 (256 byte I2C) | 145 | // Generation 3 devices -- 3410 based edgport/1 (256 byte I2C) |
146 | #define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1 0x240 // Edgeport/1 RS232 | 146 | #define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1 0x0240 // Edgeport/1 RS232 |
147 | #define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I 0x241 // Edgeport/1i- RS422 model | 147 | #define ION_DEVICE_ID_TI_TI3410_EDGEPORT_1I 0x0241 // Edgeport/1i- RS422 model |
148 | 148 | ||
149 | // Ti based software switchable RS232/RS422/RS485 devices | 149 | // Ti based software switchable RS232/RS422/RS485 devices |
150 | #define ION_DEVICE_ID_TI_EDGEPORT_4S 0x242 // Edgeport/4s - software switchable model | 150 | #define ION_DEVICE_ID_TI_EDGEPORT_4S 0x0242 // Edgeport/4s - software switchable model |
151 | #define ION_DEVICE_ID_IT_EDGEPORT_8S 0x243 // Edgeport/8s - software switchable model | 151 | #define ION_DEVICE_ID_TI_EDGEPORT_8S 0x0243 // Edgeport/8s - software switchable model |
152 | #define ION_DEVICE_ID_TI_EDGEPORT_8 0x0244 // Edgeport/8 (single-CPU) | ||
153 | #define ION_DEVICE_ID_TI_EDGEPORT_416B 0x0247 // Edgeport/416 | ||
152 | 154 | ||
153 | 155 | ||
154 | /************************************************************************ | 156 | /************************************************************************ |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 4df0ec74e0b1..0455c1552ae9 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
@@ -732,11 +732,13 @@ static void ipaq_read_bulk_callback(struct urb *urb) | |||
732 | struct tty_struct *tty; | 732 | struct tty_struct *tty; |
733 | unsigned char *data = urb->transfer_buffer; | 733 | unsigned char *data = urb->transfer_buffer; |
734 | int result; | 734 | int result; |
735 | int status = urb->status; | ||
735 | 736 | ||
736 | dbg("%s - port %d", __FUNCTION__, port->number); | 737 | dbg("%s - port %d", __FUNCTION__, port->number); |
737 | 738 | ||
738 | if (urb->status) { | 739 | if (status) { |
739 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 740 | dbg("%s - nonzero read bulk status received: %d", |
741 | __FUNCTION__, status); | ||
740 | return; | 742 | return; |
741 | } | 743 | } |
742 | 744 | ||
@@ -870,11 +872,13 @@ static void ipaq_write_bulk_callback(struct urb *urb) | |||
870 | struct ipaq_private *priv = usb_get_serial_port_data(port); | 872 | struct ipaq_private *priv = usb_get_serial_port_data(port); |
871 | unsigned long flags; | 873 | unsigned long flags; |
872 | int result; | 874 | int result; |
875 | int status = urb->status; | ||
873 | 876 | ||
874 | dbg("%s - port %d", __FUNCTION__, port->number); | 877 | dbg("%s - port %d", __FUNCTION__, port->number); |
875 | 878 | ||
876 | if (urb->status) { | 879 | if (status) { |
877 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 880 | dbg("%s - nonzero write bulk status received: %d", |
881 | __FUNCTION__, status); | ||
878 | return; | 882 | return; |
879 | } | 883 | } |
880 | 884 | ||
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 1bc586064c77..1b94daa61584 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
@@ -167,11 +167,13 @@ static void ipw_read_bulk_callback(struct urb *urb) | |||
167 | unsigned char *data = urb->transfer_buffer; | 167 | unsigned char *data = urb->transfer_buffer; |
168 | struct tty_struct *tty; | 168 | struct tty_struct *tty; |
169 | int result; | 169 | int result; |
170 | int status = urb->status; | ||
170 | 171 | ||
171 | dbg("%s - port %d", __FUNCTION__, port->number); | 172 | dbg("%s - port %d", __FUNCTION__, port->number); |
172 | 173 | ||
173 | if (urb->status) { | 174 | if (status) { |
174 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 175 | dbg("%s - nonzero read bulk status received: %d", |
176 | __FUNCTION__, status); | ||
175 | return; | 177 | return; |
176 | } | 178 | } |
177 | 179 | ||
@@ -369,13 +371,15 @@ static void ipw_close(struct usb_serial_port *port, struct file * filp) | |||
369 | static void ipw_write_bulk_callback(struct urb *urb) | 371 | static void ipw_write_bulk_callback(struct urb *urb) |
370 | { | 372 | { |
371 | struct usb_serial_port *port = urb->context; | 373 | struct usb_serial_port *port = urb->context; |
374 | int status = urb->status; | ||
372 | 375 | ||
373 | dbg("%s", __FUNCTION__); | 376 | dbg("%s", __FUNCTION__); |
374 | 377 | ||
375 | port->write_urb_busy = 0; | 378 | port->write_urb_busy = 0; |
376 | 379 | ||
377 | if (urb->status) | 380 | if (status) |
378 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 381 | dbg("%s - nonzero write bulk status received: %d", |
382 | __FUNCTION__, status); | ||
379 | 383 | ||
380 | usb_serial_port_softint(port); | 384 | usb_serial_port_softint(port); |
381 | } | 385 | } |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 9d847f69291c..5ab6a0c5ac52 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
@@ -21,6 +21,10 @@ | |||
21 | * | 21 | * |
22 | * See Documentation/usb/usb-serial.txt for more information on using this driver | 22 | * See Documentation/usb/usb-serial.txt for more information on using this driver |
23 | * | 23 | * |
24 | * 2007_Jun_21 Alan Cox <alan@redhat.com> | ||
25 | * Minimal cleanups for some of the driver problens and tty layer abuse. | ||
26 | * Still needs fixing to allow multiple dongles. | ||
27 | * | ||
24 | * 2002_Mar_07 greg kh | 28 | * 2002_Mar_07 greg kh |
25 | * moved some needed structures and #define values from the | 29 | * moved some needed structures and #define values from the |
26 | * net/irda/irda-usb.h file into our file, as we don't want to depend on | 30 | * net/irda/irda-usb.h file into our file, as we don't want to depend on |
@@ -109,6 +113,7 @@ static void ir_write_bulk_callback (struct urb *urb); | |||
109 | static void ir_read_bulk_callback (struct urb *urb); | 113 | static void ir_read_bulk_callback (struct urb *urb); |
110 | static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); | 114 | static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios); |
111 | 115 | ||
116 | /* Not that this lot means you can only have one per system */ | ||
112 | static u8 ir_baud = 0; | 117 | static u8 ir_baud = 0; |
113 | static u8 ir_xbof = 0; | 118 | static u8 ir_xbof = 0; |
114 | static u8 ir_add_bof = 0; | 119 | static u8 ir_add_bof = 0; |
@@ -392,12 +397,14 @@ static int ir_write (struct usb_serial_port *port, const unsigned char *buf, int | |||
392 | static void ir_write_bulk_callback (struct urb *urb) | 397 | static void ir_write_bulk_callback (struct urb *urb) |
393 | { | 398 | { |
394 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 399 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
400 | int status = urb->status; | ||
395 | 401 | ||
396 | dbg("%s - port %d", __FUNCTION__, port->number); | 402 | dbg("%s - port %d", __FUNCTION__, port->number); |
397 | 403 | ||
398 | port->write_urb_busy = 0; | 404 | port->write_urb_busy = 0; |
399 | if (urb->status) { | 405 | if (status) { |
400 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 406 | dbg("%s - nonzero write bulk status received: %d", |
407 | __FUNCTION__, status); | ||
401 | return; | 408 | return; |
402 | } | 409 | } |
403 | 410 | ||
@@ -417,6 +424,7 @@ static void ir_read_bulk_callback (struct urb *urb) | |||
417 | struct tty_struct *tty; | 424 | struct tty_struct *tty; |
418 | unsigned char *data = urb->transfer_buffer; | 425 | unsigned char *data = urb->transfer_buffer; |
419 | int result; | 426 | int result; |
427 | int status = urb->status; | ||
420 | 428 | ||
421 | dbg("%s - port %d", __FUNCTION__, port->number); | 429 | dbg("%s - port %d", __FUNCTION__, port->number); |
422 | 430 | ||
@@ -425,8 +433,7 @@ static void ir_read_bulk_callback (struct urb *urb) | |||
425 | return; | 433 | return; |
426 | } | 434 | } |
427 | 435 | ||
428 | switch (urb->status) { | 436 | switch (status) { |
429 | |||
430 | case 0: /* Successful */ | 437 | case 0: /* Successful */ |
431 | 438 | ||
432 | /* | 439 | /* |
@@ -444,22 +451,12 @@ static void ir_read_bulk_callback (struct urb *urb) | |||
444 | urb->actual_length, | 451 | urb->actual_length, |
445 | data); | 452 | data); |
446 | 453 | ||
447 | /* | ||
448 | * Bypass flip-buffers, and feed the ldisc directly | ||
449 | * due to our potentially large buffer size. Since we | ||
450 | * used to set low_latency, this is exactly what the | ||
451 | * tty layer did anyway :) | ||
452 | */ | ||
453 | tty = port->tty; | 454 | tty = port->tty; |
454 | 455 | ||
455 | /* | 456 | if (tty_buffer_request_room(tty, urb->actual_length - 1)) { |
456 | * FIXME: must not do this in IRQ context | 457 | tty_insert_flip_string(tty, data+1, urb->actual_length - 1); |
457 | */ | 458 | tty_flip_buffer_push(tty); |
458 | tty->ldisc.receive_buf( | 459 | } |
459 | tty, | ||
460 | data+1, | ||
461 | NULL, | ||
462 | urb->actual_length-1); | ||
463 | 460 | ||
464 | /* | 461 | /* |
465 | * No break here. | 462 | * No break here. |
@@ -490,7 +487,7 @@ static void ir_read_bulk_callback (struct urb *urb) | |||
490 | default: | 487 | default: |
491 | dbg("%s - nonzero read bulk status received: %d", | 488 | dbg("%s - nonzero read bulk status received: %d", |
492 | __FUNCTION__, | 489 | __FUNCTION__, |
493 | urb->status); | 490 | status); |
494 | break ; | 491 | break ; |
495 | 492 | ||
496 | } | 493 | } |
@@ -501,8 +498,9 @@ static void ir_read_bulk_callback (struct urb *urb) | |||
501 | static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) | 498 | static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) |
502 | { | 499 | { |
503 | unsigned char *transfer_buffer; | 500 | unsigned char *transfer_buffer; |
504 | unsigned int cflag; | ||
505 | int result; | 501 | int result; |
502 | speed_t baud; | ||
503 | int ir_baud; | ||
506 | 504 | ||
507 | dbg("%s - port %d", __FUNCTION__, port->number); | 505 | dbg("%s - port %d", __FUNCTION__, port->number); |
508 | 506 | ||
@@ -511,77 +509,59 @@ static void ir_set_termios (struct usb_serial_port *port, struct ktermios *old_t | |||
511 | return; | 509 | return; |
512 | } | 510 | } |
513 | 511 | ||
514 | cflag = port->tty->termios->c_cflag; | 512 | baud = tty_get_baud_rate(port->tty); |
515 | /* check that they really want us to change something */ | 513 | |
516 | if (old_termios) { | 514 | /* |
517 | if ((cflag == old_termios->c_cflag) && | 515 | * FIXME, we should compare the baud request against the |
518 | (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { | 516 | * capability stated in the IR header that we got in the |
519 | dbg("%s - nothing to change...", __FUNCTION__); | 517 | * startup function. |
520 | return; | 518 | */ |
521 | } | 519 | |
520 | switch (baud) { | ||
521 | case 2400: ir_baud = SPEED_2400; break; | ||
522 | case 9600: ir_baud = SPEED_9600; break; | ||
523 | case 19200: ir_baud = SPEED_19200; break; | ||
524 | case 38400: ir_baud = SPEED_38400; break; | ||
525 | case 57600: ir_baud = SPEED_57600; break; | ||
526 | case 115200: ir_baud = SPEED_115200; break; | ||
527 | case 576000: ir_baud = SPEED_576000; break; | ||
528 | case 1152000: ir_baud = SPEED_1152000; break; | ||
529 | case 4000000: ir_baud = SPEED_4000000; break; | ||
530 | break; | ||
531 | default: | ||
532 | ir_baud = SPEED_9600; | ||
533 | baud = 9600; | ||
534 | /* And once the new tty stuff is all done we need to | ||
535 | call back to correct the baud bits */ | ||
522 | } | 536 | } |
523 | 537 | ||
524 | /* All we can change is the baud rate */ | 538 | if (xbof == -1) |
525 | if (cflag & CBAUD) { | 539 | ir_xbof = ir_xbof_change(ir_add_bof); |
526 | 540 | else | |
527 | dbg ("%s - asking for baud %d", | 541 | ir_xbof = ir_xbof_change(xbof) ; |
528 | __FUNCTION__, | ||
529 | tty_get_baud_rate(port->tty)); | ||
530 | |||
531 | /* | ||
532 | * FIXME, we should compare the baud request against the | ||
533 | * capability stated in the IR header that we got in the | ||
534 | * startup function. | ||
535 | */ | ||
536 | switch (cflag & CBAUD) { | ||
537 | case B2400: ir_baud = SPEED_2400; break; | ||
538 | default: | ||
539 | case B9600: ir_baud = SPEED_9600; break; | ||
540 | case B19200: ir_baud = SPEED_19200; break; | ||
541 | case B38400: ir_baud = SPEED_38400; break; | ||
542 | case B57600: ir_baud = SPEED_57600; break; | ||
543 | case B115200: ir_baud = SPEED_115200; break; | ||
544 | case B576000: ir_baud = SPEED_576000; break; | ||
545 | case B1152000: ir_baud = SPEED_1152000; break; | ||
546 | #ifdef B4000000 | ||
547 | case B4000000: ir_baud = SPEED_4000000; break; | ||
548 | #endif | ||
549 | } | ||
550 | 542 | ||
551 | if (xbof == -1) { | 543 | /* FIXME need to check to see if our write urb is busy right |
552 | ir_xbof = ir_xbof_change(ir_add_bof); | 544 | * now, or use a urb pool. |
553 | } else { | 545 | * |
554 | ir_xbof = ir_xbof_change(xbof) ; | 546 | * send the baud change out on an "empty" data packet |
555 | } | 547 | */ |
548 | transfer_buffer = port->write_urb->transfer_buffer; | ||
549 | *transfer_buffer = ir_xbof | ir_baud; | ||
556 | 550 | ||
557 | /* Notify the tty driver that the termios have changed. */ | 551 | usb_fill_bulk_urb ( |
558 | port->tty->ldisc.set_termios(port->tty, NULL); | 552 | port->write_urb, |
559 | 553 | port->serial->dev, | |
560 | /* FIXME need to check to see if our write urb is busy right | 554 | usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), |
561 | * now, or use a urb pool. | 555 | port->write_urb->transfer_buffer, |
562 | * | 556 | 1, |
563 | * send the baud change out on an "empty" data packet | 557 | ir_write_bulk_callback, |
564 | */ | 558 | port); |
565 | transfer_buffer = port->write_urb->transfer_buffer; | 559 | |
566 | *transfer_buffer = ir_xbof | ir_baud; | 560 | port->write_urb->transfer_flags = URB_ZERO_PACKET; |
567 | 561 | ||
568 | usb_fill_bulk_urb ( | 562 | result = usb_submit_urb (port->write_urb, GFP_KERNEL); |
569 | port->write_urb, | 563 | if (result) |
570 | port->serial->dev, | 564 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); |
571 | usb_sndbulkpipe(port->serial->dev, | ||
572 | port->bulk_out_endpointAddress), | ||
573 | port->write_urb->transfer_buffer, | ||
574 | 1, | ||
575 | ir_write_bulk_callback, | ||
576 | port); | ||
577 | |||
578 | port->write_urb->transfer_flags = URB_ZERO_PACKET; | ||
579 | |||
580 | result = usb_submit_urb (port->write_urb, GFP_KERNEL); | ||
581 | if (result) | ||
582 | dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result); | ||
583 | } | ||
584 | return; | ||
585 | } | 565 | } |
586 | 566 | ||
587 | 567 | ||
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index e6966f12ed5a..f2a6fce5de1e 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
@@ -115,12 +115,13 @@ static int debug; | |||
115 | /* | 115 | /* |
116 | * Version Information | 116 | * Version Information |
117 | */ | 117 | */ |
118 | #define DRIVER_VERSION "v1.1.4" | 118 | #define DRIVER_VERSION "v1.1.5" |
119 | #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu" | 119 | #define DRIVER_AUTHOR "Hugh Blemings <hugh@misc.nu" |
120 | #define DRIVER_DESC "Keyspan USB to Serial Converter Driver" | 120 | #define DRIVER_DESC "Keyspan USB to Serial Converter Driver" |
121 | 121 | ||
122 | #define INSTAT_BUFLEN 32 | 122 | #define INSTAT_BUFLEN 32 |
123 | #define GLOCONT_BUFLEN 64 | 123 | #define GLOCONT_BUFLEN 64 |
124 | #define INDAT49W_BUFLEN 512 | ||
124 | 125 | ||
125 | /* Per device and per port private data */ | 126 | /* Per device and per port private data */ |
126 | struct keyspan_serial_private { | 127 | struct keyspan_serial_private { |
@@ -129,9 +130,15 @@ struct keyspan_serial_private { | |||
129 | struct urb *instat_urb; | 130 | struct urb *instat_urb; |
130 | char instat_buf[INSTAT_BUFLEN]; | 131 | char instat_buf[INSTAT_BUFLEN]; |
131 | 132 | ||
133 | /* added to support 49wg, where data from all 4 ports comes in on 1 EP */ | ||
134 | /* and high-speed supported */ | ||
135 | struct urb *indat_urb; | ||
136 | char indat_buf[INDAT49W_BUFLEN]; | ||
137 | |||
132 | /* XXX this one probably will need a lock */ | 138 | /* XXX this one probably will need a lock */ |
133 | struct urb *glocont_urb; | 139 | struct urb *glocont_urb; |
134 | char glocont_buf[GLOCONT_BUFLEN]; | 140 | char glocont_buf[GLOCONT_BUFLEN]; |
141 | char ctrl_buf[8]; // for EP0 control message | ||
135 | }; | 142 | }; |
136 | 143 | ||
137 | struct keyspan_port_private { | 144 | struct keyspan_port_private { |
@@ -179,12 +186,13 @@ struct keyspan_port_private { | |||
179 | 186 | ||
180 | 187 | ||
181 | /* Include Keyspan message headers. All current Keyspan Adapters | 188 | /* Include Keyspan message headers. All current Keyspan Adapters |
182 | make use of one of four message formats which are referred | 189 | make use of one of five message formats which are referred |
183 | to as USA-26, USA-28 and USA-49, USA-90 by Keyspan and within this driver. */ | 190 | to as USA-26, USA-28, USA-49, USA-90, USA-67 by Keyspan and within this driver. */ |
184 | #include "keyspan_usa26msg.h" | 191 | #include "keyspan_usa26msg.h" |
185 | #include "keyspan_usa28msg.h" | 192 | #include "keyspan_usa28msg.h" |
186 | #include "keyspan_usa49msg.h" | 193 | #include "keyspan_usa49msg.h" |
187 | #include "keyspan_usa90msg.h" | 194 | #include "keyspan_usa90msg.h" |
195 | #include "keyspan_usa67msg.h" | ||
188 | 196 | ||
189 | 197 | ||
190 | /* Functions used by new usb-serial code. */ | 198 | /* Functions used by new usb-serial code. */ |
@@ -419,14 +427,15 @@ static void usa26_indat_callback(struct urb *urb) | |||
419 | struct usb_serial_port *port; | 427 | struct usb_serial_port *port; |
420 | struct tty_struct *tty; | 428 | struct tty_struct *tty; |
421 | unsigned char *data = urb->transfer_buffer; | 429 | unsigned char *data = urb->transfer_buffer; |
430 | int status = urb->status; | ||
422 | 431 | ||
423 | dbg ("%s", __FUNCTION__); | 432 | dbg ("%s", __FUNCTION__); |
424 | 433 | ||
425 | endpoint = usb_pipeendpoint(urb->pipe); | 434 | endpoint = usb_pipeendpoint(urb->pipe); |
426 | 435 | ||
427 | if (urb->status) { | 436 | if (status) { |
428 | dbg("%s - nonzero status: %x on endpoint %d.", | 437 | dbg("%s - nonzero status: %x on endpoint %d.", |
429 | __FUNCTION__, urb->status, endpoint); | 438 | __FUNCTION__, status, endpoint); |
430 | return; | 439 | return; |
431 | } | 440 | } |
432 | 441 | ||
@@ -511,11 +520,12 @@ static void usa26_instat_callback(struct urb *urb) | |||
511 | struct usb_serial_port *port; | 520 | struct usb_serial_port *port; |
512 | struct keyspan_port_private *p_priv; | 521 | struct keyspan_port_private *p_priv; |
513 | int old_dcd_state, err; | 522 | int old_dcd_state, err; |
523 | int status = urb->status; | ||
514 | 524 | ||
515 | serial = (struct usb_serial *) urb->context; | 525 | serial = (struct usb_serial *) urb->context; |
516 | 526 | ||
517 | if (urb->status) { | 527 | if (status) { |
518 | dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); | 528 | dbg("%s - nonzero status: %x", __FUNCTION__, status); |
519 | return; | 529 | return; |
520 | } | 530 | } |
521 | if (urb->actual_length != 9) { | 531 | if (urb->actual_length != 9) { |
@@ -579,6 +589,7 @@ static void usa28_indat_callback(struct urb *urb) | |||
579 | struct tty_struct *tty; | 589 | struct tty_struct *tty; |
580 | unsigned char *data; | 590 | unsigned char *data; |
581 | struct keyspan_port_private *p_priv; | 591 | struct keyspan_port_private *p_priv; |
592 | int status = urb->status; | ||
582 | 593 | ||
583 | dbg ("%s", __FUNCTION__); | 594 | dbg ("%s", __FUNCTION__); |
584 | 595 | ||
@@ -590,9 +601,9 @@ static void usa28_indat_callback(struct urb *urb) | |||
590 | return; | 601 | return; |
591 | 602 | ||
592 | do { | 603 | do { |
593 | if (urb->status) { | 604 | if (status) { |
594 | dbg("%s - nonzero status: %x on endpoint %d.", | 605 | dbg("%s - nonzero status: %x on endpoint %d.", |
595 | __FUNCTION__, urb->status, usb_pipeendpoint(urb->pipe)); | 606 | __FUNCTION__, status, usb_pipeendpoint(urb->pipe)); |
596 | return; | 607 | return; |
597 | } | 608 | } |
598 | 609 | ||
@@ -648,11 +659,12 @@ static void usa28_instat_callback(struct urb *urb) | |||
648 | struct usb_serial_port *port; | 659 | struct usb_serial_port *port; |
649 | struct keyspan_port_private *p_priv; | 660 | struct keyspan_port_private *p_priv; |
650 | int old_dcd_state; | 661 | int old_dcd_state; |
662 | int status = urb->status; | ||
651 | 663 | ||
652 | serial = (struct usb_serial *) urb->context; | 664 | serial = (struct usb_serial *) urb->context; |
653 | 665 | ||
654 | if (urb->status) { | 666 | if (status) { |
655 | dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); | 667 | dbg("%s - nonzero status: %x", __FUNCTION__, status); |
656 | return; | 668 | return; |
657 | } | 669 | } |
658 | 670 | ||
@@ -739,13 +751,14 @@ static void usa49_instat_callback(struct urb *urb) | |||
739 | struct usb_serial_port *port; | 751 | struct usb_serial_port *port; |
740 | struct keyspan_port_private *p_priv; | 752 | struct keyspan_port_private *p_priv; |
741 | int old_dcd_state; | 753 | int old_dcd_state; |
754 | int status = urb->status; | ||
742 | 755 | ||
743 | dbg ("%s", __FUNCTION__); | 756 | dbg ("%s", __FUNCTION__); |
744 | 757 | ||
745 | serial = (struct usb_serial *) urb->context; | 758 | serial = (struct usb_serial *) urb->context; |
746 | 759 | ||
747 | if (urb->status) { | 760 | if (status) { |
748 | dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); | 761 | dbg("%s - nonzero status: %x", __FUNCTION__, status); |
749 | return; | 762 | return; |
750 | } | 763 | } |
751 | 764 | ||
@@ -805,14 +818,15 @@ static void usa49_indat_callback(struct urb *urb) | |||
805 | struct usb_serial_port *port; | 818 | struct usb_serial_port *port; |
806 | struct tty_struct *tty; | 819 | struct tty_struct *tty; |
807 | unsigned char *data = urb->transfer_buffer; | 820 | unsigned char *data = urb->transfer_buffer; |
821 | int status = urb->status; | ||
808 | 822 | ||
809 | dbg ("%s", __FUNCTION__); | 823 | dbg ("%s", __FUNCTION__); |
810 | 824 | ||
811 | endpoint = usb_pipeendpoint(urb->pipe); | 825 | endpoint = usb_pipeendpoint(urb->pipe); |
812 | 826 | ||
813 | if (urb->status) { | 827 | if (status) { |
814 | dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__, | 828 | dbg("%s - nonzero status: %x on endpoint %d.", __FUNCTION__, |
815 | urb->status, endpoint); | 829 | status, endpoint); |
816 | return; | 830 | return; |
817 | } | 831 | } |
818 | 832 | ||
@@ -850,13 +864,90 @@ static void usa49_indat_callback(struct urb *urb) | |||
850 | } | 864 | } |
851 | } | 865 | } |
852 | 866 | ||
867 | static void usa49wg_indat_callback(struct urb *urb) | ||
868 | { | ||
869 | int i, len, x, err; | ||
870 | struct usb_serial *serial; | ||
871 | struct usb_serial_port *port; | ||
872 | struct tty_struct *tty; | ||
873 | unsigned char *data = urb->transfer_buffer; | ||
874 | int status = urb->status; | ||
875 | |||
876 | dbg ("%s", __FUNCTION__); | ||
877 | |||
878 | serial = urb->context; | ||
879 | |||
880 | if (status) { | ||
881 | dbg("%s - nonzero status: %x", __FUNCTION__, status); | ||
882 | return; | ||
883 | } | ||
884 | |||
885 | /* inbound data is in the form P#, len, status, data */ | ||
886 | i = 0; | ||
887 | len = 0; | ||
888 | |||
889 | if (urb->actual_length) { | ||
890 | while (i < urb->actual_length) { | ||
891 | |||
892 | /* Check port number from message*/ | ||
893 | if (data[i] >= serial->num_ports) { | ||
894 | dbg ("%s - Unexpected port number %d", | ||
895 | __FUNCTION__, data[i]); | ||
896 | return; | ||
897 | } | ||
898 | port = serial->port[data[i++]]; | ||
899 | tty = port->tty; | ||
900 | len = data[i++]; | ||
901 | |||
902 | /* 0x80 bit is error flag */ | ||
903 | if ((data[i] & 0x80) == 0) { | ||
904 | /* no error on any byte */ | ||
905 | i++; | ||
906 | for (x = 1; x < len ; ++x) | ||
907 | if (port->open_count) | ||
908 | tty_insert_flip_char(tty, | ||
909 | data[i++], 0); | ||
910 | else | ||
911 | i++; | ||
912 | } else { | ||
913 | /* | ||
914 | * some bytes had errors, every byte has status | ||
915 | */ | ||
916 | for (x = 0; x + 1 < len; x += 2) { | ||
917 | int stat = data[i], flag = 0; | ||
918 | if (stat & RXERROR_OVERRUN) | ||
919 | flag |= TTY_OVERRUN; | ||
920 | if (stat & RXERROR_FRAMING) | ||
921 | flag |= TTY_FRAME; | ||
922 | if (stat & RXERROR_PARITY) | ||
923 | flag |= TTY_PARITY; | ||
924 | /* XXX should handle break (0x10) */ | ||
925 | if (port->open_count) | ||
926 | tty_insert_flip_char(tty, | ||
927 | data[i+1], flag); | ||
928 | i += 2; | ||
929 | } | ||
930 | } | ||
931 | if (port->open_count) | ||
932 | tty_flip_buffer_push(tty); | ||
933 | } | ||
934 | } | ||
935 | |||
936 | /* Resubmit urb so we continue receiving */ | ||
937 | urb->dev = serial->dev; | ||
938 | |||
939 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
940 | if (err != 0) | ||
941 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
942 | } | ||
943 | |||
853 | /* not used, usa-49 doesn't have per-port control endpoints */ | 944 | /* not used, usa-49 doesn't have per-port control endpoints */ |
854 | static void usa49_outcont_callback(struct urb *urb) | 945 | static void usa49_outcont_callback(struct urb *urb) |
855 | { | 946 | { |
856 | dbg ("%s", __FUNCTION__); | 947 | dbg ("%s", __FUNCTION__); |
857 | } | 948 | } |
858 | 949 | ||
859 | static void usa90_indat_callback(struct urb *urb) | 950 | static void usa90_indat_callback(struct urb *urb) |
860 | { | 951 | { |
861 | int i, err; | 952 | int i, err; |
862 | int endpoint; | 953 | int endpoint; |
@@ -864,15 +955,15 @@ static void usa90_indat_callback(struct urb *urb) | |||
864 | struct keyspan_port_private *p_priv; | 955 | struct keyspan_port_private *p_priv; |
865 | struct tty_struct *tty; | 956 | struct tty_struct *tty; |
866 | unsigned char *data = urb->transfer_buffer; | 957 | unsigned char *data = urb->transfer_buffer; |
958 | int status = urb->status; | ||
867 | 959 | ||
868 | dbg ("%s", __FUNCTION__); | 960 | dbg ("%s", __FUNCTION__); |
869 | 961 | ||
870 | endpoint = usb_pipeendpoint(urb->pipe); | 962 | endpoint = usb_pipeendpoint(urb->pipe); |
871 | 963 | ||
872 | 964 | if (status) { | |
873 | if (urb->status) { | ||
874 | dbg("%s - nonzero status: %x on endpoint %d.", | 965 | dbg("%s - nonzero status: %x on endpoint %d.", |
875 | __FUNCTION__, urb->status, endpoint); | 966 | __FUNCTION__, status, endpoint); |
876 | return; | 967 | return; |
877 | } | 968 | } |
878 | 969 | ||
@@ -938,11 +1029,12 @@ static void usa90_instat_callback(struct urb *urb) | |||
938 | struct usb_serial_port *port; | 1029 | struct usb_serial_port *port; |
939 | struct keyspan_port_private *p_priv; | 1030 | struct keyspan_port_private *p_priv; |
940 | int old_dcd_state, err; | 1031 | int old_dcd_state, err; |
1032 | int status = urb->status; | ||
941 | 1033 | ||
942 | serial = (struct usb_serial *) urb->context; | 1034 | serial = (struct usb_serial *) urb->context; |
943 | 1035 | ||
944 | if (urb->status) { | 1036 | if (status) { |
945 | dbg("%s - nonzero status: %x", __FUNCTION__, urb->status); | 1037 | dbg("%s - nonzero status: %x", __FUNCTION__, status); |
946 | return; | 1038 | return; |
947 | } | 1039 | } |
948 | if (urb->actual_length < 14) { | 1040 | if (urb->actual_length < 14) { |
@@ -995,6 +1087,88 @@ static void usa90_outcont_callback(struct urb *urb) | |||
995 | } | 1087 | } |
996 | } | 1088 | } |
997 | 1089 | ||
1090 | /* Status messages from the 28xg */ | ||
1091 | static void usa67_instat_callback(struct urb *urb) | ||
1092 | { | ||
1093 | int err; | ||
1094 | unsigned char *data = urb->transfer_buffer; | ||
1095 | struct keyspan_usa67_portStatusMessage *msg; | ||
1096 | struct usb_serial *serial; | ||
1097 | struct usb_serial_port *port; | ||
1098 | struct keyspan_port_private *p_priv; | ||
1099 | int old_dcd_state; | ||
1100 | int status = urb->status; | ||
1101 | |||
1102 | dbg ("%s", __FUNCTION__); | ||
1103 | |||
1104 | serial = urb->context; | ||
1105 | |||
1106 | if (status) { | ||
1107 | dbg("%s - nonzero status: %x", __FUNCTION__, status); | ||
1108 | return; | ||
1109 | } | ||
1110 | |||
1111 | if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) { | ||
1112 | dbg("%s - bad length %d", __FUNCTION__, urb->actual_length); | ||
1113 | return; | ||
1114 | } | ||
1115 | |||
1116 | |||
1117 | /* Now do something useful with the data */ | ||
1118 | msg = (struct keyspan_usa67_portStatusMessage *)data; | ||
1119 | |||
1120 | /* Check port number from message and retrieve private data */ | ||
1121 | if (msg->port >= serial->num_ports) { | ||
1122 | dbg ("%s - Unexpected port number %d", __FUNCTION__, msg->port); | ||
1123 | return; | ||
1124 | } | ||
1125 | |||
1126 | port = serial->port[msg->port]; | ||
1127 | p_priv = usb_get_serial_port_data(port); | ||
1128 | |||
1129 | /* Update handshaking pin state information */ | ||
1130 | old_dcd_state = p_priv->dcd_state; | ||
1131 | p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); | ||
1132 | p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); | ||
1133 | |||
1134 | if (port->tty && !C_CLOCAL(port->tty) | ||
1135 | && old_dcd_state != p_priv->dcd_state) { | ||
1136 | if (old_dcd_state) | ||
1137 | tty_hangup(port->tty); | ||
1138 | /* else */ | ||
1139 | /* wake_up_interruptible(&p_priv->open_wait); */ | ||
1140 | } | ||
1141 | |||
1142 | /* Resubmit urb so we continue receiving */ | ||
1143 | urb->dev = serial->dev; | ||
1144 | err = usb_submit_urb(urb, GFP_ATOMIC); | ||
1145 | if (err != 0) | ||
1146 | dbg("%s - resubmit read urb failed. (%d)", __FUNCTION__, err); | ||
1147 | } | ||
1148 | |||
1149 | static void usa67_glocont_callback(struct urb *urb) | ||
1150 | { | ||
1151 | struct usb_serial *serial; | ||
1152 | struct usb_serial_port *port; | ||
1153 | struct keyspan_port_private *p_priv; | ||
1154 | int i; | ||
1155 | |||
1156 | dbg ("%s", __FUNCTION__); | ||
1157 | |||
1158 | serial = urb->context; | ||
1159 | for (i = 0; i < serial->num_ports; ++i) { | ||
1160 | port = serial->port[i]; | ||
1161 | p_priv = usb_get_serial_port_data(port); | ||
1162 | |||
1163 | if (p_priv->resend_cont) { | ||
1164 | dbg ("%s - sending setup", __FUNCTION__); | ||
1165 | keyspan_usa67_send_setup(serial, port, | ||
1166 | p_priv->resend_cont - 1); | ||
1167 | break; | ||
1168 | } | ||
1169 | } | ||
1170 | } | ||
1171 | |||
998 | static int keyspan_write_room (struct usb_serial_port *port) | 1172 | static int keyspan_write_room (struct usb_serial_port *port) |
999 | { | 1173 | { |
1000 | struct keyspan_port_private *p_priv; | 1174 | struct keyspan_port_private *p_priv; |
@@ -1311,6 +1485,11 @@ static struct urb *keyspan_setup_urb (struct usb_serial *serial, int endpoint, | |||
1311 | return NULL; | 1485 | return NULL; |
1312 | } | 1486 | } |
1313 | 1487 | ||
1488 | if (endpoint == 0) { | ||
1489 | /* control EP filled in when used */ | ||
1490 | return urb; | ||
1491 | } | ||
1492 | |||
1314 | ep_desc = find_ep(serial, endpoint); | 1493 | ep_desc = find_ep(serial, endpoint); |
1315 | if (!ep_desc) { | 1494 | if (!ep_desc) { |
1316 | /* leak the urb, something's wrong and the callers don't care */ | 1495 | /* leak the urb, something's wrong and the callers don't care */ |
@@ -1380,6 +1559,14 @@ static struct callbacks { | |||
1380 | .outdat_callback = usa2x_outdat_callback, | 1559 | .outdat_callback = usa2x_outdat_callback, |
1381 | .inack_callback = usa28_inack_callback, | 1560 | .inack_callback = usa28_inack_callback, |
1382 | .outcont_callback = usa90_outcont_callback, | 1561 | .outcont_callback = usa90_outcont_callback, |
1562 | }, { | ||
1563 | /* msg_usa67 callbacks */ | ||
1564 | .instat_callback = usa67_instat_callback, | ||
1565 | .glocont_callback = usa67_glocont_callback, | ||
1566 | .indat_callback = usa26_indat_callback, | ||
1567 | .outdat_callback = usa2x_outdat_callback, | ||
1568 | .inack_callback = usa26_inack_callback, | ||
1569 | .outcont_callback = usa26_outcont_callback, | ||
1383 | } | 1570 | } |
1384 | }; | 1571 | }; |
1385 | 1572 | ||
@@ -1410,6 +1597,11 @@ static void keyspan_setup_urbs(struct usb_serial *serial) | |||
1410 | serial, s_priv->instat_buf, INSTAT_BUFLEN, | 1597 | serial, s_priv->instat_buf, INSTAT_BUFLEN, |
1411 | cback->instat_callback); | 1598 | cback->instat_callback); |
1412 | 1599 | ||
1600 | s_priv->indat_urb = keyspan_setup_urb | ||
1601 | (serial, d_details->indat_endpoint, USB_DIR_IN, | ||
1602 | serial, s_priv->indat_buf, INDAT49W_BUFLEN, | ||
1603 | usa49wg_indat_callback); | ||
1604 | |||
1413 | s_priv->glocont_urb = keyspan_setup_urb | 1605 | s_priv->glocont_urb = keyspan_setup_urb |
1414 | (serial, d_details->glocont_endpoint, USB_DIR_OUT, | 1606 | (serial, d_details->glocont_endpoint, USB_DIR_OUT, |
1415 | serial, s_priv->glocont_buf, GLOCONT_BUFLEN, | 1607 | serial, s_priv->glocont_buf, GLOCONT_BUFLEN, |
@@ -1685,8 +1877,8 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, | |||
1685 | } | 1877 | } |
1686 | 1878 | ||
1687 | /* Save reset port val for resend. | 1879 | /* Save reset port val for resend. |
1688 | Don't overwrite resend for close condition. */ | 1880 | Don't overwrite resend for open/close condition. */ |
1689 | if (p_priv->resend_cont != 3) | 1881 | if ((reset_port + 1) > p_priv->resend_cont) |
1690 | p_priv->resend_cont = reset_port + 1; | 1882 | p_priv->resend_cont = reset_port + 1; |
1691 | if (this_urb->status == -EINPROGRESS) { | 1883 | if (this_urb->status == -EINPROGRESS) { |
1692 | /* dbg ("%s - already writing", __FUNCTION__); */ | 1884 | /* dbg ("%s - already writing", __FUNCTION__); */ |
@@ -1836,8 +2028,8 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, | |||
1836 | } | 2028 | } |
1837 | 2029 | ||
1838 | /* Save reset port val for resend. | 2030 | /* Save reset port val for resend. |
1839 | Don't overwrite resend for close condition. */ | 2031 | Don't overwrite resend for open/close condition. */ |
1840 | if (p_priv->resend_cont != 3) | 2032 | if ((reset_port + 1) > p_priv->resend_cont) |
1841 | p_priv->resend_cont = reset_port + 1; | 2033 | p_priv->resend_cont = reset_port + 1; |
1842 | if (this_urb->status == -EINPROGRESS) { | 2034 | if (this_urb->status == -EINPROGRESS) { |
1843 | dbg ("%s already writing", __FUNCTION__); | 2035 | dbg ("%s already writing", __FUNCTION__); |
@@ -1940,11 +2132,11 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
1940 | struct usb_serial_port *port, | 2132 | struct usb_serial_port *port, |
1941 | int reset_port) | 2133 | int reset_port) |
1942 | { | 2134 | { |
1943 | struct keyspan_usa49_portControlMessage msg; | 2135 | struct keyspan_usa49_portControlMessage msg; |
2136 | struct usb_ctrlrequest *dr = NULL; | ||
1944 | struct keyspan_serial_private *s_priv; | 2137 | struct keyspan_serial_private *s_priv; |
1945 | struct keyspan_port_private *p_priv; | 2138 | struct keyspan_port_private *p_priv; |
1946 | const struct keyspan_device_details *d_details; | 2139 | const struct keyspan_device_details *d_details; |
1947 | int glocont_urb; | ||
1948 | struct urb *this_urb; | 2140 | struct urb *this_urb; |
1949 | int err, device_port; | 2141 | int err, device_port; |
1950 | 2142 | ||
@@ -1954,10 +2146,9 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
1954 | p_priv = usb_get_serial_port_data(port); | 2146 | p_priv = usb_get_serial_port_data(port); |
1955 | d_details = s_priv->device_details; | 2147 | d_details = s_priv->device_details; |
1956 | 2148 | ||
1957 | glocont_urb = d_details->glocont_endpoint; | ||
1958 | this_urb = s_priv->glocont_urb; | 2149 | this_urb = s_priv->glocont_urb; |
1959 | 2150 | ||
1960 | /* Work out which port within the device is being setup */ | 2151 | /* Work out which port within the device is being setup */ |
1961 | device_port = port->number - port->serial->minor; | 2152 | device_port = port->number - port->serial->minor; |
1962 | 2153 | ||
1963 | dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port); | 2154 | dbg("%s - endpoint %d port %d (%d)",__FUNCTION__, usb_pipeendpoint(this_urb->pipe), port->number, device_port); |
@@ -1969,9 +2160,10 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
1969 | } | 2160 | } |
1970 | 2161 | ||
1971 | /* Save reset port val for resend. | 2162 | /* Save reset port val for resend. |
1972 | Don't overwrite resend for close condition. */ | 2163 | Don't overwrite resend for open/close condition. */ |
1973 | if (p_priv->resend_cont != 3) | 2164 | if ((reset_port + 1) > p_priv->resend_cont) |
1974 | p_priv->resend_cont = reset_port + 1; | 2165 | p_priv->resend_cont = reset_port + 1; |
2166 | |||
1975 | if (this_urb->status == -EINPROGRESS) { | 2167 | if (this_urb->status == -EINPROGRESS) { |
1976 | /* dbg ("%s - already writing", __FUNCTION__); */ | 2168 | /* dbg ("%s - already writing", __FUNCTION__); */ |
1977 | mdelay(5); | 2169 | mdelay(5); |
@@ -2083,20 +2275,39 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, | |||
2083 | msg.dtr = p_priv->dtr_state; | 2275 | msg.dtr = p_priv->dtr_state; |
2084 | 2276 | ||
2085 | p_priv->resend_cont = 0; | 2277 | p_priv->resend_cont = 0; |
2086 | memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); | 2278 | |
2279 | /* if the device is a 49wg, we send control message on usb control EP 0 */ | ||
2280 | |||
2281 | if (d_details->product_id == keyspan_usa49wg_product_id) { | ||
2282 | dr = (void *)(s_priv->ctrl_buf); | ||
2283 | dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT; | ||
2284 | dr->bRequest = 0xB0; /* 49wg control message */; | ||
2285 | dr->wValue = 0; | ||
2286 | dr->wIndex = 0; | ||
2287 | dr->wLength = cpu_to_le16(sizeof(msg)); | ||
2288 | |||
2289 | memcpy (s_priv->glocont_buf, &msg, sizeof(msg)); | ||
2290 | |||
2291 | usb_fill_control_urb(this_urb, serial->dev, usb_sndctrlpipe(serial->dev, 0), | ||
2292 | (unsigned char *)dr, s_priv->glocont_buf, sizeof(msg), | ||
2293 | usa49_glocont_callback, serial); | ||
2294 | |||
2295 | } else { | ||
2296 | memcpy(this_urb->transfer_buffer, &msg, sizeof(msg)); | ||
2087 | 2297 | ||
2088 | /* send the data out the device on control endpoint */ | 2298 | /* send the data out the device on control endpoint */ |
2089 | this_urb->transfer_buffer_length = sizeof(msg); | 2299 | this_urb->transfer_buffer_length = sizeof(msg); |
2090 | 2300 | ||
2091 | this_urb->dev = serial->dev; | 2301 | this_urb->dev = serial->dev; |
2302 | } | ||
2092 | if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { | 2303 | if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) { |
2093 | dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err); | 2304 | dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, err); |
2094 | } | 2305 | } |
2095 | #if 0 | 2306 | #if 0 |
2096 | else { | 2307 | else { |
2097 | dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__, | 2308 | dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __FUNCTION__, |
2098 | outcont_urb, this_urb->transfer_buffer_length, | 2309 | outcont_urb, this_urb->transfer_buffer_length, |
2099 | usb_pipeendpoint(this_urb->pipe)); | 2310 | usb_pipeendpoint(this_urb->pipe)); |
2100 | } | 2311 | } |
2101 | #endif | 2312 | #endif |
2102 | 2313 | ||
@@ -2241,6 +2452,154 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, | |||
2241 | return (0); | 2452 | return (0); |
2242 | } | 2453 | } |
2243 | 2454 | ||
2455 | static int keyspan_usa67_send_setup(struct usb_serial *serial, | ||
2456 | struct usb_serial_port *port, | ||
2457 | int reset_port) | ||
2458 | { | ||
2459 | struct keyspan_usa67_portControlMessage msg; | ||
2460 | struct keyspan_serial_private *s_priv; | ||
2461 | struct keyspan_port_private *p_priv; | ||
2462 | const struct keyspan_device_details *d_details; | ||
2463 | struct urb *this_urb; | ||
2464 | int err, device_port; | ||
2465 | |||
2466 | dbg ("%s", __FUNCTION__); | ||
2467 | |||
2468 | s_priv = usb_get_serial_data(serial); | ||
2469 | p_priv = usb_get_serial_port_data(port); | ||
2470 | d_details = s_priv->device_details; | ||
2471 | |||
2472 | this_urb = s_priv->glocont_urb; | ||
2473 | |||
2474 | /* Work out which port within the device is being setup */ | ||
2475 | device_port = port->number - port->serial->minor; | ||
2476 | |||
2477 | /* Make sure we have an urb then send the message */ | ||
2478 | if (this_urb == NULL) { | ||
2479 | dbg("%s - oops no urb for port %d.", __FUNCTION__, | ||
2480 | port->number); | ||
2481 | return -1; | ||
2482 | } | ||
2483 | |||
2484 | /* Save reset port val for resend. | ||
2485 | Don't overwrite resend for open/close condition. */ | ||
2486 | if ((reset_port + 1) > p_priv->resend_cont) | ||
2487 | p_priv->resend_cont = reset_port + 1; | ||
2488 | if (this_urb->status == -EINPROGRESS) { | ||
2489 | /* dbg ("%s - already writing", __FUNCTION__); */ | ||
2490 | mdelay(5); | ||
2491 | return(-1); | ||
2492 | } | ||
2493 | |||
2494 | memset(&msg, 0, sizeof(struct keyspan_usa67_portControlMessage)); | ||
2495 | |||
2496 | msg.port = device_port; | ||
2497 | |||
2498 | /* Only set baud rate if it's changed */ | ||
2499 | if (p_priv->old_baud != p_priv->baud) { | ||
2500 | p_priv->old_baud = p_priv->baud; | ||
2501 | msg.setClocking = 0xff; | ||
2502 | if (d_details->calculate_baud_rate | ||
2503 | (p_priv->baud, d_details->baudclk, &msg.baudHi, | ||
2504 | &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE ) { | ||
2505 | dbg("%s - Invalid baud rate %d requested, using 9600.", __FUNCTION__, | ||
2506 | p_priv->baud); | ||
2507 | msg.baudLo = 0; | ||
2508 | msg.baudHi = 125; /* Values for 9600 baud */ | ||
2509 | msg.prescaler = 10; | ||
2510 | } | ||
2511 | msg.setPrescaler = 0xff; | ||
2512 | } | ||
2513 | |||
2514 | msg.lcr = (p_priv->cflag & CSTOPB) ? STOPBITS_678_2 : STOPBITS_5678_1; | ||
2515 | switch (p_priv->cflag & CSIZE) { | ||
2516 | case CS5: | ||
2517 | msg.lcr |= USA_DATABITS_5; | ||
2518 | break; | ||
2519 | case CS6: | ||
2520 | msg.lcr |= USA_DATABITS_6; | ||
2521 | break; | ||
2522 | case CS7: | ||
2523 | msg.lcr |= USA_DATABITS_7; | ||
2524 | break; | ||
2525 | case CS8: | ||
2526 | msg.lcr |= USA_DATABITS_8; | ||
2527 | break; | ||
2528 | } | ||
2529 | if (p_priv->cflag & PARENB) { | ||
2530 | /* note USA_PARITY_NONE == 0 */ | ||
2531 | msg.lcr |= (p_priv->cflag & PARODD)? | ||
2532 | USA_PARITY_ODD: USA_PARITY_EVEN; | ||
2533 | } | ||
2534 | msg.setLcr = 0xff; | ||
2535 | |||
2536 | msg.ctsFlowControl = (p_priv->flow_control == flow_cts); | ||
2537 | msg.xonFlowControl = 0; | ||
2538 | msg.setFlowControl = 0xff; | ||
2539 | msg.forwardingLength = 16; | ||
2540 | msg.xonChar = 17; | ||
2541 | msg.xoffChar = 19; | ||
2542 | |||
2543 | if (reset_port == 1) { | ||
2544 | /* Opening port */ | ||
2545 | msg._txOn = 1; | ||
2546 | msg._txOff = 0; | ||
2547 | msg.txFlush = 0; | ||
2548 | msg.txBreak = 0; | ||
2549 | msg.rxOn = 1; | ||
2550 | msg.rxOff = 0; | ||
2551 | msg.rxFlush = 1; | ||
2552 | msg.rxForward = 0; | ||
2553 | msg.returnStatus = 0; | ||
2554 | msg.resetDataToggle = 0xff; | ||
2555 | } else if (reset_port == 2) { | ||
2556 | /* Closing port */ | ||
2557 | msg._txOn = 0; | ||
2558 | msg._txOff = 1; | ||
2559 | msg.txFlush = 0; | ||
2560 | msg.txBreak = 0; | ||
2561 | msg.rxOn = 0; | ||
2562 | msg.rxOff = 1; | ||
2563 | msg.rxFlush = 1; | ||
2564 | msg.rxForward = 0; | ||
2565 | msg.returnStatus = 0; | ||
2566 | msg.resetDataToggle = 0; | ||
2567 | } else { | ||
2568 | /* Sending intermediate configs */ | ||
2569 | msg._txOn = (! p_priv->break_on); | ||
2570 | msg._txOff = 0; | ||
2571 | msg.txFlush = 0; | ||
2572 | msg.txBreak = (p_priv->break_on); | ||
2573 | msg.rxOn = 0; | ||
2574 | msg.rxOff = 0; | ||
2575 | msg.rxFlush = 0; | ||
2576 | msg.rxForward = 0; | ||
2577 | msg.returnStatus = 0; | ||
2578 | msg.resetDataToggle = 0x0; | ||
2579 | } | ||
2580 | |||
2581 | /* Do handshaking outputs */ | ||
2582 | msg.setTxTriState_setRts = 0xff; | ||
2583 | msg.txTriState_rts = p_priv->rts_state; | ||
2584 | |||
2585 | msg.setHskoa_setDtr = 0xff; | ||
2586 | msg.hskoa_dtr = p_priv->dtr_state; | ||
2587 | |||
2588 | p_priv->resend_cont = 0; | ||
2589 | |||
2590 | memcpy(this_urb->transfer_buffer, &msg, sizeof(msg)); | ||
2591 | |||
2592 | /* send the data out the device on control endpoint */ | ||
2593 | this_urb->transfer_buffer_length = sizeof(msg); | ||
2594 | this_urb->dev = serial->dev; | ||
2595 | |||
2596 | err = usb_submit_urb(this_urb, GFP_ATOMIC); | ||
2597 | if (err != 0) | ||
2598 | dbg("%s - usb_submit_urb(setup) failed (%d)", __FUNCTION__, | ||
2599 | err); | ||
2600 | return (0); | ||
2601 | } | ||
2602 | |||
2244 | static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) | 2603 | static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) |
2245 | { | 2604 | { |
2246 | struct usb_serial *serial = port->serial; | 2605 | struct usb_serial *serial = port->serial; |
@@ -2265,6 +2624,9 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port) | |||
2265 | case msg_usa90: | 2624 | case msg_usa90: |
2266 | keyspan_usa90_send_setup(serial, port, reset_port); | 2625 | keyspan_usa90_send_setup(serial, port, reset_port); |
2267 | break; | 2626 | break; |
2627 | case msg_usa67: | ||
2628 | keyspan_usa67_send_setup(serial, port, reset_port); | ||
2629 | break; | ||
2268 | } | 2630 | } |
2269 | } | 2631 | } |
2270 | 2632 | ||
@@ -2313,9 +2675,19 @@ static int keyspan_startup (struct usb_serial *serial) | |||
2313 | 2675 | ||
2314 | keyspan_setup_urbs(serial); | 2676 | keyspan_setup_urbs(serial); |
2315 | 2677 | ||
2316 | s_priv->instat_urb->dev = serial->dev; | 2678 | if (s_priv->instat_urb != NULL) { |
2317 | if ((err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL)) != 0) { | 2679 | s_priv->instat_urb->dev = serial->dev; |
2318 | dbg("%s - submit instat urb failed %d", __FUNCTION__, err); | 2680 | err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL); |
2681 | if (err != 0) | ||
2682 | dbg("%s - submit instat urb failed %d", __FUNCTION__, | ||
2683 | err); | ||
2684 | } | ||
2685 | if (s_priv->indat_urb != NULL) { | ||
2686 | s_priv->indat_urb->dev = serial->dev; | ||
2687 | err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL); | ||
2688 | if (err != 0) | ||
2689 | dbg("%s - submit indat urb failed %d", __FUNCTION__, | ||
2690 | err); | ||
2319 | } | 2691 | } |
2320 | 2692 | ||
2321 | return (0); | 2693 | return (0); |
@@ -2335,6 +2707,7 @@ static void keyspan_shutdown (struct usb_serial *serial) | |||
2335 | /* Stop reading/writing urbs */ | 2707 | /* Stop reading/writing urbs */ |
2336 | stop_urb(s_priv->instat_urb); | 2708 | stop_urb(s_priv->instat_urb); |
2337 | stop_urb(s_priv->glocont_urb); | 2709 | stop_urb(s_priv->glocont_urb); |
2710 | stop_urb(s_priv->indat_urb); | ||
2338 | for (i = 0; i < serial->num_ports; ++i) { | 2711 | for (i = 0; i < serial->num_ports; ++i) { |
2339 | port = serial->port[i]; | 2712 | port = serial->port[i]; |
2340 | p_priv = usb_get_serial_port_data(port); | 2713 | p_priv = usb_get_serial_port_data(port); |
@@ -2348,6 +2721,7 @@ static void keyspan_shutdown (struct usb_serial *serial) | |||
2348 | 2721 | ||
2349 | /* Now free them */ | 2722 | /* Now free them */ |
2350 | usb_free_urb(s_priv->instat_urb); | 2723 | usb_free_urb(s_priv->instat_urb); |
2724 | usb_free_urb(s_priv->indat_urb); | ||
2351 | usb_free_urb(s_priv->glocont_urb); | 2725 | usb_free_urb(s_priv->glocont_urb); |
2352 | for (i = 0; i < serial->num_ports; ++i) { | 2726 | for (i = 0; i < serial->num_ports; ++i) { |
2353 | port = serial->port[i]; | 2727 | port = serial->port[i]; |
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index c6830cbdc6df..8a0d17401529 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h | |||
@@ -99,6 +99,10 @@ static int keyspan_usa90_send_setup (struct usb_serial *serial, | |||
99 | struct usb_serial_port *port, | 99 | struct usb_serial_port *port, |
100 | int reset_port); | 100 | int reset_port); |
101 | 101 | ||
102 | static int keyspan_usa67_send_setup (struct usb_serial *serial, | ||
103 | struct usb_serial_port *port, | ||
104 | int reset_port); | ||
105 | |||
102 | /* Struct used for firmware - increased size of data section | 106 | /* Struct used for firmware - increased size of data section |
103 | to allow Keyspan's 'C' firmware struct to be used unmodified */ | 107 | to allow Keyspan's 'C' firmware struct to be used unmodified */ |
104 | struct ezusb_hex_record { | 108 | struct ezusb_hex_record { |
@@ -229,15 +233,17 @@ struct ezusb_hex_record { | |||
229 | #define keyspan_usa28_product_id 0x010f | 233 | #define keyspan_usa28_product_id 0x010f |
230 | #define keyspan_usa28x_product_id 0x0110 | 234 | #define keyspan_usa28x_product_id 0x0110 |
231 | #define keyspan_usa28xa_product_id 0x0115 | 235 | #define keyspan_usa28xa_product_id 0x0115 |
236 | #define keyspan_usa28xb_product_id 0x0110 | ||
237 | #define keyspan_usa28xg_product_id 0x0135 | ||
232 | #define keyspan_usa49w_product_id 0x010a | 238 | #define keyspan_usa49w_product_id 0x010a |
233 | #define keyspan_usa49wlc_product_id 0x012a | 239 | #define keyspan_usa49wlc_product_id 0x012a |
234 | 240 | #define keyspan_usa49wg_product_id 0x0131 | |
235 | 241 | ||
236 | struct keyspan_device_details { | 242 | struct keyspan_device_details { |
237 | /* product ID value */ | 243 | /* product ID value */ |
238 | int product_id; | 244 | int product_id; |
239 | 245 | ||
240 | enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90} msg_format; | 246 | enum {msg_usa26, msg_usa28, msg_usa49, msg_usa90, msg_usa67} msg_format; |
241 | 247 | ||
242 | /* Number of physical ports */ | 248 | /* Number of physical ports */ |
243 | int num_ports; | 249 | int num_ports; |
@@ -264,6 +270,9 @@ struct keyspan_device_details { | |||
264 | /* Endpoint used for input status */ | 270 | /* Endpoint used for input status */ |
265 | int instat_endpoint; | 271 | int instat_endpoint; |
266 | 272 | ||
273 | /* Endpoint used for input data 49WG only */ | ||
274 | int indat_endpoint; | ||
275 | |||
267 | /* Endpoint used for global control functions */ | 276 | /* Endpoint used for global control functions */ |
268 | int glocont_endpoint; | 277 | int glocont_endpoint; |
269 | 278 | ||
@@ -287,6 +296,7 @@ static const struct keyspan_device_details usa18x_device_details = { | |||
287 | .inack_endpoints = {0x85}, | 296 | .inack_endpoints = {0x85}, |
288 | .outcont_endpoints = {0x05}, | 297 | .outcont_endpoints = {0x05}, |
289 | .instat_endpoint = 0x87, | 298 | .instat_endpoint = 0x87, |
299 | .indat_endpoint = -1, | ||
290 | .glocont_endpoint = 0x07, | 300 | .glocont_endpoint = 0x07, |
291 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 301 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
292 | .baudclk = KEYSPAN_USA18X_BAUDCLK, | 302 | .baudclk = KEYSPAN_USA18X_BAUDCLK, |
@@ -303,6 +313,7 @@ static const struct keyspan_device_details usa19_device_details = { | |||
303 | .inack_endpoints = {0x83}, | 313 | .inack_endpoints = {0x83}, |
304 | .outcont_endpoints = {0x03}, | 314 | .outcont_endpoints = {0x03}, |
305 | .instat_endpoint = 0x84, | 315 | .instat_endpoint = 0x84, |
316 | .indat_endpoint = -1, | ||
306 | .glocont_endpoint = -1, | 317 | .glocont_endpoint = -1, |
307 | .calculate_baud_rate = keyspan_usa19_calc_baud, | 318 | .calculate_baud_rate = keyspan_usa19_calc_baud, |
308 | .baudclk = KEYSPAN_USA19_BAUDCLK, | 319 | .baudclk = KEYSPAN_USA19_BAUDCLK, |
@@ -319,6 +330,7 @@ static const struct keyspan_device_details usa19qi_device_details = { | |||
319 | .inack_endpoints = {0x83}, | 330 | .inack_endpoints = {0x83}, |
320 | .outcont_endpoints = {0x03}, | 331 | .outcont_endpoints = {0x03}, |
321 | .instat_endpoint = 0x84, | 332 | .instat_endpoint = 0x84, |
333 | .indat_endpoint = -1, | ||
322 | .glocont_endpoint = -1, | 334 | .glocont_endpoint = -1, |
323 | .calculate_baud_rate = keyspan_usa28_calc_baud, | 335 | .calculate_baud_rate = keyspan_usa28_calc_baud, |
324 | .baudclk = KEYSPAN_USA19_BAUDCLK, | 336 | .baudclk = KEYSPAN_USA19_BAUDCLK, |
@@ -335,6 +347,7 @@ static const struct keyspan_device_details mpr_device_details = { | |||
335 | .inack_endpoints = {0x83}, | 347 | .inack_endpoints = {0x83}, |
336 | .outcont_endpoints = {0x03}, | 348 | .outcont_endpoints = {0x03}, |
337 | .instat_endpoint = 0x84, | 349 | .instat_endpoint = 0x84, |
350 | .indat_endpoint = -1, | ||
338 | .glocont_endpoint = -1, | 351 | .glocont_endpoint = -1, |
339 | .calculate_baud_rate = keyspan_usa28_calc_baud, | 352 | .calculate_baud_rate = keyspan_usa28_calc_baud, |
340 | .baudclk = KEYSPAN_USA19_BAUDCLK, | 353 | .baudclk = KEYSPAN_USA19_BAUDCLK, |
@@ -351,6 +364,7 @@ static const struct keyspan_device_details usa19qw_device_details = { | |||
351 | .inack_endpoints = {0x85}, | 364 | .inack_endpoints = {0x85}, |
352 | .outcont_endpoints = {0x05}, | 365 | .outcont_endpoints = {0x05}, |
353 | .instat_endpoint = 0x87, | 366 | .instat_endpoint = 0x87, |
367 | .indat_endpoint = -1, | ||
354 | .glocont_endpoint = 0x07, | 368 | .glocont_endpoint = 0x07, |
355 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 369 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
356 | .baudclk = KEYSPAN_USA19W_BAUDCLK, | 370 | .baudclk = KEYSPAN_USA19W_BAUDCLK, |
@@ -367,6 +381,7 @@ static const struct keyspan_device_details usa19w_device_details = { | |||
367 | .inack_endpoints = {0x85}, | 381 | .inack_endpoints = {0x85}, |
368 | .outcont_endpoints = {0x05}, | 382 | .outcont_endpoints = {0x05}, |
369 | .instat_endpoint = 0x87, | 383 | .instat_endpoint = 0x87, |
384 | .indat_endpoint = -1, | ||
370 | .glocont_endpoint = 0x07, | 385 | .glocont_endpoint = 0x07, |
371 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 386 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
372 | .baudclk = KEYSPAN_USA19W_BAUDCLK, | 387 | .baudclk = KEYSPAN_USA19W_BAUDCLK, |
@@ -383,6 +398,7 @@ static const struct keyspan_device_details usa19hs_device_details = { | |||
383 | .inack_endpoints = {-1}, | 398 | .inack_endpoints = {-1}, |
384 | .outcont_endpoints = {0x02}, | 399 | .outcont_endpoints = {0x02}, |
385 | .instat_endpoint = 0x82, | 400 | .instat_endpoint = 0x82, |
401 | .indat_endpoint = -1, | ||
386 | .glocont_endpoint = -1, | 402 | .glocont_endpoint = -1, |
387 | .calculate_baud_rate = keyspan_usa19hs_calc_baud, | 403 | .calculate_baud_rate = keyspan_usa19hs_calc_baud, |
388 | .baudclk = KEYSPAN_USA19HS_BAUDCLK, | 404 | .baudclk = KEYSPAN_USA19HS_BAUDCLK, |
@@ -399,6 +415,7 @@ static const struct keyspan_device_details usa28_device_details = { | |||
399 | .inack_endpoints = {0x85, 0x86}, | 415 | .inack_endpoints = {0x85, 0x86}, |
400 | .outcont_endpoints = {0x05, 0x06}, | 416 | .outcont_endpoints = {0x05, 0x06}, |
401 | .instat_endpoint = 0x87, | 417 | .instat_endpoint = 0x87, |
418 | .indat_endpoint = -1, | ||
402 | .glocont_endpoint = 0x07, | 419 | .glocont_endpoint = 0x07, |
403 | .calculate_baud_rate = keyspan_usa28_calc_baud, | 420 | .calculate_baud_rate = keyspan_usa28_calc_baud, |
404 | .baudclk = KEYSPAN_USA28_BAUDCLK, | 421 | .baudclk = KEYSPAN_USA28_BAUDCLK, |
@@ -415,6 +432,7 @@ static const struct keyspan_device_details usa28x_device_details = { | |||
415 | .inack_endpoints = {0x85, 0x86}, | 432 | .inack_endpoints = {0x85, 0x86}, |
416 | .outcont_endpoints = {0x05, 0x06}, | 433 | .outcont_endpoints = {0x05, 0x06}, |
417 | .instat_endpoint = 0x87, | 434 | .instat_endpoint = 0x87, |
435 | .indat_endpoint = -1, | ||
418 | .glocont_endpoint = 0x07, | 436 | .glocont_endpoint = 0x07, |
419 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 437 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
420 | .baudclk = KEYSPAN_USA28X_BAUDCLK, | 438 | .baudclk = KEYSPAN_USA28X_BAUDCLK, |
@@ -431,11 +449,28 @@ static const struct keyspan_device_details usa28xa_device_details = { | |||
431 | .inack_endpoints = {0x85, 0x86}, | 449 | .inack_endpoints = {0x85, 0x86}, |
432 | .outcont_endpoints = {0x05, 0x06}, | 450 | .outcont_endpoints = {0x05, 0x06}, |
433 | .instat_endpoint = 0x87, | 451 | .instat_endpoint = 0x87, |
452 | .indat_endpoint = -1, | ||
434 | .glocont_endpoint = 0x07, | 453 | .glocont_endpoint = 0x07, |
435 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 454 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
436 | .baudclk = KEYSPAN_USA28X_BAUDCLK, | 455 | .baudclk = KEYSPAN_USA28X_BAUDCLK, |
437 | }; | 456 | }; |
438 | 457 | ||
458 | static const struct keyspan_device_details usa28xg_device_details = { | ||
459 | .product_id = keyspan_usa28xg_product_id, | ||
460 | .msg_format = msg_usa67, | ||
461 | .num_ports = 2, | ||
462 | .indat_endp_flip = 0, | ||
463 | .outdat_endp_flip = 0, | ||
464 | .indat_endpoints = {0x84, 0x88}, | ||
465 | .outdat_endpoints = {0x02, 0x06}, | ||
466 | .inack_endpoints = {-1, -1}, | ||
467 | .outcont_endpoints = {-1, -1}, | ||
468 | .instat_endpoint = 0x81, | ||
469 | .indat_endpoint = -1, | ||
470 | .glocont_endpoint = 0x01, | ||
471 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | ||
472 | .baudclk = KEYSPAN_USA28X_BAUDCLK, | ||
473 | }; | ||
439 | /* We don't need a separate entry for the usa28xb as it appears as a 28x anyway */ | 474 | /* We don't need a separate entry for the usa28xb as it appears as a 28x anyway */ |
440 | 475 | ||
441 | static const struct keyspan_device_details usa49w_device_details = { | 476 | static const struct keyspan_device_details usa49w_device_details = { |
@@ -449,6 +484,7 @@ static const struct keyspan_device_details usa49w_device_details = { | |||
449 | .inack_endpoints = {-1, -1, -1, -1}, | 484 | .inack_endpoints = {-1, -1, -1, -1}, |
450 | .outcont_endpoints = {-1, -1, -1, -1}, | 485 | .outcont_endpoints = {-1, -1, -1, -1}, |
451 | .instat_endpoint = 0x87, | 486 | .instat_endpoint = 0x87, |
487 | .indat_endpoint = -1, | ||
452 | .glocont_endpoint = 0x07, | 488 | .glocont_endpoint = 0x07, |
453 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 489 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
454 | .baudclk = KEYSPAN_USA49W_BAUDCLK, | 490 | .baudclk = KEYSPAN_USA49W_BAUDCLK, |
@@ -465,11 +501,29 @@ static const struct keyspan_device_details usa49wlc_device_details = { | |||
465 | .inack_endpoints = {-1, -1, -1, -1}, | 501 | .inack_endpoints = {-1, -1, -1, -1}, |
466 | .outcont_endpoints = {-1, -1, -1, -1}, | 502 | .outcont_endpoints = {-1, -1, -1, -1}, |
467 | .instat_endpoint = 0x87, | 503 | .instat_endpoint = 0x87, |
504 | .indat_endpoint = -1, | ||
468 | .glocont_endpoint = 0x07, | 505 | .glocont_endpoint = 0x07, |
469 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | 506 | .calculate_baud_rate = keyspan_usa19w_calc_baud, |
470 | .baudclk = KEYSPAN_USA19W_BAUDCLK, | 507 | .baudclk = KEYSPAN_USA19W_BAUDCLK, |
471 | }; | 508 | }; |
472 | 509 | ||
510 | static const struct keyspan_device_details usa49wg_device_details = { | ||
511 | .product_id = keyspan_usa49wg_product_id, | ||
512 | .msg_format = msg_usa49, | ||
513 | .num_ports = 4, | ||
514 | .indat_endp_flip = 0, | ||
515 | .outdat_endp_flip = 0, | ||
516 | .indat_endpoints = {-1, -1, -1, -1}, /* single 'global' data in EP */ | ||
517 | .outdat_endpoints = {0x01, 0x02, 0x04, 0x06}, | ||
518 | .inack_endpoints = {-1, -1, -1, -1}, | ||
519 | .outcont_endpoints = {-1, -1, -1, -1}, | ||
520 | .instat_endpoint = 0x81, | ||
521 | .indat_endpoint = 0x88, | ||
522 | .glocont_endpoint = 0x00, /* uses control EP */ | ||
523 | .calculate_baud_rate = keyspan_usa19w_calc_baud, | ||
524 | .baudclk = KEYSPAN_USA19W_BAUDCLK, | ||
525 | }; | ||
526 | |||
473 | static const struct keyspan_device_details *keyspan_devices[] = { | 527 | static const struct keyspan_device_details *keyspan_devices[] = { |
474 | &usa18x_device_details, | 528 | &usa18x_device_details, |
475 | &usa19_device_details, | 529 | &usa19_device_details, |
@@ -481,9 +535,11 @@ static const struct keyspan_device_details *keyspan_devices[] = { | |||
481 | &usa28_device_details, | 535 | &usa28_device_details, |
482 | &usa28x_device_details, | 536 | &usa28x_device_details, |
483 | &usa28xa_device_details, | 537 | &usa28xa_device_details, |
538 | &usa28xg_device_details, | ||
484 | /* 28xb not required as it renumerates as a 28x */ | 539 | /* 28xb not required as it renumerates as a 28x */ |
485 | &usa49w_device_details, | 540 | &usa49w_device_details, |
486 | &usa49wlc_device_details, | 541 | &usa49wlc_device_details, |
542 | &usa49wg_device_details, | ||
487 | NULL, | 543 | NULL, |
488 | }; | 544 | }; |
489 | 545 | ||
@@ -510,8 +566,11 @@ static struct usb_device_id keyspan_ids_combined[] = { | |||
510 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, | 566 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, |
511 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, | 567 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, |
512 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, | 568 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, |
569 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, | ||
570 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) }, | ||
513 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)}, | 571 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id)}, |
514 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, | 572 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, |
573 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)}, | ||
515 | { } /* Terminating entry */ | 574 | { } /* Terminating entry */ |
516 | }; | 575 | }; |
517 | 576 | ||
@@ -557,12 +616,15 @@ static struct usb_device_id keyspan_2port_ids[] = { | |||
557 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, | 616 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28_product_id) }, |
558 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, | 617 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28x_product_id) }, |
559 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, | 618 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xa_product_id) }, |
619 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xb_product_id) }, | ||
620 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa28xg_product_id) }, | ||
560 | { } /* Terminating entry */ | 621 | { } /* Terminating entry */ |
561 | }; | 622 | }; |
562 | 623 | ||
563 | static struct usb_device_id keyspan_4port_ids[] = { | 624 | static struct usb_device_id keyspan_4port_ids[] = { |
564 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) }, | 625 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49w_product_id) }, |
565 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, | 626 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wlc_product_id)}, |
627 | { USB_DEVICE(KEYSPAN_VENDOR_ID, keyspan_usa49wg_product_id)}, | ||
566 | { } /* Terminating entry */ | 628 | { } /* Terminating entry */ |
567 | }; | 629 | }; |
568 | 630 | ||
@@ -573,7 +635,6 @@ static struct usb_serial_driver keyspan_pre_device = { | |||
573 | .name = "keyspan_no_firm", | 635 | .name = "keyspan_no_firm", |
574 | }, | 636 | }, |
575 | .description = "Keyspan - (without firmware)", | 637 | .description = "Keyspan - (without firmware)", |
576 | .usb_driver = &keyspan_driver, | ||
577 | .id_table = keyspan_pre_ids, | 638 | .id_table = keyspan_pre_ids, |
578 | .num_interrupt_in = NUM_DONT_CARE, | 639 | .num_interrupt_in = NUM_DONT_CARE, |
579 | .num_bulk_in = NUM_DONT_CARE, | 640 | .num_bulk_in = NUM_DONT_CARE, |
@@ -588,7 +649,6 @@ static struct usb_serial_driver keyspan_1port_device = { | |||
588 | .name = "keyspan_1", | 649 | .name = "keyspan_1", |
589 | }, | 650 | }, |
590 | .description = "Keyspan 1 port adapter", | 651 | .description = "Keyspan 1 port adapter", |
591 | .usb_driver = &keyspan_driver, | ||
592 | .id_table = keyspan_1port_ids, | 652 | .id_table = keyspan_1port_ids, |
593 | .num_interrupt_in = NUM_DONT_CARE, | 653 | .num_interrupt_in = NUM_DONT_CARE, |
594 | .num_bulk_in = NUM_DONT_CARE, | 654 | .num_bulk_in = NUM_DONT_CARE, |
@@ -616,7 +676,6 @@ static struct usb_serial_driver keyspan_2port_device = { | |||
616 | .name = "keyspan_2", | 676 | .name = "keyspan_2", |
617 | }, | 677 | }, |
618 | .description = "Keyspan 2 port adapter", | 678 | .description = "Keyspan 2 port adapter", |
619 | .usb_driver = &keyspan_driver, | ||
620 | .id_table = keyspan_2port_ids, | 679 | .id_table = keyspan_2port_ids, |
621 | .num_interrupt_in = NUM_DONT_CARE, | 680 | .num_interrupt_in = NUM_DONT_CARE, |
622 | .num_bulk_in = NUM_DONT_CARE, | 681 | .num_bulk_in = NUM_DONT_CARE, |
@@ -644,11 +703,10 @@ static struct usb_serial_driver keyspan_4port_device = { | |||
644 | .name = "keyspan_4", | 703 | .name = "keyspan_4", |
645 | }, | 704 | }, |
646 | .description = "Keyspan 4 port adapter", | 705 | .description = "Keyspan 4 port adapter", |
647 | .usb_driver = &keyspan_driver, | ||
648 | .id_table = keyspan_4port_ids, | 706 | .id_table = keyspan_4port_ids, |
649 | .num_interrupt_in = NUM_DONT_CARE, | 707 | .num_interrupt_in = NUM_DONT_CARE, |
650 | .num_bulk_in = 5, | 708 | .num_bulk_in = NUM_DONT_CARE, |
651 | .num_bulk_out = 5, | 709 | .num_bulk_out = NUM_DONT_CARE, |
652 | .num_ports = 4, | 710 | .num_ports = 4, |
653 | .open = keyspan_open, | 711 | .open = keyspan_open, |
654 | .close = keyspan_close, | 712 | .close = keyspan_close, |
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index dd0b66a6ed5d..be9ac20a8f10 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
@@ -218,11 +218,12 @@ static void keyspan_pda_rx_interrupt (struct urb *urb) | |||
218 | struct tty_struct *tty = port->tty; | 218 | struct tty_struct *tty = port->tty; |
219 | unsigned char *data = urb->transfer_buffer; | 219 | unsigned char *data = urb->transfer_buffer; |
220 | int i; | 220 | int i; |
221 | int status; | 221 | int retval; |
222 | int status = urb->status; | ||
222 | struct keyspan_pda_private *priv; | 223 | struct keyspan_pda_private *priv; |
223 | priv = usb_get_serial_port_data(port); | 224 | priv = usb_get_serial_port_data(port); |
224 | 225 | ||
225 | switch (urb->status) { | 226 | switch (status) { |
226 | case 0: | 227 | case 0: |
227 | /* success */ | 228 | /* success */ |
228 | break; | 229 | break; |
@@ -230,10 +231,12 @@ static void keyspan_pda_rx_interrupt (struct urb *urb) | |||
230 | case -ENOENT: | 231 | case -ENOENT: |
231 | case -ESHUTDOWN: | 232 | case -ESHUTDOWN: |
232 | /* this urb is terminated, clean up */ | 233 | /* this urb is terminated, clean up */ |
233 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 234 | dbg("%s - urb shutting down with status: %d", |
235 | __FUNCTION__, status); | ||
234 | return; | 236 | return; |
235 | default: | 237 | default: |
236 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 238 | dbg("%s - nonzero urb status received: %d", |
239 | __FUNCTION__, status); | ||
237 | goto exit; | 240 | goto exit; |
238 | } | 241 | } |
239 | 242 | ||
@@ -268,10 +271,10 @@ static void keyspan_pda_rx_interrupt (struct urb *urb) | |||
268 | } | 271 | } |
269 | 272 | ||
270 | exit: | 273 | exit: |
271 | status = usb_submit_urb (urb, GFP_ATOMIC); | 274 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
272 | if (status) | 275 | if (retval) |
273 | err ("%s - usb_submit_urb failed with result %d", | 276 | err ("%s - usb_submit_urb failed with result %d", |
274 | __FUNCTION__, status); | 277 | __FUNCTION__, retval); |
275 | } | 278 | } |
276 | 279 | ||
277 | 280 | ||
diff --git a/drivers/usb/serial/keyspan_usa67msg.h b/drivers/usb/serial/keyspan_usa67msg.h new file mode 100644 index 000000000000..20fa3e2f7187 --- /dev/null +++ b/drivers/usb/serial/keyspan_usa67msg.h | |||
@@ -0,0 +1,254 @@ | |||
1 | /* | ||
2 | usa67msg.h | ||
3 | |||
4 | Copyright (c) 1998-2007 InnoSys Incorporated. All Rights Reserved | ||
5 | This file is available under a BSD-style copyright | ||
6 | |||
7 | Keyspan USB Async Firmware to run on Anchor FX1 | ||
8 | |||
9 | Redistribution and use in source and binary forms, with or without | ||
10 | modification, are permitted provided that the following conditions are | ||
11 | met: | ||
12 | |||
13 | 1. Redistributions of source code must retain this licence text | ||
14 | without modification, this list of conditions, and the following | ||
15 | disclaimer. The following copyright notice must appear immediately at | ||
16 | the beginning of all source files: | ||
17 | |||
18 | Copyright (c) 1998-2007 InnoSys Incorporated. All Rights Reserved | ||
19 | |||
20 | This file is available under a BSD-style copyright | ||
21 | |||
22 | 2. Redistributions in binary form must reproduce the above copyright | ||
23 | notice, this list of conditions and the following disclaimer in the | ||
24 | documentation and/or other materials provided with the distribution. | ||
25 | |||
26 | 3. The name of InnoSys Incorprated may not be used to endorse or promote | ||
27 | products derived from this software without specific prior written | ||
28 | permission. | ||
29 | |||
30 | THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR | ||
31 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
32 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN | ||
33 | NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | ||
34 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
35 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
36 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
37 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
38 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
39 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
40 | SUCH DAMAGE. | ||
41 | |||
42 | Fourth revision: This message format supports the USA28XG | ||
43 | |||
44 | Buffer formats for RX/TX data messages are not defined by | ||
45 | a structure, but are described here: | ||
46 | |||
47 | USB OUT (host -> USAxx, transmit) messages contain a | ||
48 | REQUEST_ACK indicator (set to 0xff to request an ACK at the | ||
49 | completion of transmit; 0x00 otherwise), followed by data: | ||
50 | |||
51 | RQSTACK DAT DAT DAT ... | ||
52 | |||
53 | with a total data length of up to 63. | ||
54 | |||
55 | USB IN (USAxx -> host, receive) messages begin with a status | ||
56 | byte in which the 0x80 bit is either: | ||
57 | |||
58 | (a) 0x80 bit clear | ||
59 | indicates that the bytes following it are all data | ||
60 | bytes: | ||
61 | |||
62 | STAT DATA DATA DATA DATA DATA ... | ||
63 | |||
64 | for a total of up to 63 DATA bytes, | ||
65 | |||
66 | or: | ||
67 | |||
68 | (b) 0x80 bit set | ||
69 | indiates that the bytes following alternate data and | ||
70 | status bytes: | ||
71 | |||
72 | STAT DATA STAT DATA STAT DATA STAT DATA ... | ||
73 | |||
74 | for a total of up to 32 DATA bytes. | ||
75 | |||
76 | The valid bits in the STAT bytes are: | ||
77 | |||
78 | OVERRUN 0x02 | ||
79 | PARITY 0x04 | ||
80 | FRAMING 0x08 | ||
81 | BREAK 0x10 | ||
82 | |||
83 | Notes: | ||
84 | |||
85 | (1) The OVERRUN bit can appear in either (a) or (b) format | ||
86 | messages, but the but the PARITY/FRAMING/BREAK bits | ||
87 | only appear in (b) format messages. | ||
88 | (2) For the host to determine the exact point at which the | ||
89 | overrun occurred (to identify the point in the data | ||
90 | stream at which the data was lost), it needs to count | ||
91 | 128 characters, starting at the first character of the | ||
92 | message in which OVERRUN was reported; the lost character(s) | ||
93 | would have been received between the 128th and 129th | ||
94 | characters. | ||
95 | (3) An RX data message in which the first byte has 0x80 clear | ||
96 | serves as a "break off" indicator. | ||
97 | |||
98 | revision history: | ||
99 | |||
100 | 1999feb10 add reportHskiaChanges to allow us to ignore them | ||
101 | 1999feb10 add txAckThreshold for fast+loose throughput enhancement | ||
102 | 1999mar30 beef up support for RX error reporting | ||
103 | 1999apr14 add resetDataToggle to control message | ||
104 | 2000jan04 merge with usa17msg.h | ||
105 | 2000jun01 add extended BSD-style copyright text | ||
106 | 2001jul05 change message format to improve OVERRUN case | ||
107 | 2002jun05 update copyright date, improve comments | ||
108 | 2006feb06 modify for FX1 chip | ||
109 | |||
110 | */ | ||
111 | |||
112 | #ifndef __USA67MSG__ | ||
113 | #define __USA67MSG__ | ||
114 | |||
115 | |||
116 | // all things called "ControlMessage" are sent on the 'control' endpoint | ||
117 | |||
118 | typedef struct keyspan_usa67_portControlMessage | ||
119 | { | ||
120 | u8 port; // 0 or 1 (selects port) | ||
121 | /* | ||
122 | there are three types of "commands" sent in the control message: | ||
123 | |||
124 | 1. configuration changes which must be requested by setting | ||
125 | the corresponding "set" flag (and should only be requested | ||
126 | when necessary, to reduce overhead on the device): | ||
127 | */ | ||
128 | u8 setClocking, // host requests baud rate be set | ||
129 | baudLo, // host does baud divisor calculation | ||
130 | baudHi, // baudHi is only used for first port (gives lower rates) | ||
131 | externalClock_txClocking, | ||
132 | // 0=internal, other=external | ||
133 | |||
134 | setLcr, // host requests lcr be set | ||
135 | lcr, // use PARITY, STOPBITS, DATABITS below | ||
136 | |||
137 | setFlowControl, // host requests flow control be set | ||
138 | ctsFlowControl, // 1=use CTS flow control, 0=don't | ||
139 | xonFlowControl, // 1=use XON/XOFF flow control, 0=don't | ||
140 | xonChar, // specified in current character format | ||
141 | xoffChar, // specified in current character format | ||
142 | |||
143 | setTxTriState_setRts, | ||
144 | // host requests TX tri-state be set | ||
145 | txTriState_rts, // 1=active (normal), 0=tristate (off) | ||
146 | |||
147 | setHskoa_setDtr, | ||
148 | // host requests HSKOA output be set | ||
149 | hskoa_dtr, // 1=on, 0=off | ||
150 | |||
151 | setPrescaler, // host requests prescalar be set (default: 13) | ||
152 | prescaler; // specified as N/8; values 8-ff are valid | ||
153 | // must be set any time internal baud rate is set; | ||
154 | // must not be set when external clocking is used | ||
155 | |||
156 | /* | ||
157 | 3. configuration data which is simply used as is (no overhead, | ||
158 | but must be specified correctly in every host message). | ||
159 | */ | ||
160 | u8 forwardingLength, // forward when this number of chars available | ||
161 | reportHskiaChanges_dsrFlowControl, | ||
162 | // 1=normal; 0=ignore external clock | ||
163 | // 1=use DSR flow control, 0=don't | ||
164 | txAckThreshold, // 0=not allowed, 1=normal, 2-255 deliver ACK faster | ||
165 | loopbackMode; // 0=no loopback, 1=loopback enabled | ||
166 | |||
167 | /* | ||
168 | 4. commands which are flags only; these are processed in order | ||
169 | (so that, e.g., if both _txOn and _txOff flags are set, the | ||
170 | port ends in a TX_OFF state); any non-zero value is respected | ||
171 | */ | ||
172 | u8 _txOn, // enable transmitting (and continue if there's data) | ||
173 | _txOff, // stop transmitting | ||
174 | txFlush, // toss outbound data | ||
175 | txBreak, // turn on break (cleared by _txOn) | ||
176 | rxOn, // turn on receiver | ||
177 | rxOff, // turn off receiver | ||
178 | rxFlush, // toss inbound data | ||
179 | rxForward, // forward all inbound data, NOW (as if fwdLen==1) | ||
180 | returnStatus, // return current status (even if it hasn't changed) | ||
181 | resetDataToggle;// reset data toggle state to DATA0 | ||
182 | |||
183 | } keyspan_usa67_portControlMessage; | ||
184 | |||
185 | // defines for bits in lcr | ||
186 | #define USA_DATABITS_5 0x00 | ||
187 | #define USA_DATABITS_6 0x01 | ||
188 | #define USA_DATABITS_7 0x02 | ||
189 | #define USA_DATABITS_8 0x03 | ||
190 | #define STOPBITS_5678_1 0x00 // 1 stop bit for all byte sizes | ||
191 | #define STOPBITS_5_1p5 0x04 // 1.5 stop bits for 5-bit byte | ||
192 | #define STOPBITS_678_2 0x04 // 2 stop bits for 6/7/8-bit byte | ||
193 | #define USA_PARITY_NONE 0x00 | ||
194 | #define USA_PARITY_ODD 0x08 | ||
195 | #define USA_PARITY_EVEN 0x18 | ||
196 | #define PARITY_1 0x28 | ||
197 | #define PARITY_0 0x38 | ||
198 | |||
199 | // all things called "StatusMessage" are sent on the status endpoint | ||
200 | |||
201 | typedef struct keyspan_usa67_portStatusMessage // one for each port | ||
202 | { | ||
203 | u8 port, // 0=first, 1=second, other=see below | ||
204 | hskia_cts, // reports HSKIA pin | ||
205 | gpia_dcd, // reports GPIA pin | ||
206 | _txOff, // port has been disabled (by host) | ||
207 | _txXoff, // port is in XOFF state (either host or RX XOFF) | ||
208 | txAck, // indicates a TX message acknowledgement | ||
209 | rxEnabled, // as configured by rxOn/rxOff 1=on, 0=off | ||
210 | controlResponse;// 1=a control message has been processed | ||
211 | } keyspan_usa67_portStatusMessage; | ||
212 | |||
213 | // bits in RX data message when STAT byte is included | ||
214 | #define RXERROR_OVERRUN 0x02 | ||
215 | #define RXERROR_PARITY 0x04 | ||
216 | #define RXERROR_FRAMING 0x08 | ||
217 | #define RXERROR_BREAK 0x10 | ||
218 | |||
219 | typedef struct keyspan_usa67_globalControlMessage | ||
220 | { | ||
221 | u8 port, // 3 | ||
222 | sendGlobalStatus, // 2=request for two status responses | ||
223 | resetStatusToggle, // 1=reset global status toggle | ||
224 | resetStatusCount; // a cycling value | ||
225 | } keyspan_usa67_globalControlMessage; | ||
226 | |||
227 | typedef struct keyspan_usa67_globalStatusMessage | ||
228 | { | ||
229 | u8 port, // 3 | ||
230 | sendGlobalStatus, // from request, decremented | ||
231 | resetStatusCount; // as in request | ||
232 | } keyspan_usa67_globalStatusMessage; | ||
233 | |||
234 | typedef struct keyspan_usa67_globalDebugMessage | ||
235 | { | ||
236 | u8 port, // 2 | ||
237 | a, | ||
238 | b, | ||
239 | c, | ||
240 | d; | ||
241 | } keyspan_usa67_globalDebugMessage; | ||
242 | |||
243 | // ie: the maximum length of an FX1 endpoint buffer | ||
244 | #define MAX_DATA_LEN 64 | ||
245 | |||
246 | // update status approx. 60 times a second (16.6666 ms) | ||
247 | #define STATUS_UPDATE_INTERVAL 16 | ||
248 | |||
249 | // status rationing tuning value (each port gets checked each n ms) | ||
250 | #define STATUS_RATION 10 | ||
251 | |||
252 | #endif | ||
253 | |||
254 | |||
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 7b085f334ceb..5a4127e62c4a 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c | |||
@@ -567,12 +567,13 @@ exit: | |||
567 | static void klsi_105_write_bulk_callback ( struct urb *urb) | 567 | static void klsi_105_write_bulk_callback ( struct urb *urb) |
568 | { | 568 | { |
569 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 569 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
570 | int status = urb->status; | ||
570 | 571 | ||
571 | dbg("%s - port %d", __FUNCTION__, port->number); | 572 | dbg("%s - port %d", __FUNCTION__, port->number); |
572 | 573 | ||
573 | if (urb->status) { | 574 | if (status) { |
574 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, | 575 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, |
575 | urb->status); | 576 | status); |
576 | return; | 577 | return; |
577 | } | 578 | } |
578 | 579 | ||
@@ -631,16 +632,17 @@ static void klsi_105_read_bulk_callback (struct urb *urb) | |||
631 | struct tty_struct *tty; | 632 | struct tty_struct *tty; |
632 | unsigned char *data = urb->transfer_buffer; | 633 | unsigned char *data = urb->transfer_buffer; |
633 | int rc; | 634 | int rc; |
635 | int status = urb->status; | ||
634 | 636 | ||
635 | dbg("%s - port %d", __FUNCTION__, port->number); | 637 | dbg("%s - port %d", __FUNCTION__, port->number); |
636 | 638 | ||
637 | /* The urb might have been killed. */ | 639 | /* The urb might have been killed. */ |
638 | if (urb->status) { | 640 | if (status) { |
639 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, | 641 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, |
640 | urb->status); | 642 | status); |
641 | return; | 643 | return; |
642 | } | 644 | } |
643 | 645 | ||
644 | /* The data received is again preceded by a length double-byte in LSB- | 646 | /* The data received is again preceded by a length double-byte in LSB- |
645 | * first order (see klsi_105_write() ) | 647 | * first order (see klsi_105_write() ) |
646 | */ | 648 | */ |
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 0683b51f0932..02a86dbc0e97 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c | |||
@@ -358,24 +358,26 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp) | |||
358 | } | 358 | } |
359 | 359 | ||
360 | 360 | ||
361 | static void kobil_read_int_callback( struct urb *purb) | 361 | static void kobil_read_int_callback(struct urb *urb) |
362 | { | 362 | { |
363 | int result; | 363 | int result; |
364 | struct usb_serial_port *port = (struct usb_serial_port *) purb->context; | 364 | struct usb_serial_port *port = urb->context; |
365 | struct tty_struct *tty; | 365 | struct tty_struct *tty; |
366 | unsigned char *data = purb->transfer_buffer; | 366 | unsigned char *data = urb->transfer_buffer; |
367 | int status = urb->status; | ||
367 | // char *dbg_data; | 368 | // char *dbg_data; |
368 | 369 | ||
369 | dbg("%s - port %d", __FUNCTION__, port->number); | 370 | dbg("%s - port %d", __FUNCTION__, port->number); |
370 | 371 | ||
371 | if (purb->status) { | 372 | if (status) { |
372 | dbg("%s - port %d Read int status not zero: %d", __FUNCTION__, port->number, purb->status); | 373 | dbg("%s - port %d Read int status not zero: %d", |
374 | __FUNCTION__, port->number, status); | ||
373 | return; | 375 | return; |
374 | } | 376 | } |
375 | 377 | ||
376 | tty = port->tty; | 378 | tty = port->tty; |
377 | if (purb->actual_length) { | 379 | if (urb->actual_length) { |
378 | 380 | ||
379 | // BEGIN DEBUG | 381 | // BEGIN DEBUG |
380 | /* | 382 | /* |
381 | dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); | 383 | dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); |
@@ -390,15 +392,15 @@ static void kobil_read_int_callback( struct urb *purb) | |||
390 | */ | 392 | */ |
391 | // END DEBUG | 393 | // END DEBUG |
392 | 394 | ||
393 | tty_buffer_request_room(tty, purb->actual_length); | 395 | tty_buffer_request_room(tty, urb->actual_length); |
394 | tty_insert_flip_string(tty, data, purb->actual_length); | 396 | tty_insert_flip_string(tty, data, urb->actual_length); |
395 | tty_flip_buffer_push(tty); | 397 | tty_flip_buffer_push(tty); |
396 | } | 398 | } |
397 | 399 | ||
398 | // someone sets the dev to 0 if the close method has been called | 400 | // someone sets the dev to 0 if the close method has been called |
399 | port->interrupt_in_urb->dev = port->serial->dev; | 401 | port->interrupt_in_urb->dev = port->serial->dev; |
400 | 402 | ||
401 | result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); | 403 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); |
402 | dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result); | 404 | dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result); |
403 | } | 405 | } |
404 | 406 | ||
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 3db1adc25f84..2a3fabcf5186 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c | |||
@@ -81,7 +81,7 @@ | |||
81 | /* | 81 | /* |
82 | * Version Information | 82 | * Version Information |
83 | */ | 83 | */ |
84 | #define DRIVER_VERSION "z2.0" /* Linux in-kernel version */ | 84 | #define DRIVER_VERSION "z2.1" /* Linux in-kernel version */ |
85 | #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>" | 85 | #define DRIVER_AUTHOR "Wolfgang Grandegger <wolfgang@ces.ch>" |
86 | #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" | 86 | #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" |
87 | 87 | ||
@@ -110,6 +110,10 @@ static int mct_u232_tiocmget (struct usb_serial_port *port, | |||
110 | static int mct_u232_tiocmset (struct usb_serial_port *port, | 110 | static int mct_u232_tiocmset (struct usb_serial_port *port, |
111 | struct file *file, unsigned int set, | 111 | struct file *file, unsigned int set, |
112 | unsigned int clear); | 112 | unsigned int clear); |
113 | static void mct_u232_throttle (struct usb_serial_port *port); | ||
114 | static void mct_u232_unthrottle (struct usb_serial_port *port); | ||
115 | |||
116 | |||
113 | /* | 117 | /* |
114 | * All of the device info needed for the MCT USB-RS232 converter. | 118 | * All of the device info needed for the MCT USB-RS232 converter. |
115 | */ | 119 | */ |
@@ -145,6 +149,8 @@ static struct usb_serial_driver mct_u232_device = { | |||
145 | .num_ports = 1, | 149 | .num_ports = 1, |
146 | .open = mct_u232_open, | 150 | .open = mct_u232_open, |
147 | .close = mct_u232_close, | 151 | .close = mct_u232_close, |
152 | .throttle = mct_u232_throttle, | ||
153 | .unthrottle = mct_u232_unthrottle, | ||
148 | .read_int_callback = mct_u232_read_int_callback, | 154 | .read_int_callback = mct_u232_read_int_callback, |
149 | .ioctl = mct_u232_ioctl, | 155 | .ioctl = mct_u232_ioctl, |
150 | .set_termios = mct_u232_set_termios, | 156 | .set_termios = mct_u232_set_termios, |
@@ -162,8 +168,11 @@ struct mct_u232_private { | |||
162 | unsigned char last_lcr; /* Line Control Register */ | 168 | unsigned char last_lcr; /* Line Control Register */ |
163 | unsigned char last_lsr; /* Line Status Register */ | 169 | unsigned char last_lsr; /* Line Status Register */ |
164 | unsigned char last_msr; /* Modem Status Register */ | 170 | unsigned char last_msr; /* Modem Status Register */ |
171 | unsigned int rx_flags; /* Throttling flags */ | ||
165 | }; | 172 | }; |
166 | 173 | ||
174 | #define THROTTLED 0x01 | ||
175 | |||
167 | /* | 176 | /* |
168 | * Handle vendor specific USB requests | 177 | * Handle vendor specific USB requests |
169 | */ | 178 | */ |
@@ -216,11 +225,13 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) | |||
216 | } | 225 | } |
217 | } | 226 | } |
218 | 227 | ||
219 | static int mct_u232_set_baud_rate(struct usb_serial *serial, int value) | 228 | static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port, |
229 | int value) | ||
220 | { | 230 | { |
221 | __le32 divisor; | 231 | __le32 divisor; |
222 | int rc; | 232 | int rc; |
223 | unsigned char zero_byte = 0; | 233 | unsigned char zero_byte = 0; |
234 | unsigned char cts_enable_byte = 0; | ||
224 | 235 | ||
225 | divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value)); | 236 | divisor = cpu_to_le32(mct_u232_calculate_baud_rate(serial, value)); |
226 | 237 | ||
@@ -238,10 +249,17 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, int value) | |||
238 | 'baud rate change' message. The actual functionality of the | 249 | 'baud rate change' message. The actual functionality of the |
239 | request codes in these messages is not fully understood but these | 250 | request codes in these messages is not fully understood but these |
240 | particular codes are never seen in any operation besides a baud | 251 | particular codes are never seen in any operation besides a baud |
241 | rate change. Both of these messages send a single byte of data | 252 | rate change. Both of these messages send a single byte of data. |
242 | whose value is always zero. The second of these two extra messages | 253 | In the first message, the value of this byte is always zero. |
243 | is required in order for data to be properly written to an RS-232 | 254 | |
244 | device which does not assert the 'CTS' signal. */ | 255 | The second message has been determined experimentally to control |
256 | whether data will be transmitted to a device which is not asserting | ||
257 | the 'CTS' signal. If the second message's data byte is zero, data | ||
258 | will be transmitted even if 'CTS' is not asserted (i.e. no hardware | ||
259 | flow control). if the second message's data byte is nonzero (a value | ||
260 | of 1 is used by this driver), data will not be transmitted to a device | ||
261 | which is not asserting 'CTS'. | ||
262 | */ | ||
245 | 263 | ||
246 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 264 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
247 | MCT_U232_SET_UNKNOWN1_REQUEST, | 265 | MCT_U232_SET_UNKNOWN1_REQUEST, |
@@ -252,14 +270,19 @@ static int mct_u232_set_baud_rate(struct usb_serial *serial, int value) | |||
252 | err("Sending USB device request code %d failed (error = %d)", | 270 | err("Sending USB device request code %d failed (error = %d)", |
253 | MCT_U232_SET_UNKNOWN1_REQUEST, rc); | 271 | MCT_U232_SET_UNKNOWN1_REQUEST, rc); |
254 | 272 | ||
273 | if (port && C_CRTSCTS(port->tty)) { | ||
274 | cts_enable_byte = 1; | ||
275 | } | ||
276 | |||
277 | dbg("set_baud_rate: send second control message, data = %02X", cts_enable_byte); | ||
255 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), | 278 | rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), |
256 | MCT_U232_SET_UNKNOWN2_REQUEST, | 279 | MCT_U232_SET_CTS_REQUEST, |
257 | MCT_U232_SET_REQUEST_TYPE, | 280 | MCT_U232_SET_REQUEST_TYPE, |
258 | 0, 0, &zero_byte, MCT_U232_SET_UNKNOWN2_SIZE, | 281 | 0, 0, &cts_enable_byte, MCT_U232_SET_CTS_SIZE, |
259 | WDR_TIMEOUT); | 282 | WDR_TIMEOUT); |
260 | if (rc < 0) | 283 | if (rc < 0) |
261 | err("Sending USB device request code %d failed (error = %d)", | 284 | err("Sending USB device request code %d failed (error = %d)", |
262 | MCT_U232_SET_UNKNOWN2_REQUEST, rc); | 285 | MCT_U232_SET_CTS_REQUEST, rc); |
263 | 286 | ||
264 | return rc; | 287 | return rc; |
265 | } /* mct_u232_set_baud_rate */ | 288 | } /* mct_u232_set_baud_rate */ |
@@ -458,8 +481,25 @@ error: | |||
458 | 481 | ||
459 | static void mct_u232_close (struct usb_serial_port *port, struct file *filp) | 482 | static void mct_u232_close (struct usb_serial_port *port, struct file *filp) |
460 | { | 483 | { |
484 | unsigned int c_cflag; | ||
485 | unsigned long flags; | ||
486 | unsigned int control_state; | ||
487 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | ||
461 | dbg("%s port %d", __FUNCTION__, port->number); | 488 | dbg("%s port %d", __FUNCTION__, port->number); |
462 | 489 | ||
490 | if (port->tty) { | ||
491 | c_cflag = port->tty->termios->c_cflag; | ||
492 | if (c_cflag & HUPCL) { | ||
493 | /* drop DTR and RTS */ | ||
494 | spin_lock_irqsave(&priv->lock, flags); | ||
495 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); | ||
496 | control_state = priv->control_state; | ||
497 | spin_unlock_irqrestore(&priv->lock, flags); | ||
498 | mct_u232_set_modem_ctrl(port->serial, control_state); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | |||
463 | if (port->serial->dev) { | 503 | if (port->serial->dev) { |
464 | /* shutdown our urbs */ | 504 | /* shutdown our urbs */ |
465 | usb_kill_urb(port->write_urb); | 505 | usb_kill_urb(port->write_urb); |
@@ -476,10 +516,11 @@ static void mct_u232_read_int_callback (struct urb *urb) | |||
476 | struct usb_serial *serial = port->serial; | 516 | struct usb_serial *serial = port->serial; |
477 | struct tty_struct *tty; | 517 | struct tty_struct *tty; |
478 | unsigned char *data = urb->transfer_buffer; | 518 | unsigned char *data = urb->transfer_buffer; |
479 | int status; | 519 | int retval; |
520 | int status = urb->status; | ||
480 | unsigned long flags; | 521 | unsigned long flags; |
481 | 522 | ||
482 | switch (urb->status) { | 523 | switch (status) { |
483 | case 0: | 524 | case 0: |
484 | /* success */ | 525 | /* success */ |
485 | break; | 526 | break; |
@@ -487,10 +528,12 @@ static void mct_u232_read_int_callback (struct urb *urb) | |||
487 | case -ENOENT: | 528 | case -ENOENT: |
488 | case -ESHUTDOWN: | 529 | case -ESHUTDOWN: |
489 | /* this urb is terminated, clean up */ | 530 | /* this urb is terminated, clean up */ |
490 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); | 531 | dbg("%s - urb shutting down with status: %d", |
532 | __FUNCTION__, status); | ||
491 | return; | 533 | return; |
492 | default: | 534 | default: |
493 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 535 | dbg("%s - nonzero urb status received: %d", |
536 | __FUNCTION__, status); | ||
494 | goto exit; | 537 | goto exit; |
495 | } | 538 | } |
496 | 539 | ||
@@ -554,10 +597,10 @@ static void mct_u232_read_int_callback (struct urb *urb) | |||
554 | #endif | 597 | #endif |
555 | spin_unlock_irqrestore(&priv->lock, flags); | 598 | spin_unlock_irqrestore(&priv->lock, flags); |
556 | exit: | 599 | exit: |
557 | status = usb_submit_urb (urb, GFP_ATOMIC); | 600 | retval = usb_submit_urb (urb, GFP_ATOMIC); |
558 | if (status) | 601 | if (retval) |
559 | err ("%s - usb_submit_urb failed with result %d", | 602 | err ("%s - usb_submit_urb failed with result %d", |
560 | __FUNCTION__, status); | 603 | __FUNCTION__, retval); |
561 | } /* mct_u232_read_int_callback */ | 604 | } /* mct_u232_read_int_callback */ |
562 | 605 | ||
563 | static void mct_u232_set_termios (struct usb_serial_port *port, | 606 | static void mct_u232_set_termios (struct usb_serial_port *port, |
@@ -565,11 +608,10 @@ static void mct_u232_set_termios (struct usb_serial_port *port, | |||
565 | { | 608 | { |
566 | struct usb_serial *serial = port->serial; | 609 | struct usb_serial *serial = port->serial; |
567 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 610 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
568 | unsigned int iflag = port->tty->termios->c_iflag; | ||
569 | unsigned int cflag = port->tty->termios->c_cflag; | 611 | unsigned int cflag = port->tty->termios->c_cflag; |
570 | unsigned int old_cflag = old_termios->c_cflag; | 612 | unsigned int old_cflag = old_termios->c_cflag; |
571 | unsigned long flags; | 613 | unsigned long flags; |
572 | unsigned int control_state, new_state; | 614 | unsigned int control_state; |
573 | unsigned char last_lcr; | 615 | unsigned char last_lcr; |
574 | 616 | ||
575 | /* get a local copy of the current port settings */ | 617 | /* get a local copy of the current port settings */ |
@@ -585,18 +627,14 @@ static void mct_u232_set_termios (struct usb_serial_port *port, | |||
585 | * Premature optimization is the root of all evil. | 627 | * Premature optimization is the root of all evil. |
586 | */ | 628 | */ |
587 | 629 | ||
588 | /* reassert DTR and (maybe) RTS on transition from B0 */ | 630 | /* reassert DTR and RTS on transition from B0 */ |
589 | if ((old_cflag & CBAUD) == B0) { | 631 | if ((old_cflag & CBAUD) == B0) { |
590 | dbg("%s: baud was B0", __FUNCTION__); | 632 | dbg("%s: baud was B0", __FUNCTION__); |
591 | control_state |= TIOCM_DTR; | 633 | control_state |= TIOCM_DTR | TIOCM_RTS; |
592 | /* don't set RTS if using hardware flow control */ | ||
593 | if (!(old_cflag & CRTSCTS)) { | ||
594 | control_state |= TIOCM_RTS; | ||
595 | } | ||
596 | mct_u232_set_modem_ctrl(serial, control_state); | 634 | mct_u232_set_modem_ctrl(serial, control_state); |
597 | } | 635 | } |
598 | 636 | ||
599 | mct_u232_set_baud_rate(serial, cflag & CBAUD); | 637 | mct_u232_set_baud_rate(serial, port, cflag & CBAUD); |
600 | 638 | ||
601 | if ((cflag & CBAUD) == B0 ) { | 639 | if ((cflag & CBAUD) == B0 ) { |
602 | dbg("%s: baud is B0", __FUNCTION__); | 640 | dbg("%s: baud is B0", __FUNCTION__); |
@@ -638,21 +676,6 @@ static void mct_u232_set_termios (struct usb_serial_port *port, | |||
638 | 676 | ||
639 | mct_u232_set_line_ctrl(serial, last_lcr); | 677 | mct_u232_set_line_ctrl(serial, last_lcr); |
640 | 678 | ||
641 | /* | ||
642 | * Set flow control: well, I do not really now how to handle DTR/RTS. | ||
643 | * Just do what we have seen with SniffUSB on Win98. | ||
644 | */ | ||
645 | /* Drop DTR/RTS if no flow control otherwise assert */ | ||
646 | new_state = control_state; | ||
647 | if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS)) | ||
648 | new_state |= TIOCM_DTR | TIOCM_RTS; | ||
649 | else | ||
650 | new_state &= ~(TIOCM_DTR | TIOCM_RTS); | ||
651 | if (new_state != control_state) { | ||
652 | mct_u232_set_modem_ctrl(serial, new_state); | ||
653 | control_state = new_state; | ||
654 | } | ||
655 | |||
656 | /* save off the modified port settings */ | 679 | /* save off the modified port settings */ |
657 | spin_lock_irqsave(&priv->lock, flags); | 680 | spin_lock_irqsave(&priv->lock, flags); |
658 | priv->control_state = control_state; | 681 | priv->control_state = control_state; |
@@ -747,6 +770,50 @@ static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, | |||
747 | return 0; | 770 | return 0; |
748 | } /* mct_u232_ioctl */ | 771 | } /* mct_u232_ioctl */ |
749 | 772 | ||
773 | static void mct_u232_throttle (struct usb_serial_port *port) | ||
774 | { | ||
775 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | ||
776 | unsigned long flags; | ||
777 | unsigned int control_state; | ||
778 | struct tty_struct *tty; | ||
779 | |||
780 | tty = port->tty; | ||
781 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
782 | |||
783 | spin_lock_irqsave(&priv->lock, flags); | ||
784 | priv->rx_flags |= THROTTLED; | ||
785 | if (C_CRTSCTS(tty)) { | ||
786 | priv->control_state &= ~TIOCM_RTS; | ||
787 | control_state = priv->control_state; | ||
788 | spin_unlock_irqrestore(&priv->lock, flags); | ||
789 | (void) mct_u232_set_modem_ctrl(port->serial, control_state); | ||
790 | } else { | ||
791 | spin_unlock_irqrestore(&priv->lock, flags); | ||
792 | } | ||
793 | } | ||
794 | |||
795 | |||
796 | static void mct_u232_unthrottle (struct usb_serial_port *port) | ||
797 | { | ||
798 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | ||
799 | unsigned long flags; | ||
800 | unsigned int control_state; | ||
801 | struct tty_struct *tty; | ||
802 | |||
803 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
804 | |||
805 | tty = port->tty; | ||
806 | spin_lock_irqsave(&priv->lock, flags); | ||
807 | if ((priv->rx_flags & THROTTLED) && C_CRTSCTS(tty)) { | ||
808 | priv->rx_flags &= ~THROTTLED; | ||
809 | priv->control_state |= TIOCM_RTS; | ||
810 | control_state = priv->control_state; | ||
811 | spin_unlock_irqrestore(&priv->lock, flags); | ||
812 | (void) mct_u232_set_modem_ctrl(port->serial, control_state); | ||
813 | } else { | ||
814 | spin_unlock_irqrestore(&priv->lock, flags); | ||
815 | } | ||
816 | } | ||
750 | 817 | ||
751 | static int __init mct_u232_init (void) | 818 | static int __init mct_u232_init (void) |
752 | { | 819 | { |
diff --git a/drivers/usb/serial/mct_u232.h b/drivers/usb/serial/mct_u232.h index 73dd0d984cd3..a61bac8f224a 100644 --- a/drivers/usb/serial/mct_u232.h +++ b/drivers/usb/serial/mct_u232.h | |||
@@ -63,14 +63,15 @@ | |||
63 | #define MCT_U232_SET_UNKNOWN1_REQUEST 11 /* Unknown functionality */ | 63 | #define MCT_U232_SET_UNKNOWN1_REQUEST 11 /* Unknown functionality */ |
64 | #define MCT_U232_SET_UNKNOWN1_SIZE 1 | 64 | #define MCT_U232_SET_UNKNOWN1_SIZE 1 |
65 | 65 | ||
66 | /* This USB device request code is not well understood. It is transmitted by | 66 | /* This USB device request code appears to control whether CTS is required |
67 | the MCT-supplied Windows driver whenever the baud rate changes. | 67 | during transmission. |
68 | 68 | ||
69 | Without this USB device request, the USB/RS-232 adapter will not write to | 69 | Sending a zero byte allows data transmission to a device which is not |
70 | RS-232 devices which do not assert the 'CTS' signal. | 70 | asserting CTS. Sending a '1' byte will cause transmission to be deferred |
71 | until the device asserts CTS. | ||
71 | */ | 72 | */ |
72 | #define MCT_U232_SET_UNKNOWN2_REQUEST 12 /* Unknown functionality */ | 73 | #define MCT_U232_SET_CTS_REQUEST 12 |
73 | #define MCT_U232_SET_UNKNOWN2_SIZE 1 | 74 | #define MCT_U232_SET_CTS_SIZE 1 |
74 | 75 | ||
75 | /* | 76 | /* |
76 | * Baud rate (divisor) | 77 | * Baud rate (divisor) |
@@ -439,7 +440,7 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value); | |||
439 | * which says "U232-P9" ;-) | 440 | * which says "U232-P9" ;-) |
440 | * | 441 | * |
441 | * The circuit board inside the adaptor contains a Philips PDIUSBD12 | 442 | * The circuit board inside the adaptor contains a Philips PDIUSBD12 |
442 | * USB endpoint chip and a Phillips P87C52UBAA microcontroller with | 443 | * USB endpoint chip and a Philips P87C52UBAA microcontroller with |
443 | * embedded UART. Exhaustive documentation for these is available at: | 444 | * embedded UART. Exhaustive documentation for these is available at: |
444 | * | 445 | * |
445 | * http://www.semiconductors.philips.com/pip/p87c52ubaa | 446 | * http://www.semiconductors.philips.com/pip/p87c52ubaa |
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index b563e2ad8728..231b584f6d0f 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c | |||
@@ -9,9 +9,9 @@ | |||
9 | * the Free Software Foundation, version 2 of the License. | 9 | * the Free Software Foundation, version 2 of the License. |
10 | * | 10 | * |
11 | * Developed by: | 11 | * Developed by: |
12 | * VijayaKumar.G.N. <vijaykumar@aspirecom.net> | 12 | * Vijaya Kumar <vijaykumar.gn@gmail.com> |
13 | * AjayKumar <ajay@aspirecom.net> | 13 | * Ajay Kumar <naanuajay@yahoo.com> |
14 | * Gurudeva.N. <gurudev@aspirecom.net> | 14 | * Gurudeva <ngurudeva@yahoo.com> |
15 | * | 15 | * |
16 | * Cleaned up from the original by: | 16 | * Cleaned up from the original by: |
17 | * Greg Kroah-Hartman <gregkh@suse.de> | 17 | * Greg Kroah-Hartman <gregkh@suse.de> |
@@ -103,6 +103,7 @@ static void mos7720_interrupt_callback(struct urb *urb) | |||
103 | { | 103 | { |
104 | int result; | 104 | int result; |
105 | int length; | 105 | int length; |
106 | int status = urb->status; | ||
106 | __u8 *data; | 107 | __u8 *data; |
107 | __u8 sp1; | 108 | __u8 sp1; |
108 | __u8 sp2; | 109 | __u8 sp2; |
@@ -114,7 +115,7 @@ static void mos7720_interrupt_callback(struct urb *urb) | |||
114 | return; | 115 | return; |
115 | } | 116 | } |
116 | 117 | ||
117 | switch (urb->status) { | 118 | switch (status) { |
118 | case 0: | 119 | case 0: |
119 | /* success */ | 120 | /* success */ |
120 | break; | 121 | break; |
@@ -123,11 +124,11 @@ static void mos7720_interrupt_callback(struct urb *urb) | |||
123 | case -ESHUTDOWN: | 124 | case -ESHUTDOWN: |
124 | /* this urb is terminated, clean up */ | 125 | /* this urb is terminated, clean up */ |
125 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, | 126 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, |
126 | urb->status); | 127 | status); |
127 | return; | 128 | return; |
128 | default: | 129 | default: |
129 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, | 130 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, |
130 | urb->status); | 131 | status); |
131 | goto exit; | 132 | goto exit; |
132 | } | 133 | } |
133 | 134 | ||
@@ -198,14 +199,15 @@ exit: | |||
198 | */ | 199 | */ |
199 | static void mos7720_bulk_in_callback(struct urb *urb) | 200 | static void mos7720_bulk_in_callback(struct urb *urb) |
200 | { | 201 | { |
201 | int status; | 202 | int retval; |
202 | unsigned char *data ; | 203 | unsigned char *data ; |
203 | struct usb_serial_port *port; | 204 | struct usb_serial_port *port; |
204 | struct moschip_port *mos7720_port; | 205 | struct moschip_port *mos7720_port; |
205 | struct tty_struct *tty; | 206 | struct tty_struct *tty; |
207 | int status = urb->status; | ||
206 | 208 | ||
207 | if (urb->status) { | 209 | if (status) { |
208 | dbg("nonzero read bulk status received: %d",urb->status); | 210 | dbg("nonzero read bulk status received: %d", status); |
209 | return; | 211 | return; |
210 | } | 212 | } |
211 | 213 | ||
@@ -236,10 +238,10 @@ static void mos7720_bulk_in_callback(struct urb *urb) | |||
236 | if (port->read_urb->status != -EINPROGRESS) { | 238 | if (port->read_urb->status != -EINPROGRESS) { |
237 | port->read_urb->dev = port->serial->dev; | 239 | port->read_urb->dev = port->serial->dev; |
238 | 240 | ||
239 | status = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 241 | retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
240 | if (status) | 242 | if (retval) |
241 | dbg("usb_submit_urb(read bulk) failed, status = %d", | 243 | dbg("usb_submit_urb(read bulk) failed, retval = %d", |
242 | status); | 244 | retval); |
243 | } | 245 | } |
244 | } | 246 | } |
245 | 247 | ||
@@ -252,9 +254,10 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) | |||
252 | { | 254 | { |
253 | struct moschip_port *mos7720_port; | 255 | struct moschip_port *mos7720_port; |
254 | struct tty_struct *tty; | 256 | struct tty_struct *tty; |
257 | int status = urb->status; | ||
255 | 258 | ||
256 | if (urb->status) { | 259 | if (status) { |
257 | dbg("nonzero write bulk status received:%d", urb->status); | 260 | dbg("nonzero write bulk status received:%d", status); |
258 | return; | 261 | return; |
259 | } | 262 | } |
260 | 263 | ||
@@ -1235,16 +1238,6 @@ static void mos7720_set_termios(struct usb_serial_port *port, | |||
1235 | return; | 1238 | return; |
1236 | } | 1239 | } |
1237 | 1240 | ||
1238 | /* check that they really want us to change something */ | ||
1239 | if (old_termios) { | ||
1240 | if ((cflag == old_termios->c_cflag) && | ||
1241 | (RELEVANT_IFLAG(tty->termios->c_iflag) == | ||
1242 | RELEVANT_IFLAG(old_termios->c_iflag))) { | ||
1243 | dbg("Nothing to change"); | ||
1244 | return; | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1248 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, | 1241 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, |
1249 | tty->termios->c_cflag, | 1242 | tty->termios->c_cflag, |
1250 | RELEVANT_IFLAG(tty->termios->c_iflag)); | 1243 | RELEVANT_IFLAG(tty->termios->c_iflag)); |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 36620c651079..37f41f576d3d 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -434,6 +434,7 @@ static void mos7840_control_callback(struct urb *urb) | |||
434 | struct moschip_port *mos7840_port; | 434 | struct moschip_port *mos7840_port; |
435 | __u8 regval = 0x0; | 435 | __u8 regval = 0x0; |
436 | int result = 0; | 436 | int result = 0; |
437 | int status = urb->status; | ||
437 | 438 | ||
438 | if (!urb) { | 439 | if (!urb) { |
439 | dbg("%s", "Invalid Pointer !!!!:\n"); | 440 | dbg("%s", "Invalid Pointer !!!!:\n"); |
@@ -442,7 +443,7 @@ static void mos7840_control_callback(struct urb *urb) | |||
442 | 443 | ||
443 | mos7840_port = (struct moschip_port *)urb->context; | 444 | mos7840_port = (struct moschip_port *)urb->context; |
444 | 445 | ||
445 | switch (urb->status) { | 446 | switch (status) { |
446 | case 0: | 447 | case 0: |
447 | /* success */ | 448 | /* success */ |
448 | break; | 449 | break; |
@@ -451,11 +452,11 @@ static void mos7840_control_callback(struct urb *urb) | |||
451 | case -ESHUTDOWN: | 452 | case -ESHUTDOWN: |
452 | /* this urb is terminated, clean up */ | 453 | /* this urb is terminated, clean up */ |
453 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, | 454 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, |
454 | urb->status); | 455 | status); |
455 | return; | 456 | return; |
456 | default: | 457 | default: |
457 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, | 458 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, |
458 | urb->status); | 459 | status); |
459 | goto exit; | 460 | goto exit; |
460 | } | 461 | } |
461 | 462 | ||
@@ -521,6 +522,7 @@ static void mos7840_interrupt_callback(struct urb *urb) | |||
521 | __u8 sp[5], st; | 522 | __u8 sp[5], st; |
522 | int i, rv = 0; | 523 | int i, rv = 0; |
523 | __u16 wval, wreg = 0; | 524 | __u16 wval, wreg = 0; |
525 | int status = urb->status; | ||
524 | 526 | ||
525 | dbg("%s", " : Entering\n"); | 527 | dbg("%s", " : Entering\n"); |
526 | if (!urb) { | 528 | if (!urb) { |
@@ -528,7 +530,7 @@ static void mos7840_interrupt_callback(struct urb *urb) | |||
528 | return; | 530 | return; |
529 | } | 531 | } |
530 | 532 | ||
531 | switch (urb->status) { | 533 | switch (status) { |
532 | case 0: | 534 | case 0: |
533 | /* success */ | 535 | /* success */ |
534 | break; | 536 | break; |
@@ -537,11 +539,11 @@ static void mos7840_interrupt_callback(struct urb *urb) | |||
537 | case -ESHUTDOWN: | 539 | case -ESHUTDOWN: |
538 | /* this urb is terminated, clean up */ | 540 | /* this urb is terminated, clean up */ |
539 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, | 541 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, |
540 | urb->status); | 542 | status); |
541 | return; | 543 | return; |
542 | default: | 544 | default: |
543 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, | 545 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, |
544 | urb->status); | 546 | status); |
545 | goto exit; | 547 | goto exit; |
546 | } | 548 | } |
547 | 549 | ||
@@ -666,20 +668,21 @@ static struct usb_serial *mos7840_get_usb_serial(struct usb_serial_port *port, | |||
666 | 668 | ||
667 | static void mos7840_bulk_in_callback(struct urb *urb) | 669 | static void mos7840_bulk_in_callback(struct urb *urb) |
668 | { | 670 | { |
669 | int status; | 671 | int retval; |
670 | unsigned char *data; | 672 | unsigned char *data; |
671 | struct usb_serial *serial; | 673 | struct usb_serial *serial; |
672 | struct usb_serial_port *port; | 674 | struct usb_serial_port *port; |
673 | struct moschip_port *mos7840_port; | 675 | struct moschip_port *mos7840_port; |
674 | struct tty_struct *tty; | 676 | struct tty_struct *tty; |
677 | int status = urb->status; | ||
675 | 678 | ||
676 | if (!urb) { | 679 | if (!urb) { |
677 | dbg("%s", "Invalid Pointer !!!!:\n"); | 680 | dbg("%s", "Invalid Pointer !!!!:\n"); |
678 | return; | 681 | return; |
679 | } | 682 | } |
680 | 683 | ||
681 | if (urb->status) { | 684 | if (status) { |
682 | dbg("nonzero read bulk status received: %d", urb->status); | 685 | dbg("nonzero read bulk status received: %d", status); |
683 | return; | 686 | return; |
684 | } | 687 | } |
685 | 688 | ||
@@ -729,11 +732,11 @@ static void mos7840_bulk_in_callback(struct urb *urb) | |||
729 | 732 | ||
730 | mos7840_port->read_urb->dev = serial->dev; | 733 | mos7840_port->read_urb->dev = serial->dev; |
731 | 734 | ||
732 | status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); | 735 | retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); |
733 | 736 | ||
734 | if (status) { | 737 | if (retval) { |
735 | dbg(" usb_submit_urb(read bulk) failed, status = %d", | 738 | dbg(" usb_submit_urb(read bulk) failed, retval = %d", |
736 | status); | 739 | retval); |
737 | } | 740 | } |
738 | } | 741 | } |
739 | 742 | ||
@@ -747,6 +750,7 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) | |||
747 | { | 750 | { |
748 | struct moschip_port *mos7840_port; | 751 | struct moschip_port *mos7840_port; |
749 | struct tty_struct *tty; | 752 | struct tty_struct *tty; |
753 | int status = urb->status; | ||
750 | int i; | 754 | int i; |
751 | 755 | ||
752 | if (!urb) { | 756 | if (!urb) { |
@@ -764,8 +768,8 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) | |||
764 | } | 768 | } |
765 | spin_unlock(&mos7840_port->pool_lock); | 769 | spin_unlock(&mos7840_port->pool_lock); |
766 | 770 | ||
767 | if (urb->status) { | 771 | if (status) { |
768 | dbg("nonzero write bulk status received:%d\n", urb->status); | 772 | dbg("nonzero write bulk status received:%d\n", status); |
769 | return; | 773 | return; |
770 | } | 774 | } |
771 | 775 | ||
@@ -2185,16 +2189,6 @@ static void mos7840_set_termios(struct usb_serial_port *port, | |||
2185 | return; | 2189 | return; |
2186 | } | 2190 | } |
2187 | 2191 | ||
2188 | /* check that they really want us to change something */ | ||
2189 | if (old_termios) { | ||
2190 | if ((cflag == old_termios->c_cflag) && | ||
2191 | (RELEVANT_IFLAG(tty->termios->c_iflag) == | ||
2192 | RELEVANT_IFLAG(old_termios->c_iflag))) { | ||
2193 | dbg("%s\n", "Nothing to change"); | ||
2194 | return; | ||
2195 | } | ||
2196 | } | ||
2197 | |||
2198 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, | 2192 | dbg("%s - clfag %08x iflag %08x", __FUNCTION__, |
2199 | tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); | 2193 | tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); |
2200 | 2194 | ||
@@ -2254,30 +2248,6 @@ static int mos7840_get_lsr_info(struct moschip_port *mos7840_port, | |||
2254 | } | 2248 | } |
2255 | 2249 | ||
2256 | /***************************************************************************** | 2250 | /***************************************************************************** |
2257 | * mos7840_get_bytes_avail - get number of bytes available | ||
2258 | * | ||
2259 | * Purpose: Let user call ioctl to get the count of number of bytes available. | ||
2260 | *****************************************************************************/ | ||
2261 | |||
2262 | static int mos7840_get_bytes_avail(struct moschip_port *mos7840_port, | ||
2263 | unsigned int __user *value) | ||
2264 | { | ||
2265 | unsigned int result = 0; | ||
2266 | struct tty_struct *tty = mos7840_port->port->tty; | ||
2267 | |||
2268 | if (!tty) | ||
2269 | return -ENOIOCTLCMD; | ||
2270 | |||
2271 | result = tty->read_cnt; | ||
2272 | |||
2273 | dbg("%s(%d) = %d", __FUNCTION__, mos7840_port->port->number, result); | ||
2274 | if (copy_to_user(value, &result, sizeof(int))) | ||
2275 | return -EFAULT; | ||
2276 | |||
2277 | return -ENOIOCTLCMD; | ||
2278 | } | ||
2279 | |||
2280 | /***************************************************************************** | ||
2281 | * mos7840_set_modem_info | 2251 | * mos7840_set_modem_info |
2282 | * function to set modem info | 2252 | * function to set modem info |
2283 | *****************************************************************************/ | 2253 | *****************************************************************************/ |
@@ -2425,8 +2395,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file, | |||
2425 | struct async_icount cprev; | 2395 | struct async_icount cprev; |
2426 | struct serial_icounter_struct icount; | 2396 | struct serial_icounter_struct icount; |
2427 | int mosret = 0; | 2397 | int mosret = 0; |
2428 | int retval; | ||
2429 | struct tty_ldisc *ld; | ||
2430 | 2398 | ||
2431 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { | 2399 | if (mos7840_port_paranoia_check(port, __FUNCTION__)) { |
2432 | dbg("%s", "Invalid port \n"); | 2400 | dbg("%s", "Invalid port \n"); |
@@ -2445,42 +2413,6 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file, | |||
2445 | switch (cmd) { | 2413 | switch (cmd) { |
2446 | /* return number of bytes available */ | 2414 | /* return number of bytes available */ |
2447 | 2415 | ||
2448 | case TIOCINQ: | ||
2449 | dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number); | ||
2450 | return mos7840_get_bytes_avail(mos7840_port, argp); | ||
2451 | |||
2452 | case TIOCOUTQ: | ||
2453 | dbg("%s (%d) TIOCOUTQ", __FUNCTION__, port->number); | ||
2454 | return put_user(tty->driver->chars_in_buffer ? | ||
2455 | tty->driver->chars_in_buffer(tty) : 0, | ||
2456 | (int __user *)arg); | ||
2457 | |||
2458 | case TCFLSH: | ||
2459 | retval = tty_check_change(tty); | ||
2460 | if (retval) | ||
2461 | return retval; | ||
2462 | |||
2463 | ld = tty_ldisc_ref(tty); | ||
2464 | switch (arg) { | ||
2465 | case TCIFLUSH: | ||
2466 | if (ld && ld->flush_buffer) | ||
2467 | ld->flush_buffer(tty); | ||
2468 | break; | ||
2469 | case TCIOFLUSH: | ||
2470 | if (ld && ld->flush_buffer) | ||
2471 | ld->flush_buffer(tty); | ||
2472 | /* fall through */ | ||
2473 | case TCOFLUSH: | ||
2474 | if (tty->driver->flush_buffer) | ||
2475 | tty->driver->flush_buffer(tty); | ||
2476 | break; | ||
2477 | default: | ||
2478 | tty_ldisc_deref(ld); | ||
2479 | return -EINVAL; | ||
2480 | } | ||
2481 | tty_ldisc_deref(ld); | ||
2482 | return 0; | ||
2483 | |||
2484 | case TIOCSERGETLSR: | 2416 | case TIOCSERGETLSR: |
2485 | dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number); | 2417 | dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number); |
2486 | return mos7840_get_lsr_info(mos7840_port, argp); | 2418 | return mos7840_get_lsr_info(mos7840_port, argp); |
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index 90701111d746..7f337c9aeb5f 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c | |||
@@ -37,9 +37,10 @@ static void navman_read_int_callback(struct urb *urb) | |||
37 | struct usb_serial_port *port = urb->context; | 37 | struct usb_serial_port *port = urb->context; |
38 | unsigned char *data = urb->transfer_buffer; | 38 | unsigned char *data = urb->transfer_buffer; |
39 | struct tty_struct *tty; | 39 | struct tty_struct *tty; |
40 | int status = urb->status; | ||
40 | int result; | 41 | int result; |
41 | 42 | ||
42 | switch (urb->status) { | 43 | switch (status) { |
43 | case 0: | 44 | case 0: |
44 | /* success */ | 45 | /* success */ |
45 | break; | 46 | break; |
@@ -48,11 +49,11 @@ static void navman_read_int_callback(struct urb *urb) | |||
48 | case -ESHUTDOWN: | 49 | case -ESHUTDOWN: |
49 | /* this urb is terminated, clean up */ | 50 | /* this urb is terminated, clean up */ |
50 | dbg("%s - urb shutting down with status: %d", | 51 | dbg("%s - urb shutting down with status: %d", |
51 | __FUNCTION__, urb->status); | 52 | __FUNCTION__, status); |
52 | return; | 53 | return; |
53 | default: | 54 | default: |
54 | dbg("%s - nonzero urb status received: %d", | 55 | dbg("%s - nonzero urb status received: %d", |
55 | __FUNCTION__, urb->status); | 56 | __FUNCTION__, status); |
56 | goto exit; | 57 | goto exit; |
57 | } | 58 | } |
58 | 59 | ||
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 00afc1712c39..ee94d9616d82 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
@@ -1,10 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * USB ZyXEL omni.net LCD PLUS driver | 2 | * USB ZyXEL omni.net LCD PLUS driver |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or |
5 | * it under the terms of the GNU General Public License as published by | 5 | * modify it under the terms of the GNU General Public License version |
6 | * the Free Software Foundation; either version 2 of the License, or | 6 | * 2 as published by the Free Software Foundation. |
7 | * (at your option) any later version. | ||
8 | * | 7 | * |
9 | * See Documentation/usb/usb-serial.txt for more information on using this driver | 8 | * See Documentation/usb/usb-serial.txt for more information on using this driver |
10 | * | 9 | * |
@@ -201,14 +200,15 @@ static void omninet_read_bulk_callback (struct urb *urb) | |||
201 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 200 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
202 | unsigned char *data = urb->transfer_buffer; | 201 | unsigned char *data = urb->transfer_buffer; |
203 | struct omninet_header *header = (struct omninet_header *) &data[0]; | 202 | struct omninet_header *header = (struct omninet_header *) &data[0]; |
204 | 203 | int status = urb->status; | |
205 | int i; | 204 | int i; |
206 | int result; | 205 | int result; |
207 | 206 | ||
208 | dbg("%s - port %d", __FUNCTION__, port->number); | 207 | dbg("%s - port %d", __FUNCTION__, port->number); |
209 | 208 | ||
210 | if (urb->status) { | 209 | if (status) { |
211 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 210 | dbg("%s - nonzero read bulk status received: %d", |
211 | __FUNCTION__, status); | ||
212 | return; | 212 | return; |
213 | } | 213 | } |
214 | 214 | ||
@@ -312,12 +312,14 @@ static void omninet_write_bulk_callback (struct urb *urb) | |||
312 | { | 312 | { |
313 | /* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */ | 313 | /* struct omninet_header *header = (struct omninet_header *) urb->transfer_buffer; */ |
314 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | 314 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; |
315 | int status = urb->status; | ||
315 | 316 | ||
316 | dbg("%s - port %0x\n", __FUNCTION__, port->number); | 317 | dbg("%s - port %0x\n", __FUNCTION__, port->number); |
317 | 318 | ||
318 | port->write_urb_busy = 0; | 319 | port->write_urb_busy = 0; |
319 | if (urb->status) { | 320 | if (status) { |
320 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 321 | dbg("%s - nonzero write bulk status received: %d", |
322 | __FUNCTION__, status); | ||
321 | return; | 323 | return; |
322 | } | 324 | } |
323 | 325 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5d3999e3ff61..84c12b5f1271 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/tty.h> | 38 | #include <linux/tty.h> |
39 | #include <linux/tty_flip.h> | 39 | #include <linux/tty_flip.h> |
40 | #include <linux/module.h> | 40 | #include <linux/module.h> |
41 | #include <linux/bitops.h> | ||
41 | #include <linux/usb.h> | 42 | #include <linux/usb.h> |
42 | #include <linux/usb/serial.h> | 43 | #include <linux/usb/serial.h> |
43 | 44 | ||
@@ -240,6 +241,7 @@ struct option_port_private { | |||
240 | /* Output endpoints and buffer for this port */ | 241 | /* Output endpoints and buffer for this port */ |
241 | struct urb *out_urbs[N_OUT_URB]; | 242 | struct urb *out_urbs[N_OUT_URB]; |
242 | char out_buffer[N_OUT_URB][OUT_BUFLEN]; | 243 | char out_buffer[N_OUT_URB][OUT_BUFLEN]; |
244 | unsigned long out_busy; /* Bit vector of URBs in use */ | ||
243 | 245 | ||
244 | /* Settings for the port */ | 246 | /* Settings for the port */ |
245 | int rts_state; /* Handshaking pins (outputs) */ | 247 | int rts_state; /* Handshaking pins (outputs) */ |
@@ -370,7 +372,7 @@ static int option_write(struct usb_serial_port *port, | |||
370 | todo = OUT_BUFLEN; | 372 | todo = OUT_BUFLEN; |
371 | 373 | ||
372 | this_urb = portdata->out_urbs[i]; | 374 | this_urb = portdata->out_urbs[i]; |
373 | if (this_urb->status == -EINPROGRESS) { | 375 | if (test_and_set_bit(i, &portdata->out_busy)) { |
374 | if (time_before(jiffies, | 376 | if (time_before(jiffies, |
375 | portdata->tx_start_time[i] + 10 * HZ)) | 377 | portdata->tx_start_time[i] + 10 * HZ)) |
376 | continue; | 378 | continue; |
@@ -394,6 +396,7 @@ static int option_write(struct usb_serial_port *port, | |||
394 | dbg("usb_submit_urb %p (write bulk) failed " | 396 | dbg("usb_submit_urb %p (write bulk) failed " |
395 | "(%d, has %d)", this_urb, | 397 | "(%d, has %d)", this_urb, |
396 | err, this_urb->status); | 398 | err, this_urb->status); |
399 | clear_bit(i, &portdata->out_busy); | ||
397 | continue; | 400 | continue; |
398 | } | 401 | } |
399 | portdata->tx_start_time[i] = jiffies; | 402 | portdata->tx_start_time[i] = jiffies; |
@@ -413,15 +416,16 @@ static void option_indat_callback(struct urb *urb) | |||
413 | struct usb_serial_port *port; | 416 | struct usb_serial_port *port; |
414 | struct tty_struct *tty; | 417 | struct tty_struct *tty; |
415 | unsigned char *data = urb->transfer_buffer; | 418 | unsigned char *data = urb->transfer_buffer; |
419 | int status = urb->status; | ||
416 | 420 | ||
417 | dbg("%s: %p", __FUNCTION__, urb); | 421 | dbg("%s: %p", __FUNCTION__, urb); |
418 | 422 | ||
419 | endpoint = usb_pipeendpoint(urb->pipe); | 423 | endpoint = usb_pipeendpoint(urb->pipe); |
420 | port = (struct usb_serial_port *) urb->context; | 424 | port = (struct usb_serial_port *) urb->context; |
421 | 425 | ||
422 | if (urb->status) { | 426 | if (status) { |
423 | dbg("%s: nonzero status: %d on endpoint %02x.", | 427 | dbg("%s: nonzero status: %d on endpoint %02x.", |
424 | __FUNCTION__, urb->status, endpoint); | 428 | __FUNCTION__, status, endpoint); |
425 | } else { | 429 | } else { |
426 | tty = port->tty; | 430 | tty = port->tty; |
427 | if (urb->actual_length) { | 431 | if (urb->actual_length) { |
@@ -433,7 +437,7 @@ static void option_indat_callback(struct urb *urb) | |||
433 | } | 437 | } |
434 | 438 | ||
435 | /* Resubmit urb so we continue receiving */ | 439 | /* Resubmit urb so we continue receiving */ |
436 | if (port->open_count && urb->status != -ESHUTDOWN) { | 440 | if (port->open_count && status != -ESHUTDOWN) { |
437 | err = usb_submit_urb(urb, GFP_ATOMIC); | 441 | err = usb_submit_urb(urb, GFP_ATOMIC); |
438 | if (err) | 442 | if (err) |
439 | printk(KERN_ERR "%s: resubmit read urb failed. " | 443 | printk(KERN_ERR "%s: resubmit read urb failed. " |
@@ -446,17 +450,29 @@ static void option_indat_callback(struct urb *urb) | |||
446 | static void option_outdat_callback(struct urb *urb) | 450 | static void option_outdat_callback(struct urb *urb) |
447 | { | 451 | { |
448 | struct usb_serial_port *port; | 452 | struct usb_serial_port *port; |
453 | struct option_port_private *portdata; | ||
454 | int i; | ||
449 | 455 | ||
450 | dbg("%s", __FUNCTION__); | 456 | dbg("%s", __FUNCTION__); |
451 | 457 | ||
452 | port = (struct usb_serial_port *) urb->context; | 458 | port = (struct usb_serial_port *) urb->context; |
453 | 459 | ||
454 | usb_serial_port_softint(port); | 460 | usb_serial_port_softint(port); |
461 | |||
462 | portdata = usb_get_serial_port_data(port); | ||
463 | for (i = 0; i < N_OUT_URB; ++i) { | ||
464 | if (portdata->out_urbs[i] == urb) { | ||
465 | smp_mb__before_clear_bit(); | ||
466 | clear_bit(i, &portdata->out_busy); | ||
467 | break; | ||
468 | } | ||
469 | } | ||
455 | } | 470 | } |
456 | 471 | ||
457 | static void option_instat_callback(struct urb *urb) | 472 | static void option_instat_callback(struct urb *urb) |
458 | { | 473 | { |
459 | int err; | 474 | int err; |
475 | int status = urb->status; | ||
460 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | 476 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; |
461 | struct option_port_private *portdata = usb_get_serial_port_data(port); | 477 | struct option_port_private *portdata = usb_get_serial_port_data(port); |
462 | struct usb_serial *serial = port->serial; | 478 | struct usb_serial *serial = port->serial; |
@@ -464,7 +480,7 @@ static void option_instat_callback(struct urb *urb) | |||
464 | dbg("%s", __FUNCTION__); | 480 | dbg("%s", __FUNCTION__); |
465 | dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); | 481 | dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); |
466 | 482 | ||
467 | if (urb->status == 0) { | 483 | if (status == 0) { |
468 | struct usb_ctrlrequest *req_pkt = | 484 | struct usb_ctrlrequest *req_pkt = |
469 | (struct usb_ctrlrequest *)urb->transfer_buffer; | 485 | (struct usb_ctrlrequest *)urb->transfer_buffer; |
470 | 486 | ||
@@ -495,10 +511,10 @@ static void option_instat_callback(struct urb *urb) | |||
495 | req_pkt->bRequestType,req_pkt->bRequest); | 511 | req_pkt->bRequestType,req_pkt->bRequest); |
496 | } | 512 | } |
497 | } else | 513 | } else |
498 | dbg("%s: error %d", __FUNCTION__, urb->status); | 514 | dbg("%s: error %d", __FUNCTION__, status); |
499 | 515 | ||
500 | /* Resubmit urb so we continue receiving IRQ data */ | 516 | /* Resubmit urb so we continue receiving IRQ data */ |
501 | if (urb->status != -ESHUTDOWN) { | 517 | if (status != -ESHUTDOWN) { |
502 | urb->dev = serial->dev; | 518 | urb->dev = serial->dev; |
503 | err = usb_submit_urb(urb, GFP_ATOMIC); | 519 | err = usb_submit_urb(urb, GFP_ATOMIC); |
504 | if (err) | 520 | if (err) |
@@ -518,7 +534,7 @@ static int option_write_room(struct usb_serial_port *port) | |||
518 | 534 | ||
519 | for (i=0; i < N_OUT_URB; i++) { | 535 | for (i=0; i < N_OUT_URB; i++) { |
520 | this_urb = portdata->out_urbs[i]; | 536 | this_urb = portdata->out_urbs[i]; |
521 | if (this_urb && this_urb->status != -EINPROGRESS) | 537 | if (this_urb && !test_bit(i, &portdata->out_busy)) |
522 | data_len += OUT_BUFLEN; | 538 | data_len += OUT_BUFLEN; |
523 | } | 539 | } |
524 | 540 | ||
@@ -537,7 +553,7 @@ static int option_chars_in_buffer(struct usb_serial_port *port) | |||
537 | 553 | ||
538 | for (i=0; i < N_OUT_URB; i++) { | 554 | for (i=0; i < N_OUT_URB; i++) { |
539 | this_urb = portdata->out_urbs[i]; | 555 | this_urb = portdata->out_urbs[i]; |
540 | if (this_urb && this_urb->status == -EINPROGRESS) | 556 | if (this_urb && test_bit(i, &portdata->out_busy)) |
541 | data_len += this_urb->transfer_buffer_length; | 557 | data_len += this_urb->transfer_buffer_length; |
542 | } | 558 | } |
543 | dbg("%s: %d", __FUNCTION__, data_len); | 559 | dbg("%s: %d", __FUNCTION__, data_len); |
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c new file mode 100644 index 000000000000..d7db71eca520 --- /dev/null +++ b/drivers/usb/serial/oti6858.c | |||
@@ -0,0 +1,1342 @@ | |||
1 | /* | ||
2 | * Ours Technology Inc. OTi-6858 USB to serial adapter driver. | ||
3 | * | ||
4 | * Copyleft (C) 2007 Kees Lemmens (adapted for kernel 2.6.20) | ||
5 | * Copyright (C) 2006 Tomasz Michal Lukaszewski (FIXME: add e-mail) | ||
6 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | ||
7 | * Copyright (C) 2003 IBM Corp. | ||
8 | * | ||
9 | * Many thanks to the authors of pl2303 driver: all functions in this file | ||
10 | * are heavily based on pl2303 code, buffering code is a 1-to-1 copy. | ||
11 | * | ||
12 | * Warning! You use this driver on your own risk! The only official | ||
13 | * description of this device I have is datasheet from manufacturer, | ||
14 | * and it doesn't contain almost any information needed to write a driver. | ||
15 | * Almost all knowlegde used while writing this driver was gathered by: | ||
16 | * - analyzing traffic between device and the M$ Windows 2000 driver, | ||
17 | * - trying different bit combinations and checking pin states | ||
18 | * with a voltmeter, | ||
19 | * - receiving malformed frames and producing buffer overflows | ||
20 | * to learn how errors are reported, | ||
21 | * So, THIS CODE CAN DESTROY OTi-6858 AND ANY OTHER DEVICES, THAT ARE | ||
22 | * CONNECTED TO IT! | ||
23 | * | ||
24 | * This program is free software; you can redistribute it and/or modify | ||
25 | * it under the terms of the GNU General Public License as published by | ||
26 | * the Free Software Foundation; either version 2 of the License. | ||
27 | * | ||
28 | * See Documentation/usb/usb-serial.txt for more information on using this driver | ||
29 | * | ||
30 | * TODO: | ||
31 | * - implement correct flushing for ioctls and oti6858_close() | ||
32 | * - check how errors (rx overflow, parity error, framing error) are reported | ||
33 | * - implement oti6858_break_ctl() | ||
34 | * - implement more ioctls | ||
35 | * - test/implement flow control | ||
36 | * - allow setting custom baud rates | ||
37 | */ | ||
38 | |||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/errno.h> | ||
41 | #include <linux/init.h> | ||
42 | #include <linux/slab.h> | ||
43 | #include <linux/tty.h> | ||
44 | #include <linux/tty_driver.h> | ||
45 | #include <linux/tty_flip.h> | ||
46 | #include <linux/serial.h> | ||
47 | #include <linux/module.h> | ||
48 | #include <linux/moduleparam.h> | ||
49 | #include <linux/spinlock.h> | ||
50 | #include <linux/usb.h> | ||
51 | #include <linux/usb/serial.h> | ||
52 | #include <asm/uaccess.h> | ||
53 | #include "oti6858.h" | ||
54 | |||
55 | #define OTI6858_DESCRIPTION \ | ||
56 | "Ours Technology Inc. OTi-6858 USB to serial adapter driver" | ||
57 | #define OTI6858_AUTHOR "Tomasz Michal Lukaszewski <FIXME@FIXME>" | ||
58 | #define OTI6858_VERSION "0.1" | ||
59 | |||
60 | static struct usb_device_id id_table [] = { | ||
61 | { USB_DEVICE(OTI6858_VENDOR_ID, OTI6858_PRODUCT_ID) }, | ||
62 | { } | ||
63 | }; | ||
64 | |||
65 | MODULE_DEVICE_TABLE(usb, id_table); | ||
66 | |||
67 | static struct usb_driver oti6858_driver = { | ||
68 | .name = "oti6858", | ||
69 | .probe = usb_serial_probe, | ||
70 | .disconnect = usb_serial_disconnect, | ||
71 | .id_table = id_table, | ||
72 | .no_dynamic_id = 1, | ||
73 | }; | ||
74 | |||
75 | static int debug; | ||
76 | |||
77 | |||
78 | /* buffering code, copied from pl2303 driver */ | ||
79 | #define PL2303_BUF_SIZE 1024 | ||
80 | #define PL2303_TMP_BUF_SIZE 1024 | ||
81 | |||
82 | struct pl2303_buf { | ||
83 | unsigned int buf_size; | ||
84 | char *buf_buf; | ||
85 | char *buf_get; | ||
86 | char *buf_put; | ||
87 | }; | ||
88 | |||
89 | /* requests */ | ||
90 | #define OTI6858_REQ_GET_STATUS (USB_DIR_IN | USB_TYPE_VENDOR | 0x00) | ||
91 | #define OTI6858_REQ_T_GET_STATUS 0x01 | ||
92 | |||
93 | #define OTI6858_REQ_SET_LINE (USB_DIR_OUT | USB_TYPE_VENDOR | 0x00) | ||
94 | #define OTI6858_REQ_T_SET_LINE 0x00 | ||
95 | |||
96 | #define OTI6858_REQ_CHECK_TXBUFF (USB_DIR_IN | USB_TYPE_VENDOR | 0x01) | ||
97 | #define OTI6858_REQ_T_CHECK_TXBUFF 0x00 | ||
98 | |||
99 | /* format of the control packet */ | ||
100 | struct oti6858_control_pkt { | ||
101 | u16 divisor; /* baud rate = 96000000 / (16 * divisor), LE */ | ||
102 | #define OTI6858_MAX_BAUD_RATE 3000000 | ||
103 | u8 frame_fmt; | ||
104 | #define FMT_STOP_BITS_MASK 0xc0 | ||
105 | #define FMT_STOP_BITS_1 0x00 | ||
106 | #define FMT_STOP_BITS_2 0x40 /* 1.5 stop bits if FMT_DATA_BITS_5 */ | ||
107 | #define FMT_PARITY_MASK 0x38 | ||
108 | #define FMT_PARITY_NONE 0x00 | ||
109 | #define FMT_PARITY_ODD 0x08 | ||
110 | #define FMT_PARITY_EVEN 0x18 | ||
111 | #define FMT_PARITY_MARK 0x28 | ||
112 | #define FMT_PARITY_SPACE 0x38 | ||
113 | #define FMT_DATA_BITS_MASK 0x03 | ||
114 | #define FMT_DATA_BITS_5 0x00 | ||
115 | #define FMT_DATA_BITS_6 0x01 | ||
116 | #define FMT_DATA_BITS_7 0x02 | ||
117 | #define FMT_DATA_BITS_8 0x03 | ||
118 | u8 something; /* always equals 0x43 */ | ||
119 | u8 control; /* settings of flow control lines */ | ||
120 | #define CONTROL_MASK 0x0c | ||
121 | #define CONTROL_DTR_HIGH 0x08 | ||
122 | #define CONTROL_RTS_HIGH 0x04 | ||
123 | u8 tx_status; | ||
124 | #define TX_BUFFER_EMPTIED 0x09 | ||
125 | u8 pin_state; | ||
126 | #define PIN_MASK 0x3f | ||
127 | #define PIN_RTS 0x20 /* output pin */ | ||
128 | #define PIN_CTS 0x10 /* input pin, active low */ | ||
129 | #define PIN_DSR 0x08 /* input pin, active low */ | ||
130 | #define PIN_DTR 0x04 /* output pin */ | ||
131 | #define PIN_RI 0x02 /* input pin, active low */ | ||
132 | #define PIN_DCD 0x01 /* input pin, active low */ | ||
133 | u8 rx_bytes_avail; /* number of bytes in rx buffer */; | ||
134 | }; | ||
135 | |||
136 | #define OTI6858_CTRL_PKT_SIZE sizeof(struct oti6858_control_pkt) | ||
137 | #define OTI6858_CTRL_EQUALS_PENDING(a, priv) \ | ||
138 | ( ((a)->divisor == (priv)->pending_setup.divisor) \ | ||
139 | && ((a)->control == (priv)->pending_setup.control) \ | ||
140 | && ((a)->frame_fmt == (priv)->pending_setup.frame_fmt) ) | ||
141 | |||
142 | /* function prototypes */ | ||
143 | static int oti6858_open(struct usb_serial_port *port, struct file *filp); | ||
144 | static void oti6858_close(struct usb_serial_port *port, struct file *filp); | ||
145 | static void oti6858_set_termios(struct usb_serial_port *port, | ||
146 | struct ktermios *old); | ||
147 | static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, | ||
148 | unsigned int cmd, unsigned long arg); | ||
149 | static void oti6858_read_int_callback(struct urb *urb); | ||
150 | static void oti6858_read_bulk_callback(struct urb *urb); | ||
151 | static void oti6858_write_bulk_callback(struct urb *urb); | ||
152 | static int oti6858_write(struct usb_serial_port *port, | ||
153 | const unsigned char *buf, int count); | ||
154 | static int oti6858_write_room(struct usb_serial_port *port); | ||
155 | static void oti6858_break_ctl(struct usb_serial_port *port, int break_state); | ||
156 | static int oti6858_chars_in_buffer(struct usb_serial_port *port); | ||
157 | static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file); | ||
158 | static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file, | ||
159 | unsigned int set, unsigned int clear); | ||
160 | static int oti6858_startup(struct usb_serial *serial); | ||
161 | static void oti6858_shutdown(struct usb_serial *serial); | ||
162 | |||
163 | /* functions operating on buffers */ | ||
164 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size); | ||
165 | static void pl2303_buf_free(struct pl2303_buf *pb); | ||
166 | static void pl2303_buf_clear(struct pl2303_buf *pb); | ||
167 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb); | ||
168 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb); | ||
169 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
170 | unsigned int count); | ||
171 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
172 | unsigned int count); | ||
173 | |||
174 | |||
175 | /* device info */ | ||
176 | static struct usb_serial_driver oti6858_device = { | ||
177 | .driver = { | ||
178 | .owner = THIS_MODULE, | ||
179 | .name = "oti6858", | ||
180 | }, | ||
181 | .id_table = id_table, | ||
182 | .num_interrupt_in = 1, | ||
183 | .num_bulk_in = 1, | ||
184 | .num_bulk_out = 1, | ||
185 | .num_ports = 1, | ||
186 | .open = oti6858_open, | ||
187 | .close = oti6858_close, | ||
188 | .write = oti6858_write, | ||
189 | .ioctl = oti6858_ioctl, | ||
190 | .break_ctl = oti6858_break_ctl, | ||
191 | .set_termios = oti6858_set_termios, | ||
192 | .tiocmget = oti6858_tiocmget, | ||
193 | .tiocmset = oti6858_tiocmset, | ||
194 | .read_bulk_callback = oti6858_read_bulk_callback, | ||
195 | .read_int_callback = oti6858_read_int_callback, | ||
196 | .write_bulk_callback = oti6858_write_bulk_callback, | ||
197 | .write_room = oti6858_write_room, | ||
198 | .chars_in_buffer = oti6858_chars_in_buffer, | ||
199 | .attach = oti6858_startup, | ||
200 | .shutdown = oti6858_shutdown, | ||
201 | }; | ||
202 | |||
203 | struct oti6858_private { | ||
204 | spinlock_t lock; | ||
205 | |||
206 | struct pl2303_buf *buf; | ||
207 | struct oti6858_control_pkt status; | ||
208 | |||
209 | struct { | ||
210 | u8 read_urb_in_use; | ||
211 | u8 write_urb_in_use; | ||
212 | u8 termios_initialized; | ||
213 | } flags; | ||
214 | struct delayed_work delayed_write_work; | ||
215 | |||
216 | struct { | ||
217 | u16 divisor; | ||
218 | u8 frame_fmt; | ||
219 | u8 control; | ||
220 | } pending_setup; | ||
221 | u8 transient; | ||
222 | u8 setup_done; | ||
223 | struct delayed_work delayed_setup_work; | ||
224 | |||
225 | wait_queue_head_t intr_wait; | ||
226 | struct usb_serial_port *port; /* USB port with which associated */ | ||
227 | }; | ||
228 | |||
229 | #undef dbg | ||
230 | /* #define dbg(format, arg...) printk(KERN_INFO "%s: " format "\n", __FILE__, ## arg) */ | ||
231 | #define dbg(format, arg...) printk(KERN_INFO "" format "\n", ## arg) | ||
232 | |||
233 | static void setup_line(struct work_struct *work) | ||
234 | { | ||
235 | struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_setup_work.work); | ||
236 | struct usb_serial_port *port = priv->port; | ||
237 | struct oti6858_control_pkt *new_setup; | ||
238 | unsigned long flags; | ||
239 | int result; | ||
240 | |||
241 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
242 | |||
243 | if ((new_setup = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) { | ||
244 | dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__); | ||
245 | /* we will try again */ | ||
246 | schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2)); | ||
247 | return; | ||
248 | } | ||
249 | |||
250 | result = usb_control_msg(port->serial->dev, | ||
251 | usb_rcvctrlpipe(port->serial->dev, 0), | ||
252 | OTI6858_REQ_T_GET_STATUS, | ||
253 | OTI6858_REQ_GET_STATUS, | ||
254 | 0, 0, | ||
255 | new_setup, OTI6858_CTRL_PKT_SIZE, | ||
256 | 100); | ||
257 | |||
258 | if (result != OTI6858_CTRL_PKT_SIZE) { | ||
259 | dev_err(&port->dev, "%s(): error reading status", __FUNCTION__); | ||
260 | kfree(new_setup); | ||
261 | /* we will try again */ | ||
262 | schedule_delayed_work(&priv->delayed_setup_work, msecs_to_jiffies(2)); | ||
263 | return; | ||
264 | } | ||
265 | |||
266 | spin_lock_irqsave(&priv->lock, flags); | ||
267 | if (!OTI6858_CTRL_EQUALS_PENDING(new_setup, priv)) { | ||
268 | new_setup->divisor = priv->pending_setup.divisor; | ||
269 | new_setup->control = priv->pending_setup.control; | ||
270 | new_setup->frame_fmt = priv->pending_setup.frame_fmt; | ||
271 | |||
272 | spin_unlock_irqrestore(&priv->lock, flags); | ||
273 | result = usb_control_msg(port->serial->dev, | ||
274 | usb_sndctrlpipe(port->serial->dev, 0), | ||
275 | OTI6858_REQ_T_SET_LINE, | ||
276 | OTI6858_REQ_SET_LINE, | ||
277 | 0, 0, | ||
278 | new_setup, OTI6858_CTRL_PKT_SIZE, | ||
279 | 100); | ||
280 | } else { | ||
281 | spin_unlock_irqrestore(&priv->lock, flags); | ||
282 | result = 0; | ||
283 | } | ||
284 | kfree(new_setup); | ||
285 | |||
286 | spin_lock_irqsave(&priv->lock, flags); | ||
287 | if (result != OTI6858_CTRL_PKT_SIZE) | ||
288 | priv->transient = 0; | ||
289 | priv->setup_done = 1; | ||
290 | spin_unlock_irqrestore(&priv->lock, flags); | ||
291 | |||
292 | dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
293 | port->interrupt_in_urb->dev = port->serial->dev; | ||
294 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | ||
295 | if (result != 0) { | ||
296 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" | ||
297 | " with error %d\n", __FUNCTION__, result); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | void send_data(struct work_struct *work) | ||
302 | { | ||
303 | struct oti6858_private *priv = container_of(work, struct oti6858_private, delayed_write_work.work); | ||
304 | struct usb_serial_port *port = priv->port; | ||
305 | int count = 0, result; | ||
306 | unsigned long flags; | ||
307 | unsigned char allow; | ||
308 | |||
309 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
310 | |||
311 | spin_lock_irqsave(&priv->lock, flags); | ||
312 | if (priv->flags.write_urb_in_use) { | ||
313 | spin_unlock_irqrestore(&priv->lock, flags); | ||
314 | schedule_delayed_work(&priv->delayed_write_work, msecs_to_jiffies(2)); | ||
315 | return; | ||
316 | } | ||
317 | priv->flags.write_urb_in_use = 1; | ||
318 | |||
319 | count = pl2303_buf_data_avail(priv->buf); | ||
320 | spin_unlock_irqrestore(&priv->lock, flags); | ||
321 | if (count > port->bulk_out_size) | ||
322 | count = port->bulk_out_size; | ||
323 | |||
324 | if (count != 0) { | ||
325 | result = usb_control_msg(port->serial->dev, | ||
326 | usb_rcvctrlpipe(port->serial->dev, 0), | ||
327 | OTI6858_REQ_T_CHECK_TXBUFF, | ||
328 | OTI6858_REQ_CHECK_TXBUFF, | ||
329 | count, 0, &allow, 1, 100); | ||
330 | if (result != 1 || allow != 0) | ||
331 | count = 0; | ||
332 | } | ||
333 | |||
334 | if (count == 0) { | ||
335 | priv->flags.write_urb_in_use = 0; | ||
336 | |||
337 | dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
338 | port->interrupt_in_urb->dev = port->serial->dev; | ||
339 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | ||
340 | if (result != 0) { | ||
341 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" | ||
342 | " with error %d\n", __FUNCTION__, result); | ||
343 | } | ||
344 | return; | ||
345 | } | ||
346 | |||
347 | spin_lock_irqsave(&priv->lock, flags); | ||
348 | pl2303_buf_get(priv->buf, port->write_urb->transfer_buffer, count); | ||
349 | spin_unlock_irqrestore(&priv->lock, flags); | ||
350 | |||
351 | port->write_urb->transfer_buffer_length = count; | ||
352 | port->write_urb->dev = port->serial->dev; | ||
353 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
354 | if (result != 0) { | ||
355 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" | ||
356 | " with error %d\n", __FUNCTION__, result); | ||
357 | priv->flags.write_urb_in_use = 0; | ||
358 | } | ||
359 | |||
360 | usb_serial_port_softint(port); | ||
361 | } | ||
362 | |||
363 | static int oti6858_startup(struct usb_serial *serial) | ||
364 | { | ||
365 | struct usb_serial_port *port = serial->port[0]; | ||
366 | struct oti6858_private *priv; | ||
367 | int i; | ||
368 | |||
369 | for (i = 0; i < serial->num_ports; ++i) { | ||
370 | priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL); | ||
371 | if (!priv) | ||
372 | break; | ||
373 | priv->buf = pl2303_buf_alloc(PL2303_BUF_SIZE); | ||
374 | if (priv->buf == NULL) { | ||
375 | kfree(priv); | ||
376 | break; | ||
377 | } | ||
378 | |||
379 | spin_lock_init(&priv->lock); | ||
380 | init_waitqueue_head(&priv->intr_wait); | ||
381 | // INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); | ||
382 | // INIT_WORK(&priv->write_work, send_data, serial->port[i]); | ||
383 | priv->port = port; | ||
384 | INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); | ||
385 | INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); | ||
386 | |||
387 | usb_set_serial_port_data(serial->port[i], priv); | ||
388 | } | ||
389 | if (i == serial->num_ports) | ||
390 | return 0; | ||
391 | |||
392 | for (--i; i >= 0; --i) { | ||
393 | priv = usb_get_serial_port_data(serial->port[i]); | ||
394 | pl2303_buf_free(priv->buf); | ||
395 | kfree(priv); | ||
396 | usb_set_serial_port_data(serial->port[i], NULL); | ||
397 | } | ||
398 | return -ENOMEM; | ||
399 | } | ||
400 | |||
401 | static int oti6858_write(struct usb_serial_port *port, | ||
402 | const unsigned char *buf, int count) | ||
403 | { | ||
404 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
405 | unsigned long flags; | ||
406 | |||
407 | dbg("%s(port = %d, count = %d)", __FUNCTION__, port->number, count); | ||
408 | |||
409 | if (!count) | ||
410 | return count; | ||
411 | |||
412 | spin_lock_irqsave(&priv->lock, flags); | ||
413 | count = pl2303_buf_put(priv->buf, buf, count); | ||
414 | spin_unlock_irqrestore(&priv->lock, flags); | ||
415 | |||
416 | return count; | ||
417 | } | ||
418 | |||
419 | static int oti6858_write_room(struct usb_serial_port *port) | ||
420 | { | ||
421 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
422 | int room = 0; | ||
423 | unsigned long flags; | ||
424 | |||
425 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
426 | |||
427 | spin_lock_irqsave(&priv->lock, flags); | ||
428 | room = pl2303_buf_space_avail(priv->buf); | ||
429 | spin_unlock_irqrestore(&priv->lock, flags); | ||
430 | |||
431 | return room; | ||
432 | } | ||
433 | |||
434 | static int oti6858_chars_in_buffer(struct usb_serial_port *port) | ||
435 | { | ||
436 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
437 | int chars = 0; | ||
438 | unsigned long flags; | ||
439 | |||
440 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
441 | |||
442 | spin_lock_irqsave(&priv->lock, flags); | ||
443 | chars = pl2303_buf_data_avail(priv->buf); | ||
444 | spin_unlock_irqrestore(&priv->lock, flags); | ||
445 | |||
446 | return chars; | ||
447 | } | ||
448 | |||
449 | static void oti6858_set_termios(struct usb_serial_port *port, | ||
450 | struct ktermios *old_termios) | ||
451 | { | ||
452 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
453 | unsigned long flags; | ||
454 | unsigned int cflag; | ||
455 | u8 frame_fmt, control; | ||
456 | u16 divisor; | ||
457 | int br; | ||
458 | |||
459 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
460 | |||
461 | if ((!port->tty) || (!port->tty->termios)) { | ||
462 | dbg("%s(): no tty structures", __FUNCTION__); | ||
463 | return; | ||
464 | } | ||
465 | |||
466 | spin_lock_irqsave(&priv->lock, flags); | ||
467 | if (!priv->flags.termios_initialized) { | ||
468 | *(port->tty->termios) = tty_std_termios; | ||
469 | port->tty->termios->c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL; | ||
470 | priv->flags.termios_initialized = 1; | ||
471 | } | ||
472 | spin_unlock_irqrestore(&priv->lock, flags); | ||
473 | |||
474 | cflag = port->tty->termios->c_cflag; | ||
475 | |||
476 | spin_lock_irqsave(&priv->lock, flags); | ||
477 | divisor = priv->pending_setup.divisor; | ||
478 | frame_fmt = priv->pending_setup.frame_fmt; | ||
479 | control = priv->pending_setup.control; | ||
480 | spin_unlock_irqrestore(&priv->lock, flags); | ||
481 | |||
482 | frame_fmt &= ~FMT_DATA_BITS_MASK; | ||
483 | switch (cflag & CSIZE) { | ||
484 | case CS5: | ||
485 | frame_fmt |= FMT_DATA_BITS_5; | ||
486 | break; | ||
487 | case CS6: | ||
488 | frame_fmt |= FMT_DATA_BITS_6; | ||
489 | break; | ||
490 | case CS7: | ||
491 | frame_fmt |= FMT_DATA_BITS_7; | ||
492 | break; | ||
493 | default: | ||
494 | case CS8: | ||
495 | frame_fmt |= FMT_DATA_BITS_8; | ||
496 | break; | ||
497 | } | ||
498 | |||
499 | /* manufacturer claims that this device can work with baud rates | ||
500 | * up to 3 Mbps; I've tested it only on 115200 bps, so I can't | ||
501 | * guarantee that any other baud rate will work (especially | ||
502 | * the higher ones) | ||
503 | */ | ||
504 | br = tty_get_baud_rate(port->tty); | ||
505 | if (br == 0) { | ||
506 | divisor = 0; | ||
507 | } else if (br <= OTI6858_MAX_BAUD_RATE) { | ||
508 | int real_br; | ||
509 | |||
510 | divisor = (96000000 + 8 * br) / (16 * br); | ||
511 | real_br = 96000000 / (16 * divisor); | ||
512 | if ((((real_br - br) * 100 + br - 1) / br) > 2) { | ||
513 | dbg("%s(): baud rate %d is invalid", __FUNCTION__, br); | ||
514 | return; | ||
515 | } | ||
516 | divisor = cpu_to_le16(divisor); | ||
517 | } else { | ||
518 | dbg("%s(): baud rate %d is too high", __FUNCTION__, br); | ||
519 | return; | ||
520 | } | ||
521 | |||
522 | frame_fmt &= ~FMT_STOP_BITS_MASK; | ||
523 | if ((cflag & CSTOPB) != 0) { | ||
524 | frame_fmt |= FMT_STOP_BITS_2; | ||
525 | } else { | ||
526 | frame_fmt |= FMT_STOP_BITS_1; | ||
527 | } | ||
528 | |||
529 | frame_fmt &= ~FMT_PARITY_MASK; | ||
530 | if ((cflag & PARENB) != 0) { | ||
531 | if ((cflag & PARODD) != 0) { | ||
532 | frame_fmt |= FMT_PARITY_ODD; | ||
533 | } else { | ||
534 | frame_fmt |= FMT_PARITY_EVEN; | ||
535 | } | ||
536 | } else { | ||
537 | frame_fmt |= FMT_PARITY_NONE; | ||
538 | } | ||
539 | |||
540 | control &= ~CONTROL_MASK; | ||
541 | if ((cflag & CRTSCTS) != 0) | ||
542 | control |= (CONTROL_DTR_HIGH | CONTROL_RTS_HIGH); | ||
543 | |||
544 | /* change control lines if we are switching to or from B0 */ | ||
545 | /* FIXME: | ||
546 | spin_lock_irqsave(&priv->lock, flags); | ||
547 | control = priv->line_control; | ||
548 | if ((cflag & CBAUD) == B0) | ||
549 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); | ||
550 | else | ||
551 | priv->line_control |= (CONTROL_DTR | CONTROL_RTS); | ||
552 | if (control != priv->line_control) { | ||
553 | control = priv->line_control; | ||
554 | spin_unlock_irqrestore(&priv->lock, flags); | ||
555 | set_control_lines(serial->dev, control); | ||
556 | } else { | ||
557 | spin_unlock_irqrestore(&priv->lock, flags); | ||
558 | } | ||
559 | */ | ||
560 | |||
561 | spin_lock_irqsave(&priv->lock, flags); | ||
562 | if (divisor != priv->pending_setup.divisor | ||
563 | || control != priv->pending_setup.control | ||
564 | || frame_fmt != priv->pending_setup.frame_fmt) { | ||
565 | priv->pending_setup.divisor = divisor; | ||
566 | priv->pending_setup.control = control; | ||
567 | priv->pending_setup.frame_fmt = frame_fmt; | ||
568 | } | ||
569 | spin_unlock_irqrestore(&priv->lock, flags); | ||
570 | } | ||
571 | |||
572 | static int oti6858_open(struct usb_serial_port *port, struct file *filp) | ||
573 | { | ||
574 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
575 | struct ktermios tmp_termios; | ||
576 | struct usb_serial *serial = port->serial; | ||
577 | struct oti6858_control_pkt *buf; | ||
578 | unsigned long flags; | ||
579 | int result; | ||
580 | |||
581 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
582 | |||
583 | usb_clear_halt(serial->dev, port->write_urb->pipe); | ||
584 | usb_clear_halt(serial->dev, port->read_urb->pipe); | ||
585 | |||
586 | if (port->open_count != 1) | ||
587 | return 0; | ||
588 | |||
589 | if ((buf = kmalloc(OTI6858_CTRL_PKT_SIZE, GFP_KERNEL)) == NULL) { | ||
590 | dev_err(&port->dev, "%s(): out of memory!\n", __FUNCTION__); | ||
591 | return -ENOMEM; | ||
592 | } | ||
593 | |||
594 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | ||
595 | OTI6858_REQ_T_GET_STATUS, | ||
596 | OTI6858_REQ_GET_STATUS, | ||
597 | 0, 0, | ||
598 | buf, OTI6858_CTRL_PKT_SIZE, | ||
599 | 100); | ||
600 | if (result != OTI6858_CTRL_PKT_SIZE) { | ||
601 | /* assume default (after power-on reset) values */ | ||
602 | buf->divisor = cpu_to_le16(0x009c); /* 38400 bps */ | ||
603 | buf->frame_fmt = 0x03; /* 8N1 */ | ||
604 | buf->something = 0x43; | ||
605 | buf->control = 0x4c; /* DTR, RTS */ | ||
606 | buf->tx_status = 0x00; | ||
607 | buf->pin_state = 0x5b; /* RTS, CTS, DSR, DTR, RI, DCD */ | ||
608 | buf->rx_bytes_avail = 0x00; | ||
609 | } | ||
610 | |||
611 | spin_lock_irqsave(&priv->lock, flags); | ||
612 | memcpy(&priv->status, buf, OTI6858_CTRL_PKT_SIZE); | ||
613 | priv->pending_setup.divisor = buf->divisor; | ||
614 | priv->pending_setup.frame_fmt = buf->frame_fmt; | ||
615 | priv->pending_setup.control = buf->control; | ||
616 | spin_unlock_irqrestore(&priv->lock, flags); | ||
617 | kfree(buf); | ||
618 | |||
619 | dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
620 | port->interrupt_in_urb->dev = serial->dev; | ||
621 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | ||
622 | if (result != 0) { | ||
623 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" | ||
624 | " with error %d\n", __FUNCTION__, result); | ||
625 | oti6858_close(port, NULL); | ||
626 | return -EPROTO; | ||
627 | } | ||
628 | |||
629 | /* setup termios */ | ||
630 | if (port->tty) | ||
631 | oti6858_set_termios(port, &tmp_termios); | ||
632 | |||
633 | return 0; | ||
634 | } | ||
635 | |||
636 | static void oti6858_close(struct usb_serial_port *port, struct file *filp) | ||
637 | { | ||
638 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
639 | unsigned long flags; | ||
640 | long timeout; | ||
641 | wait_queue_t wait; | ||
642 | |||
643 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
644 | |||
645 | /* wait for data to drain from the buffer */ | ||
646 | spin_lock_irqsave(&priv->lock, flags); | ||
647 | timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */ | ||
648 | init_waitqueue_entry(&wait, current); | ||
649 | add_wait_queue(&port->tty->write_wait, &wait); | ||
650 | dbg("%s(): entering wait loop", __FUNCTION__); | ||
651 | for (;;) { | ||
652 | set_current_state(TASK_INTERRUPTIBLE); | ||
653 | if (pl2303_buf_data_avail(priv->buf) == 0 | ||
654 | || timeout == 0 || signal_pending(current) | ||
655 | || !usb_get_intfdata(port->serial->interface)) /* disconnect */ | ||
656 | break; | ||
657 | spin_unlock_irqrestore(&priv->lock, flags); | ||
658 | timeout = schedule_timeout(timeout); | ||
659 | spin_lock_irqsave(&priv->lock, flags); | ||
660 | } | ||
661 | set_current_state(TASK_RUNNING); | ||
662 | remove_wait_queue(&port->tty->write_wait, &wait); | ||
663 | dbg("%s(): after wait loop", __FUNCTION__); | ||
664 | |||
665 | /* clear out any remaining data in the buffer */ | ||
666 | pl2303_buf_clear(priv->buf); | ||
667 | spin_unlock_irqrestore(&priv->lock, flags); | ||
668 | |||
669 | /* wait for characters to drain from the device */ | ||
670 | /* (this is long enough for the entire 256 byte */ | ||
671 | /* pl2303 hardware buffer to drain with no flow */ | ||
672 | /* control for data rates of 1200 bps or more, */ | ||
673 | /* for lower rates we should really know how much */ | ||
674 | /* data is in the buffer to compute a delay */ | ||
675 | /* that is not unnecessarily long) */ | ||
676 | /* FIXME | ||
677 | bps = tty_get_baud_rate(port->tty); | ||
678 | if (bps > 1200) | ||
679 | timeout = max((HZ*2560)/bps,HZ/10); | ||
680 | else | ||
681 | */ | ||
682 | timeout = 2*HZ; | ||
683 | schedule_timeout_interruptible(timeout); | ||
684 | dbg("%s(): after schedule_timeout_interruptible()", __FUNCTION__); | ||
685 | |||
686 | /* cancel scheduled setup */ | ||
687 | cancel_delayed_work(&priv->delayed_setup_work); | ||
688 | cancel_delayed_work(&priv->delayed_write_work); | ||
689 | flush_scheduled_work(); | ||
690 | |||
691 | /* shutdown our urbs */ | ||
692 | dbg("%s(): shutting down urbs", __FUNCTION__); | ||
693 | usb_kill_urb(port->write_urb); | ||
694 | usb_kill_urb(port->read_urb); | ||
695 | usb_kill_urb(port->interrupt_in_urb); | ||
696 | |||
697 | /* | ||
698 | if (port->tty && (port->tty->termios->c_cflag) & HUPCL) { | ||
699 | // drop DTR and RTS | ||
700 | spin_lock_irqsave(&priv->lock, flags); | ||
701 | priv->pending_setup.control &= ~CONTROL_MASK; | ||
702 | spin_unlock_irqrestore(&priv->lock, flags); | ||
703 | } | ||
704 | */ | ||
705 | } | ||
706 | |||
707 | static int oti6858_tiocmset(struct usb_serial_port *port, struct file *file, | ||
708 | unsigned int set, unsigned int clear) | ||
709 | { | ||
710 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
711 | unsigned long flags; | ||
712 | u8 control; | ||
713 | |||
714 | dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)", | ||
715 | __FUNCTION__, port->number, set, clear); | ||
716 | |||
717 | if (!usb_get_intfdata(port->serial->interface)) | ||
718 | return -ENODEV; | ||
719 | |||
720 | /* FIXME: check if this is correct (active high/low) */ | ||
721 | spin_lock_irqsave(&priv->lock, flags); | ||
722 | control = priv->pending_setup.control; | ||
723 | if ((set & TIOCM_RTS) != 0) | ||
724 | control |= CONTROL_RTS_HIGH; | ||
725 | if ((set & TIOCM_DTR) != 0) | ||
726 | control |= CONTROL_DTR_HIGH; | ||
727 | if ((clear & TIOCM_RTS) != 0) | ||
728 | control &= ~CONTROL_RTS_HIGH; | ||
729 | if ((clear & TIOCM_DTR) != 0) | ||
730 | control &= ~CONTROL_DTR_HIGH; | ||
731 | |||
732 | if (control != priv->pending_setup.control) { | ||
733 | priv->pending_setup.control = control; | ||
734 | } | ||
735 | spin_unlock_irqrestore(&priv->lock, flags); | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | static int oti6858_tiocmget(struct usb_serial_port *port, struct file *file) | ||
741 | { | ||
742 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
743 | unsigned long flags; | ||
744 | unsigned pin_state; | ||
745 | unsigned result = 0; | ||
746 | |||
747 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
748 | |||
749 | if (!usb_get_intfdata(port->serial->interface)) | ||
750 | return -ENODEV; | ||
751 | |||
752 | spin_lock_irqsave(&priv->lock, flags); | ||
753 | pin_state = priv->status.pin_state & PIN_MASK; | ||
754 | spin_unlock_irqrestore(&priv->lock, flags); | ||
755 | |||
756 | /* FIXME: check if this is correct (active high/low) */ | ||
757 | if ((pin_state & PIN_RTS) != 0) | ||
758 | result |= TIOCM_RTS; | ||
759 | if ((pin_state & PIN_CTS) != 0) | ||
760 | result |= TIOCM_CTS; | ||
761 | if ((pin_state & PIN_DSR) != 0) | ||
762 | result |= TIOCM_DSR; | ||
763 | if ((pin_state & PIN_DTR) != 0) | ||
764 | result |= TIOCM_DTR; | ||
765 | if ((pin_state & PIN_RI) != 0) | ||
766 | result |= TIOCM_RI; | ||
767 | if ((pin_state & PIN_DCD) != 0) | ||
768 | result |= TIOCM_CD; | ||
769 | |||
770 | dbg("%s() = 0x%08x", __FUNCTION__, result); | ||
771 | |||
772 | return result; | ||
773 | } | ||
774 | |||
775 | static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | ||
776 | { | ||
777 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
778 | unsigned long flags; | ||
779 | unsigned int prev, status; | ||
780 | unsigned int changed; | ||
781 | |||
782 | spin_lock_irqsave(&priv->lock, flags); | ||
783 | prev = priv->status.pin_state; | ||
784 | spin_unlock_irqrestore(&priv->lock, flags); | ||
785 | |||
786 | while (1) { | ||
787 | wait_event_interruptible(priv->intr_wait, priv->status.pin_state != prev); | ||
788 | if (signal_pending(current)) | ||
789 | return -ERESTARTSYS; | ||
790 | |||
791 | spin_lock_irqsave(&priv->lock, flags); | ||
792 | status = priv->status.pin_state & PIN_MASK; | ||
793 | spin_unlock_irqrestore(&priv->lock, flags); | ||
794 | |||
795 | changed = prev ^ status; | ||
796 | /* FIXME: check if this is correct (active high/low) */ | ||
797 | if ( ((arg & TIOCM_RNG) && (changed & PIN_RI)) || | ||
798 | ((arg & TIOCM_DSR) && (changed & PIN_DSR)) || | ||
799 | ((arg & TIOCM_CD) && (changed & PIN_DCD)) || | ||
800 | ((arg & TIOCM_CTS) && (changed & PIN_CTS))) { | ||
801 | return 0; | ||
802 | } | ||
803 | prev = status; | ||
804 | } | ||
805 | |||
806 | /* NOTREACHED */ | ||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | static int oti6858_ioctl(struct usb_serial_port *port, struct file *file, | ||
811 | unsigned int cmd, unsigned long arg) | ||
812 | { | ||
813 | void __user *user_arg = (void __user *) arg; | ||
814 | unsigned int x; | ||
815 | |||
816 | dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)", | ||
817 | __FUNCTION__, port->number, cmd, arg); | ||
818 | |||
819 | switch (cmd) { | ||
820 | case TCGETS: | ||
821 | if (copy_to_user(user_arg, port->tty->termios, | ||
822 | sizeof(struct ktermios))) { | ||
823 | return -EFAULT; | ||
824 | } | ||
825 | return 0; | ||
826 | |||
827 | case TCSETS: | ||
828 | case TCSETSW: /* FIXME: this is not the same! */ | ||
829 | case TCSETSF: /* FIXME: this is not the same! */ | ||
830 | if (copy_from_user(port->tty->termios, user_arg, | ||
831 | sizeof(struct ktermios))) { | ||
832 | return -EFAULT; | ||
833 | } | ||
834 | oti6858_set_termios(port, NULL); | ||
835 | return 0; | ||
836 | |||
837 | case TCFLSH: | ||
838 | /* FIXME */ | ||
839 | return 0; | ||
840 | |||
841 | case TIOCMBIS: | ||
842 | if (copy_from_user(&x, user_arg, sizeof(x))) | ||
843 | return -EFAULT; | ||
844 | return oti6858_tiocmset(port, NULL, x, 0); | ||
845 | |||
846 | case TIOCMBIC: | ||
847 | if (copy_from_user(&x, user_arg, sizeof(x))) | ||
848 | return -EFAULT; | ||
849 | return oti6858_tiocmset(port, NULL, 0, x); | ||
850 | |||
851 | case TIOCGSERIAL: | ||
852 | if (copy_to_user(user_arg, port->tty->termios, | ||
853 | sizeof(struct ktermios))) { | ||
854 | return -EFAULT; | ||
855 | } | ||
856 | return 0; | ||
857 | |||
858 | case TIOCSSERIAL: | ||
859 | if (copy_from_user(port->tty->termios, user_arg, | ||
860 | sizeof(struct ktermios))) { | ||
861 | return -EFAULT; | ||
862 | } | ||
863 | oti6858_set_termios(port, NULL); | ||
864 | return 0; | ||
865 | |||
866 | case TIOCMIWAIT: | ||
867 | dbg("%s(): TIOCMIWAIT", __FUNCTION__); | ||
868 | return wait_modem_info(port, arg); | ||
869 | |||
870 | default: | ||
871 | dbg("%s(): 0x%04x not supported", __FUNCTION__, cmd); | ||
872 | break; | ||
873 | } | ||
874 | |||
875 | return -ENOIOCTLCMD; | ||
876 | } | ||
877 | |||
878 | static void oti6858_break_ctl(struct usb_serial_port *port, int break_state) | ||
879 | { | ||
880 | int state; | ||
881 | |||
882 | dbg("%s(port = %d)", __FUNCTION__, port->number); | ||
883 | |||
884 | state = (break_state == 0) ? 0 : 1; | ||
885 | dbg("%s(): turning break %s", __FUNCTION__, state ? "on" : "off"); | ||
886 | |||
887 | /* FIXME */ | ||
888 | /* | ||
889 | result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0), | ||
890 | BREAK_REQUEST, BREAK_REQUEST_TYPE, state, | ||
891 | 0, NULL, 0, 100); | ||
892 | if (result != 0) | ||
893 | dbg("%s(): error sending break", __FUNCTION__); | ||
894 | */ | ||
895 | } | ||
896 | |||
897 | static void oti6858_shutdown(struct usb_serial *serial) | ||
898 | { | ||
899 | struct oti6858_private *priv; | ||
900 | int i; | ||
901 | |||
902 | dbg("%s()", __FUNCTION__); | ||
903 | |||
904 | for (i = 0; i < serial->num_ports; ++i) { | ||
905 | priv = usb_get_serial_port_data(serial->port[i]); | ||
906 | if (priv) { | ||
907 | pl2303_buf_free(priv->buf); | ||
908 | kfree(priv); | ||
909 | usb_set_serial_port_data(serial->port[i], NULL); | ||
910 | } | ||
911 | } | ||
912 | } | ||
913 | |||
914 | static void oti6858_read_int_callback(struct urb *urb) | ||
915 | { | ||
916 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | ||
917 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
918 | int transient = 0, can_recv = 0, resubmit = 1; | ||
919 | int status = urb->status; | ||
920 | |||
921 | dbg("%s(port = %d, status = %d)", | ||
922 | __FUNCTION__, port->number, status); | ||
923 | |||
924 | switch (status) { | ||
925 | case 0: | ||
926 | /* success */ | ||
927 | break; | ||
928 | case -ECONNRESET: | ||
929 | case -ENOENT: | ||
930 | case -ESHUTDOWN: | ||
931 | /* this urb is terminated, clean up */ | ||
932 | dbg("%s(): urb shutting down with status: %d", | ||
933 | __FUNCTION__, status); | ||
934 | return; | ||
935 | default: | ||
936 | dbg("%s(): nonzero urb status received: %d", | ||
937 | __FUNCTION__, status); | ||
938 | break; | ||
939 | } | ||
940 | |||
941 | if (status == 0 && urb->actual_length == OTI6858_CTRL_PKT_SIZE) { | ||
942 | struct oti6858_control_pkt *xs = urb->transfer_buffer; | ||
943 | unsigned long flags; | ||
944 | |||
945 | spin_lock_irqsave(&priv->lock, flags); | ||
946 | |||
947 | if (!priv->transient) { | ||
948 | if (!OTI6858_CTRL_EQUALS_PENDING(xs, priv)) { | ||
949 | if (xs->rx_bytes_avail == 0) { | ||
950 | priv->transient = 4; | ||
951 | priv->setup_done = 0; | ||
952 | resubmit = 0; | ||
953 | dbg("%s(): scheduling setup_line()", | ||
954 | __FUNCTION__); | ||
955 | schedule_delayed_work(&priv->delayed_setup_work, 0); | ||
956 | } | ||
957 | } | ||
958 | } else { | ||
959 | if (OTI6858_CTRL_EQUALS_PENDING(xs, priv)) { | ||
960 | priv->transient = 0; | ||
961 | } else if (!priv->setup_done) { | ||
962 | resubmit = 0; | ||
963 | } else if (--priv->transient == 0) { | ||
964 | if (xs->rx_bytes_avail == 0) { | ||
965 | priv->transient = 4; | ||
966 | priv->setup_done = 0; | ||
967 | resubmit = 0; | ||
968 | dbg("%s(): scheduling setup_line()", | ||
969 | __FUNCTION__); | ||
970 | schedule_delayed_work(&priv->delayed_setup_work, 0); | ||
971 | } | ||
972 | } | ||
973 | } | ||
974 | |||
975 | if (!priv->transient) { | ||
976 | if (xs->pin_state != priv->status.pin_state) | ||
977 | wake_up_interruptible(&priv->intr_wait); | ||
978 | memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE); | ||
979 | } | ||
980 | |||
981 | if (!priv->transient && xs->rx_bytes_avail != 0) { | ||
982 | can_recv = xs->rx_bytes_avail; | ||
983 | priv->flags.read_urb_in_use = 1; | ||
984 | } | ||
985 | |||
986 | transient = priv->transient; | ||
987 | spin_unlock_irqrestore(&priv->lock, flags); | ||
988 | } | ||
989 | |||
990 | if (can_recv) { | ||
991 | int result; | ||
992 | |||
993 | port->read_urb->dev = port->serial->dev; | ||
994 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | ||
995 | if (result != 0) { | ||
996 | priv->flags.read_urb_in_use = 0; | ||
997 | dev_err(&port->dev, "%s(): usb_submit_urb() failed," | ||
998 | " error %d\n", __FUNCTION__, result); | ||
999 | } else { | ||
1000 | resubmit = 0; | ||
1001 | } | ||
1002 | } else if (!transient) { | ||
1003 | unsigned long flags; | ||
1004 | |||
1005 | spin_lock_irqsave(&priv->lock, flags); | ||
1006 | if (priv->flags.write_urb_in_use == 0 | ||
1007 | && pl2303_buf_data_avail(priv->buf) != 0) { | ||
1008 | schedule_delayed_work(&priv->delayed_write_work,0); | ||
1009 | resubmit = 0; | ||
1010 | } | ||
1011 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1012 | } | ||
1013 | |||
1014 | if (resubmit) { | ||
1015 | int result; | ||
1016 | |||
1017 | // dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
1018 | urb->dev = port->serial->dev; | ||
1019 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
1020 | if (result != 0) { | ||
1021 | dev_err(&urb->dev->dev, | ||
1022 | "%s(): usb_submit_urb() failed with" | ||
1023 | " error %d\n", __FUNCTION__, result); | ||
1024 | } | ||
1025 | } | ||
1026 | } | ||
1027 | |||
1028 | static void oti6858_read_bulk_callback(struct urb *urb) | ||
1029 | { | ||
1030 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | ||
1031 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
1032 | struct tty_struct *tty; | ||
1033 | unsigned char *data = urb->transfer_buffer; | ||
1034 | unsigned long flags; | ||
1035 | int i, result; | ||
1036 | int status = urb->status; | ||
1037 | char tty_flag; | ||
1038 | |||
1039 | dbg("%s(port = %d, status = %d)", | ||
1040 | __FUNCTION__, port->number, status); | ||
1041 | |||
1042 | spin_lock_irqsave(&priv->lock, flags); | ||
1043 | priv->flags.read_urb_in_use = 0; | ||
1044 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1045 | |||
1046 | if (status != 0) { | ||
1047 | if (!port->open_count) { | ||
1048 | dbg("%s(): port is closed, exiting", __FUNCTION__); | ||
1049 | return; | ||
1050 | } | ||
1051 | /* | ||
1052 | if (status == -EPROTO) { | ||
1053 | // PL2303 mysteriously fails with -EPROTO reschedule the read | ||
1054 | dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__); | ||
1055 | result = usb_submit_urb(urb, GFP_ATOMIC); | ||
1056 | if (result) | ||
1057 | dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | ||
1058 | return; | ||
1059 | } | ||
1060 | */ | ||
1061 | dbg("%s(): unable to handle the error, exiting", __FUNCTION__); | ||
1062 | return; | ||
1063 | } | ||
1064 | |||
1065 | // get tty_flag from status | ||
1066 | tty_flag = TTY_NORMAL; | ||
1067 | |||
1068 | /* FIXME: probably, errors will be signalled using interrupt pipe! */ | ||
1069 | /* | ||
1070 | // break takes precedence over parity, | ||
1071 | // which takes precedence over framing errors | ||
1072 | if (status & UART_BREAK_ERROR ) | ||
1073 | tty_flag = TTY_BREAK; | ||
1074 | else if (status & UART_PARITY_ERROR) | ||
1075 | tty_flag = TTY_PARITY; | ||
1076 | else if (status & UART_FRAME_ERROR) | ||
1077 | tty_flag = TTY_FRAME; | ||
1078 | dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag); | ||
1079 | */ | ||
1080 | |||
1081 | tty = port->tty; | ||
1082 | if (tty != NULL && urb->actual_length > 0) { | ||
1083 | tty_buffer_request_room(tty, urb->actual_length); | ||
1084 | for (i = 0; i < urb->actual_length; ++i) | ||
1085 | tty_insert_flip_char(tty, data[i], tty_flag); | ||
1086 | tty_flip_buffer_push(tty); | ||
1087 | } | ||
1088 | |||
1089 | // schedule the interrupt urb if we are still open */ | ||
1090 | if (port->open_count != 0) { | ||
1091 | port->interrupt_in_urb->dev = port->serial->dev; | ||
1092 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | ||
1093 | if (result != 0) { | ||
1094 | dev_err(&port->dev, "%s(): usb_submit_urb() failed," | ||
1095 | " error %d\n", __FUNCTION__, result); | ||
1096 | } | ||
1097 | } | ||
1098 | } | ||
1099 | |||
1100 | static void oti6858_write_bulk_callback(struct urb *urb) | ||
1101 | { | ||
1102 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | ||
1103 | struct oti6858_private *priv = usb_get_serial_port_data(port); | ||
1104 | int status = urb->status; | ||
1105 | int result; | ||
1106 | |||
1107 | dbg("%s(port = %d, status = %d)", | ||
1108 | __FUNCTION__, port->number, status); | ||
1109 | |||
1110 | switch (status) { | ||
1111 | case 0: | ||
1112 | /* success */ | ||
1113 | break; | ||
1114 | case -ECONNRESET: | ||
1115 | case -ENOENT: | ||
1116 | case -ESHUTDOWN: | ||
1117 | /* this urb is terminated, clean up */ | ||
1118 | dbg("%s(): urb shutting down with status: %d", | ||
1119 | __FUNCTION__, status); | ||
1120 | priv->flags.write_urb_in_use = 0; | ||
1121 | return; | ||
1122 | default: | ||
1123 | /* error in the urb, so we have to resubmit it */ | ||
1124 | dbg("%s(): nonzero write bulk status received: %d", | ||
1125 | __FUNCTION__, status); | ||
1126 | dbg("%s(): overflow in write", __FUNCTION__); | ||
1127 | |||
1128 | port->write_urb->transfer_buffer_length = 1; | ||
1129 | port->write_urb->dev = port->serial->dev; | ||
1130 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | ||
1131 | if (result) { | ||
1132 | dev_err(&port->dev, "%s(): usb_submit_urb() failed," | ||
1133 | " error %d\n", __FUNCTION__, result); | ||
1134 | } else { | ||
1135 | return; | ||
1136 | } | ||
1137 | } | ||
1138 | |||
1139 | priv->flags.write_urb_in_use = 0; | ||
1140 | |||
1141 | // schedule the interrupt urb if we are still open */ | ||
1142 | port->interrupt_in_urb->dev = port->serial->dev; | ||
1143 | dbg("%s(): submitting interrupt urb", __FUNCTION__); | ||
1144 | result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); | ||
1145 | if (result != 0) { | ||
1146 | dev_err(&port->dev, "%s(): failed submitting int urb," | ||
1147 | " error %d\n", __FUNCTION__, result); | ||
1148 | } | ||
1149 | } | ||
1150 | |||
1151 | |||
1152 | /* | ||
1153 | * pl2303_buf_alloc | ||
1154 | * | ||
1155 | * Allocate a circular buffer and all associated memory. | ||
1156 | */ | ||
1157 | static struct pl2303_buf *pl2303_buf_alloc(unsigned int size) | ||
1158 | { | ||
1159 | struct pl2303_buf *pb; | ||
1160 | |||
1161 | if (size == 0) | ||
1162 | return NULL; | ||
1163 | |||
1164 | pb = (struct pl2303_buf *)kmalloc(sizeof(struct pl2303_buf), GFP_KERNEL); | ||
1165 | if (pb == NULL) | ||
1166 | return NULL; | ||
1167 | |||
1168 | pb->buf_buf = kmalloc(size, GFP_KERNEL); | ||
1169 | if (pb->buf_buf == NULL) { | ||
1170 | kfree(pb); | ||
1171 | return NULL; | ||
1172 | } | ||
1173 | |||
1174 | pb->buf_size = size; | ||
1175 | pb->buf_get = pb->buf_put = pb->buf_buf; | ||
1176 | |||
1177 | return pb; | ||
1178 | } | ||
1179 | |||
1180 | /* | ||
1181 | * pl2303_buf_free | ||
1182 | * | ||
1183 | * Free the buffer and all associated memory. | ||
1184 | */ | ||
1185 | static void pl2303_buf_free(struct pl2303_buf *pb) | ||
1186 | { | ||
1187 | if (pb) { | ||
1188 | kfree(pb->buf_buf); | ||
1189 | kfree(pb); | ||
1190 | } | ||
1191 | } | ||
1192 | |||
1193 | /* | ||
1194 | * pl2303_buf_clear | ||
1195 | * | ||
1196 | * Clear out all data in the circular buffer. | ||
1197 | */ | ||
1198 | static void pl2303_buf_clear(struct pl2303_buf *pb) | ||
1199 | { | ||
1200 | if (pb != NULL) { | ||
1201 | /* equivalent to a get of all data available */ | ||
1202 | pb->buf_get = pb->buf_put; | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1206 | /* | ||
1207 | * pl2303_buf_data_avail | ||
1208 | * | ||
1209 | * Return the number of bytes of data available in the circular | ||
1210 | * buffer. | ||
1211 | */ | ||
1212 | static unsigned int pl2303_buf_data_avail(struct pl2303_buf *pb) | ||
1213 | { | ||
1214 | if (pb == NULL) | ||
1215 | return 0; | ||
1216 | return ((pb->buf_size + pb->buf_put - pb->buf_get) % pb->buf_size); | ||
1217 | } | ||
1218 | |||
1219 | /* | ||
1220 | * pl2303_buf_space_avail | ||
1221 | * | ||
1222 | * Return the number of bytes of space available in the circular | ||
1223 | * buffer. | ||
1224 | */ | ||
1225 | static unsigned int pl2303_buf_space_avail(struct pl2303_buf *pb) | ||
1226 | { | ||
1227 | if (pb == NULL) | ||
1228 | return 0; | ||
1229 | return ((pb->buf_size + pb->buf_get - pb->buf_put - 1) % pb->buf_size); | ||
1230 | } | ||
1231 | |||
1232 | /* | ||
1233 | * pl2303_buf_put | ||
1234 | * | ||
1235 | * Copy data data from a user buffer and put it into the circular buffer. | ||
1236 | * Restrict to the amount of space available. | ||
1237 | * | ||
1238 | * Return the number of bytes copied. | ||
1239 | */ | ||
1240 | static unsigned int pl2303_buf_put(struct pl2303_buf *pb, const char *buf, | ||
1241 | unsigned int count) | ||
1242 | { | ||
1243 | unsigned int len; | ||
1244 | |||
1245 | if (pb == NULL) | ||
1246 | return 0; | ||
1247 | |||
1248 | len = pl2303_buf_space_avail(pb); | ||
1249 | if (count > len) | ||
1250 | count = len; | ||
1251 | |||
1252 | if (count == 0) | ||
1253 | return 0; | ||
1254 | |||
1255 | len = pb->buf_buf + pb->buf_size - pb->buf_put; | ||
1256 | if (count > len) { | ||
1257 | memcpy(pb->buf_put, buf, len); | ||
1258 | memcpy(pb->buf_buf, buf+len, count - len); | ||
1259 | pb->buf_put = pb->buf_buf + count - len; | ||
1260 | } else { | ||
1261 | memcpy(pb->buf_put, buf, count); | ||
1262 | if (count < len) | ||
1263 | pb->buf_put += count; | ||
1264 | else /* count == len */ | ||
1265 | pb->buf_put = pb->buf_buf; | ||
1266 | } | ||
1267 | |||
1268 | return count; | ||
1269 | } | ||
1270 | |||
1271 | /* | ||
1272 | * pl2303_buf_get | ||
1273 | * | ||
1274 | * Get data from the circular buffer and copy to the given buffer. | ||
1275 | * Restrict to the amount of data available. | ||
1276 | * | ||
1277 | * Return the number of bytes copied. | ||
1278 | */ | ||
1279 | static unsigned int pl2303_buf_get(struct pl2303_buf *pb, char *buf, | ||
1280 | unsigned int count) | ||
1281 | { | ||
1282 | unsigned int len; | ||
1283 | |||
1284 | if (pb == NULL) | ||
1285 | return 0; | ||
1286 | |||
1287 | len = pl2303_buf_data_avail(pb); | ||
1288 | if (count > len) | ||
1289 | count = len; | ||
1290 | |||
1291 | if (count == 0) | ||
1292 | return 0; | ||
1293 | |||
1294 | len = pb->buf_buf + pb->buf_size - pb->buf_get; | ||
1295 | if (count > len) { | ||
1296 | memcpy(buf, pb->buf_get, len); | ||
1297 | memcpy(buf+len, pb->buf_buf, count - len); | ||
1298 | pb->buf_get = pb->buf_buf + count - len; | ||
1299 | } else { | ||
1300 | memcpy(buf, pb->buf_get, count); | ||
1301 | if (count < len) | ||
1302 | pb->buf_get += count; | ||
1303 | else /* count == len */ | ||
1304 | pb->buf_get = pb->buf_buf; | ||
1305 | } | ||
1306 | |||
1307 | return count; | ||
1308 | } | ||
1309 | |||
1310 | /* module description and (de)initialization */ | ||
1311 | |||
1312 | static int __init oti6858_init(void) | ||
1313 | { | ||
1314 | int retval; | ||
1315 | |||
1316 | if ((retval = usb_serial_register(&oti6858_device)) == 0) { | ||
1317 | if ((retval = usb_register(&oti6858_driver)) != 0) | ||
1318 | usb_serial_deregister(&oti6858_device); | ||
1319 | else | ||
1320 | return 0; | ||
1321 | } | ||
1322 | |||
1323 | return retval; | ||
1324 | } | ||
1325 | |||
1326 | static void __exit oti6858_exit(void) | ||
1327 | { | ||
1328 | usb_deregister(&oti6858_driver); | ||
1329 | usb_serial_deregister(&oti6858_device); | ||
1330 | } | ||
1331 | |||
1332 | module_init(oti6858_init); | ||
1333 | module_exit(oti6858_exit); | ||
1334 | |||
1335 | MODULE_DESCRIPTION(OTI6858_DESCRIPTION); | ||
1336 | MODULE_AUTHOR(OTI6858_AUTHOR); | ||
1337 | MODULE_VERSION(OTI6858_VERSION); | ||
1338 | MODULE_LICENSE("GPL"); | ||
1339 | |||
1340 | module_param(debug, bool, S_IRUGO | S_IWUSR); | ||
1341 | MODULE_PARM_DESC(debug, "enable debug output"); | ||
1342 | |||
diff --git a/drivers/usb/serial/oti6858.h b/drivers/usb/serial/oti6858.h new file mode 100644 index 000000000000..704ac3a532b3 --- /dev/null +++ b/drivers/usb/serial/oti6858.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * Ours Technology Inc. OTi-6858 USB to serial adapter driver. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | */ | ||
9 | #ifndef __LINUX_USB_SERIAL_OTI6858_H | ||
10 | #define __LINUX_USB_SERIAL_OTI6858_H | ||
11 | |||
12 | #define OTI6858_VENDOR_ID 0x0ea0 | ||
13 | #define OTI6858_PRODUCT_ID 0x6858 | ||
14 | |||
15 | #endif | ||
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 83dfae93a45d..f9f85f56f0db 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -1,14 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * Prolific PL2303 USB to serial adaptor driver | 2 | * Prolific PL2303 USB to serial adaptor driver |
3 | * | 3 | * |
4 | * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com) | 4 | * Copyright (C) 2001-2007 Greg Kroah-Hartman (greg@kroah.com) |
5 | * Copyright (C) 2003 IBM Corp. | 5 | * Copyright (C) 2003 IBM Corp. |
6 | * | 6 | * |
7 | * Original driver for 2.2.x by anonymous | 7 | * Original driver for 2.2.x by anonymous |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or |
10 | * it under the terms of the GNU General Public License as published by | 10 | * modify it under the terms of the GNU General Public License version |
11 | * the Free Software Foundation; either version 2 of the License. | 11 | * 2 as published by the Free Software Foundation. |
12 | * | 12 | * |
13 | * See Documentation/usb/usb-serial.txt for more information on using this driver | 13 | * See Documentation/usb/usb-serial.txt for more information on using this driver |
14 | * | 14 | * |
@@ -484,15 +484,6 @@ static void pl2303_set_termios(struct usb_serial_port *port, | |||
484 | spin_unlock_irqrestore(&priv->lock, flags); | 484 | spin_unlock_irqrestore(&priv->lock, flags); |
485 | 485 | ||
486 | cflag = port->tty->termios->c_cflag; | 486 | cflag = port->tty->termios->c_cflag; |
487 | /* check that they really want us to change something */ | ||
488 | if (old_termios) { | ||
489 | if ((cflag == old_termios->c_cflag) && | ||
490 | (RELEVANT_IFLAG(port->tty->termios->c_iflag) == | ||
491 | RELEVANT_IFLAG(old_termios->c_iflag))) { | ||
492 | dbg("%s - nothing to change...", __FUNCTION__); | ||
493 | return; | ||
494 | } | ||
495 | } | ||
496 | 487 | ||
497 | buf = kzalloc(7, GFP_KERNEL); | 488 | buf = kzalloc(7, GFP_KERNEL); |
498 | if (!buf) { | 489 | if (!buf) { |
@@ -517,29 +508,7 @@ static void pl2303_set_termios(struct usb_serial_port *port, | |||
517 | dbg("%s - data bits = %d", __FUNCTION__, buf[6]); | 508 | dbg("%s - data bits = %d", __FUNCTION__, buf[6]); |
518 | } | 509 | } |
519 | 510 | ||
520 | baud = 0; | 511 | baud = tty_get_baud_rate(port->tty);; |
521 | switch (cflag & CBAUD) { | ||
522 | case B0: baud = 0; break; | ||
523 | case B75: baud = 75; break; | ||
524 | case B150: baud = 150; break; | ||
525 | case B300: baud = 300; break; | ||
526 | case B600: baud = 600; break; | ||
527 | case B1200: baud = 1200; break; | ||
528 | case B1800: baud = 1800; break; | ||
529 | case B2400: baud = 2400; break; | ||
530 | case B4800: baud = 4800; break; | ||
531 | case B9600: baud = 9600; break; | ||
532 | case B19200: baud = 19200; break; | ||
533 | case B38400: baud = 38400; break; | ||
534 | case B57600: baud = 57600; break; | ||
535 | case B115200: baud = 115200; break; | ||
536 | case B230400: baud = 230400; break; | ||
537 | case B460800: baud = 460800; break; | ||
538 | default: | ||
539 | dev_err(&port->dev, "pl2303 driver does not support" | ||
540 | " the baudrate requested (fix it)\n"); | ||
541 | break; | ||
542 | } | ||
543 | dbg("%s - baud = %d", __FUNCTION__, baud); | 512 | dbg("%s - baud = %d", __FUNCTION__, baud); |
544 | if (baud) { | 513 | if (baud) { |
545 | buf[0] = baud & 0xff; | 514 | buf[0] = baud & 0xff; |
@@ -617,6 +586,13 @@ static void pl2303_set_termios(struct usb_serial_port *port, | |||
617 | VENDOR_WRITE_REQUEST_TYPE, | 586 | VENDOR_WRITE_REQUEST_TYPE, |
618 | 0x0, index, NULL, 0, 100); | 587 | 0x0, index, NULL, 0, 100); |
619 | dbg("0x40:0x1:0x0:0x%x %d", index, i); | 588 | dbg("0x40:0x1:0x0:0x%x %d", index, i); |
589 | } else { | ||
590 | i = usb_control_msg(serial->dev, | ||
591 | usb_sndctrlpipe(serial->dev, 0), | ||
592 | VENDOR_WRITE_REQUEST, | ||
593 | VENDOR_WRITE_REQUEST_TYPE, | ||
594 | 0x0, 0x0, NULL, 0, 100); | ||
595 | dbg ("0x40:0x1:0x0:0x0 %d", i); | ||
620 | } | 596 | } |
621 | 597 | ||
622 | kfree(buf); | 598 | kfree(buf); |
@@ -954,11 +930,12 @@ static void pl2303_read_int_callback(struct urb *urb) | |||
954 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | 930 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; |
955 | unsigned char *data = urb->transfer_buffer; | 931 | unsigned char *data = urb->transfer_buffer; |
956 | unsigned int actual_length = urb->actual_length; | 932 | unsigned int actual_length = urb->actual_length; |
957 | int status; | 933 | int status = urb->status; |
934 | int retval; | ||
958 | 935 | ||
959 | dbg("%s (%d)", __FUNCTION__, port->number); | 936 | dbg("%s (%d)", __FUNCTION__, port->number); |
960 | 937 | ||
961 | switch (urb->status) { | 938 | switch (status) { |
962 | case 0: | 939 | case 0: |
963 | /* success */ | 940 | /* success */ |
964 | break; | 941 | break; |
@@ -967,11 +944,11 @@ static void pl2303_read_int_callback(struct urb *urb) | |||
967 | case -ESHUTDOWN: | 944 | case -ESHUTDOWN: |
968 | /* this urb is terminated, clean up */ | 945 | /* this urb is terminated, clean up */ |
969 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, | 946 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, |
970 | urb->status); | 947 | status); |
971 | return; | 948 | return; |
972 | default: | 949 | default: |
973 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, | 950 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, |
974 | urb->status); | 951 | status); |
975 | goto exit; | 952 | goto exit; |
976 | } | 953 | } |
977 | 954 | ||
@@ -981,11 +958,11 @@ static void pl2303_read_int_callback(struct urb *urb) | |||
981 | pl2303_update_line_status(port, data, actual_length); | 958 | pl2303_update_line_status(port, data, actual_length); |
982 | 959 | ||
983 | exit: | 960 | exit: |
984 | status = usb_submit_urb(urb, GFP_ATOMIC); | 961 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
985 | if (status) | 962 | if (retval) |
986 | dev_err(&urb->dev->dev, | 963 | dev_err(&urb->dev->dev, |
987 | "%s - usb_submit_urb failed with result %d\n", | 964 | "%s - usb_submit_urb failed with result %d\n", |
988 | __FUNCTION__, status); | 965 | __FUNCTION__, retval); |
989 | } | 966 | } |
990 | 967 | ||
991 | static void pl2303_read_bulk_callback(struct urb *urb) | 968 | static void pl2303_read_bulk_callback(struct urb *urb) |
@@ -997,23 +974,23 @@ static void pl2303_read_bulk_callback(struct urb *urb) | |||
997 | unsigned long flags; | 974 | unsigned long flags; |
998 | int i; | 975 | int i; |
999 | int result; | 976 | int result; |
1000 | u8 status; | 977 | int status = urb->status; |
978 | u8 line_status; | ||
1001 | char tty_flag; | 979 | char tty_flag; |
1002 | 980 | ||
1003 | dbg("%s - port %d", __FUNCTION__, port->number); | 981 | dbg("%s - port %d", __FUNCTION__, port->number); |
1004 | 982 | ||
1005 | if (urb->status) { | 983 | if (status) { |
1006 | dbg("%s - urb->status = %d", __FUNCTION__, urb->status); | 984 | dbg("%s - urb status = %d", __FUNCTION__, status); |
1007 | if (!port->open_count) { | 985 | if (!port->open_count) { |
1008 | dbg("%s - port is closed, exiting.", __FUNCTION__); | 986 | dbg("%s - port is closed, exiting.", __FUNCTION__); |
1009 | return; | 987 | return; |
1010 | } | 988 | } |
1011 | if (urb->status == -EPROTO) { | 989 | if (status == -EPROTO) { |
1012 | /* PL2303 mysteriously fails with -EPROTO reschedule | 990 | /* PL2303 mysteriously fails with -EPROTO reschedule |
1013 | * the read */ | 991 | * the read */ |
1014 | dbg("%s - caught -EPROTO, resubmitting the urb", | 992 | dbg("%s - caught -EPROTO, resubmitting the urb", |
1015 | __FUNCTION__); | 993 | __FUNCTION__); |
1016 | urb->status = 0; | ||
1017 | urb->dev = port->serial->dev; | 994 | urb->dev = port->serial->dev; |
1018 | result = usb_submit_urb(urb, GFP_ATOMIC); | 995 | result = usb_submit_urb(urb, GFP_ATOMIC); |
1019 | if (result) | 996 | if (result) |
@@ -1033,18 +1010,18 @@ static void pl2303_read_bulk_callback(struct urb *urb) | |||
1033 | tty_flag = TTY_NORMAL; | 1010 | tty_flag = TTY_NORMAL; |
1034 | 1011 | ||
1035 | spin_lock_irqsave(&priv->lock, flags); | 1012 | spin_lock_irqsave(&priv->lock, flags); |
1036 | status = priv->line_status; | 1013 | line_status = priv->line_status; |
1037 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; | 1014 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; |
1038 | spin_unlock_irqrestore(&priv->lock, flags); | 1015 | spin_unlock_irqrestore(&priv->lock, flags); |
1039 | wake_up_interruptible(&priv->delta_msr_wait); | 1016 | wake_up_interruptible(&priv->delta_msr_wait); |
1040 | 1017 | ||
1041 | /* break takes precedence over parity, */ | 1018 | /* break takes precedence over parity, */ |
1042 | /* which takes precedence over framing errors */ | 1019 | /* which takes precedence over framing errors */ |
1043 | if (status & UART_BREAK_ERROR ) | 1020 | if (line_status & UART_BREAK_ERROR ) |
1044 | tty_flag = TTY_BREAK; | 1021 | tty_flag = TTY_BREAK; |
1045 | else if (status & UART_PARITY_ERROR) | 1022 | else if (line_status & UART_PARITY_ERROR) |
1046 | tty_flag = TTY_PARITY; | 1023 | tty_flag = TTY_PARITY; |
1047 | else if (status & UART_FRAME_ERROR) | 1024 | else if (line_status & UART_FRAME_ERROR) |
1048 | tty_flag = TTY_FRAME; | 1025 | tty_flag = TTY_FRAME; |
1049 | dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag); | 1026 | dbg("%s - tty_flag = %d", __FUNCTION__, tty_flag); |
1050 | 1027 | ||
@@ -1052,7 +1029,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) | |||
1052 | if (tty && urb->actual_length) { | 1029 | if (tty && urb->actual_length) { |
1053 | tty_buffer_request_room(tty, urb->actual_length + 1); | 1030 | tty_buffer_request_room(tty, urb->actual_length + 1); |
1054 | /* overrun is special, not associated with a char */ | 1031 | /* overrun is special, not associated with a char */ |
1055 | if (status & UART_OVERRUN_ERROR) | 1032 | if (line_status & UART_OVERRUN_ERROR) |
1056 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | 1033 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); |
1057 | for (i = 0; i < urb->actual_length; ++i) | 1034 | for (i = 0; i < urb->actual_length; ++i) |
1058 | tty_insert_flip_char(tty, data[i], tty_flag); | 1035 | tty_insert_flip_char(tty, data[i], tty_flag); |
@@ -1076,10 +1053,11 @@ static void pl2303_write_bulk_callback(struct urb *urb) | |||
1076 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | 1053 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; |
1077 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 1054 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
1078 | int result; | 1055 | int result; |
1056 | int status = urb->status; | ||
1079 | 1057 | ||
1080 | dbg("%s - port %d", __FUNCTION__, port->number); | 1058 | dbg("%s - port %d", __FUNCTION__, port->number); |
1081 | 1059 | ||
1082 | switch (urb->status) { | 1060 | switch (status) { |
1083 | case 0: | 1061 | case 0: |
1084 | /* success */ | 1062 | /* success */ |
1085 | break; | 1063 | break; |
@@ -1088,14 +1066,14 @@ static void pl2303_write_bulk_callback(struct urb *urb) | |||
1088 | case -ESHUTDOWN: | 1066 | case -ESHUTDOWN: |
1089 | /* this urb is terminated, clean up */ | 1067 | /* this urb is terminated, clean up */ |
1090 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, | 1068 | dbg("%s - urb shutting down with status: %d", __FUNCTION__, |
1091 | urb->status); | 1069 | status); |
1092 | priv->write_urb_in_use = 0; | 1070 | priv->write_urb_in_use = 0; |
1093 | return; | 1071 | return; |
1094 | default: | 1072 | default: |
1095 | /* error in the urb, so we have to resubmit it */ | 1073 | /* error in the urb, so we have to resubmit it */ |
1096 | dbg("%s - Overflow in write", __FUNCTION__); | 1074 | dbg("%s - Overflow in write", __FUNCTION__); |
1097 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, | 1075 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, |
1098 | urb->status); | 1076 | status); |
1099 | port->write_urb->transfer_buffer_length = 1; | 1077 | port->write_urb->transfer_buffer_length = 1; |
1100 | port->write_urb->dev = port->serial->dev; | 1078 | port->write_urb->dev = port->serial->dev; |
1101 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 1079 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 5a03a3fc9386..86899d55d8d8 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c | |||
@@ -211,11 +211,13 @@ static void safe_read_bulk_callback (struct urb *urb) | |||
211 | unsigned char length = urb->actual_length; | 211 | unsigned char length = urb->actual_length; |
212 | int i; | 212 | int i; |
213 | int result; | 213 | int result; |
214 | int status = urb->status; | ||
214 | 215 | ||
215 | dbg ("%s", __FUNCTION__); | 216 | dbg ("%s", __FUNCTION__); |
216 | 217 | ||
217 | if (urb->status) { | 218 | if (status) { |
218 | dbg ("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 219 | dbg("%s - nonzero read bulk status received: %d", |
220 | __FUNCTION__, status); | ||
219 | return; | 221 | return; |
220 | } | 222 | } |
221 | 223 | ||
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index ac1829c6e8f0..e7db20343d1a 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -86,15 +86,14 @@ static int debug; | |||
86 | #define N_IN_URB 4 | 86 | #define N_IN_URB 4 |
87 | #define N_OUT_URB 4 | 87 | #define N_OUT_URB 4 |
88 | #define IN_BUFLEN 4096 | 88 | #define IN_BUFLEN 4096 |
89 | #define OUT_BUFLEN 128 | ||
90 | 89 | ||
91 | struct sierra_port_private { | 90 | struct sierra_port_private { |
91 | spinlock_t lock; /* lock the structure */ | ||
92 | int outstanding_urbs; /* number of out urbs in flight */ | ||
93 | |||
92 | /* Input endpoints and buffer for this port */ | 94 | /* Input endpoints and buffer for this port */ |
93 | struct urb *in_urbs[N_IN_URB]; | 95 | struct urb *in_urbs[N_IN_URB]; |
94 | char in_buffer[N_IN_URB][IN_BUFLEN]; | 96 | char in_buffer[N_IN_URB][IN_BUFLEN]; |
95 | /* Output endpoints and buffer for this port */ | ||
96 | struct urb *out_urbs[N_OUT_URB]; | ||
97 | char out_buffer[N_OUT_URB][OUT_BUFLEN]; | ||
98 | 97 | ||
99 | /* Settings for the port */ | 98 | /* Settings for the port */ |
100 | int rts_state; /* Handshaking pins (outputs) */ | 99 | int rts_state; /* Handshaking pins (outputs) */ |
@@ -103,8 +102,6 @@ struct sierra_port_private { | |||
103 | int dsr_state; | 102 | int dsr_state; |
104 | int dcd_state; | 103 | int dcd_state; |
105 | int ri_state; | 104 | int ri_state; |
106 | |||
107 | unsigned long tx_start_time[N_OUT_URB]; | ||
108 | }; | 105 | }; |
109 | 106 | ||
110 | static int sierra_send_setup(struct usb_serial_port *port) | 107 | static int sierra_send_setup(struct usb_serial_port *port) |
@@ -197,61 +194,98 @@ static int sierra_ioctl(struct usb_serial_port *port, struct file *file, | |||
197 | return -ENOIOCTLCMD; | 194 | return -ENOIOCTLCMD; |
198 | } | 195 | } |
199 | 196 | ||
197 | static void sierra_outdat_callback(struct urb *urb) | ||
198 | { | ||
199 | struct usb_serial_port *port = urb->context; | ||
200 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); | ||
201 | int status = urb->status; | ||
202 | unsigned long flags; | ||
203 | |||
204 | dbg("%s - port %d", __FUNCTION__, port->number); | ||
205 | |||
206 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | ||
207 | kfree(urb->transfer_buffer); | ||
208 | |||
209 | if (status) | ||
210 | dbg("%s - nonzero write bulk status received: %d", | ||
211 | __FUNCTION__, status); | ||
212 | |||
213 | spin_lock_irqsave(&portdata->lock, flags); | ||
214 | --portdata->outstanding_urbs; | ||
215 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
216 | |||
217 | usb_serial_port_softint(port); | ||
218 | } | ||
219 | |||
200 | /* Write */ | 220 | /* Write */ |
201 | static int sierra_write(struct usb_serial_port *port, | 221 | static int sierra_write(struct usb_serial_port *port, |
202 | const unsigned char *buf, int count) | 222 | const unsigned char *buf, int count) |
203 | { | 223 | { |
204 | struct sierra_port_private *portdata; | 224 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); |
205 | int i; | 225 | struct usb_serial *serial = port->serial; |
206 | int left, todo; | 226 | unsigned long flags; |
207 | struct urb *this_urb = NULL; /* spurious */ | 227 | unsigned char *buffer; |
208 | int err; | 228 | struct urb *urb; |
229 | int status; | ||
209 | 230 | ||
210 | portdata = usb_get_serial_port_data(port); | 231 | portdata = usb_get_serial_port_data(port); |
211 | 232 | ||
212 | dbg("%s: write (%d chars)", __FUNCTION__, count); | 233 | dbg("%s: write (%d chars)", __FUNCTION__, count); |
213 | 234 | ||
214 | i = 0; | 235 | spin_lock_irqsave(&portdata->lock, flags); |
215 | left = count; | 236 | if (portdata->outstanding_urbs > N_OUT_URB) { |
216 | for (i=0; left > 0 && i < N_OUT_URB; i++) { | 237 | spin_unlock_irqrestore(&portdata->lock, flags); |
217 | todo = left; | 238 | dbg("%s - write limit hit\n", __FUNCTION__); |
218 | if (todo > OUT_BUFLEN) | 239 | return 0; |
219 | todo = OUT_BUFLEN; | 240 | } |
220 | 241 | portdata->outstanding_urbs++; | |
221 | this_urb = portdata->out_urbs[i]; | 242 | spin_unlock_irqrestore(&portdata->lock, flags); |
222 | if (this_urb->status == -EINPROGRESS) { | 243 | |
223 | if (time_before(jiffies, | 244 | buffer = kmalloc(count, GFP_ATOMIC); |
224 | portdata->tx_start_time[i] + 10 * HZ)) | 245 | if (!buffer) { |
225 | continue; | 246 | dev_err(&port->dev, "out of memory\n"); |
226 | usb_unlink_urb(this_urb); | 247 | count = -ENOMEM; |
227 | continue; | 248 | goto error_no_buffer; |
228 | } | 249 | } |
229 | if (this_urb->status != 0) | 250 | |
230 | dbg("usb_write %p failed (err=%d)", | 251 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
231 | this_urb, this_urb->status); | 252 | if (!urb) { |
232 | 253 | dev_err(&port->dev, "no more free urbs\n"); | |
233 | dbg("%s: endpoint %d buf %d", __FUNCTION__, | 254 | count = -ENOMEM; |
234 | usb_pipeendpoint(this_urb->pipe), i); | 255 | goto error_no_urb; |
235 | 256 | } | |
236 | /* send the data */ | 257 | |
237 | memcpy (this_urb->transfer_buffer, buf, todo); | 258 | memcpy(buffer, buf, count); |
238 | this_urb->transfer_buffer_length = todo; | 259 | |
239 | 260 | usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, buffer); | |
240 | this_urb->dev = port->serial->dev; | 261 | |
241 | err = usb_submit_urb(this_urb, GFP_ATOMIC); | 262 | usb_fill_bulk_urb(urb, serial->dev, |
242 | if (err) { | 263 | usb_sndbulkpipe(serial->dev, |
243 | dbg("usb_submit_urb %p (write bulk) failed " | 264 | port->bulk_out_endpointAddress), |
244 | "(%d, has %d)", this_urb, | 265 | buffer, count, sierra_outdat_callback, port); |
245 | err, this_urb->status); | 266 | |
246 | continue; | 267 | /* send it down the pipe */ |
247 | } | 268 | status = usb_submit_urb(urb, GFP_ATOMIC); |
248 | portdata->tx_start_time[i] = jiffies; | 269 | if (status) { |
249 | buf += todo; | 270 | dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " |
250 | left -= todo; | 271 | "with status = %d\n", __FUNCTION__, status); |
272 | count = status; | ||
273 | goto error; | ||
251 | } | 274 | } |
252 | 275 | ||
253 | count -= left; | 276 | /* we are done with this urb, so let the host driver |
254 | dbg("%s: wrote (did %d)", __FUNCTION__, count); | 277 | * really free it when it is finished with it */ |
278 | usb_free_urb(urb); | ||
279 | |||
280 | return count; | ||
281 | error: | ||
282 | usb_free_urb(urb); | ||
283 | error_no_urb: | ||
284 | kfree(buffer); | ||
285 | error_no_buffer: | ||
286 | spin_lock_irqsave(&portdata->lock, flags); | ||
287 | --portdata->outstanding_urbs; | ||
288 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
255 | return count; | 289 | return count; |
256 | } | 290 | } |
257 | 291 | ||
@@ -262,15 +296,16 @@ static void sierra_indat_callback(struct urb *urb) | |||
262 | struct usb_serial_port *port; | 296 | struct usb_serial_port *port; |
263 | struct tty_struct *tty; | 297 | struct tty_struct *tty; |
264 | unsigned char *data = urb->transfer_buffer; | 298 | unsigned char *data = urb->transfer_buffer; |
299 | int status = urb->status; | ||
265 | 300 | ||
266 | dbg("%s: %p", __FUNCTION__, urb); | 301 | dbg("%s: %p", __FUNCTION__, urb); |
267 | 302 | ||
268 | endpoint = usb_pipeendpoint(urb->pipe); | 303 | endpoint = usb_pipeendpoint(urb->pipe); |
269 | port = (struct usb_serial_port *) urb->context; | 304 | port = (struct usb_serial_port *) urb->context; |
270 | 305 | ||
271 | if (urb->status) { | 306 | if (status) { |
272 | dbg("%s: nonzero status: %d on endpoint %02x.", | 307 | dbg("%s: nonzero status: %d on endpoint %02x.", |
273 | __FUNCTION__, urb->status, endpoint); | 308 | __FUNCTION__, status, endpoint); |
274 | } else { | 309 | } else { |
275 | tty = port->tty; | 310 | tty = port->tty; |
276 | if (urb->actual_length) { | 311 | if (urb->actual_length) { |
@@ -282,30 +317,20 @@ static void sierra_indat_callback(struct urb *urb) | |||
282 | } | 317 | } |
283 | 318 | ||
284 | /* Resubmit urb so we continue receiving */ | 319 | /* Resubmit urb so we continue receiving */ |
285 | if (port->open_count && urb->status != -ESHUTDOWN) { | 320 | if (port->open_count && status != -ESHUTDOWN) { |
286 | err = usb_submit_urb(urb, GFP_ATOMIC); | 321 | err = usb_submit_urb(urb, GFP_ATOMIC); |
287 | if (err) | 322 | if (err) |
288 | printk(KERN_ERR "%s: resubmit read urb failed. " | 323 | dev_err(&port->dev, "resubmit read urb failed." |
289 | "(%d)", __FUNCTION__, err); | 324 | "(%d)", err); |
290 | } | 325 | } |
291 | } | 326 | } |
292 | return; | 327 | return; |
293 | } | 328 | } |
294 | 329 | ||
295 | static void sierra_outdat_callback(struct urb *urb) | ||
296 | { | ||
297 | struct usb_serial_port *port; | ||
298 | |||
299 | dbg("%s", __FUNCTION__); | ||
300 | |||
301 | port = (struct usb_serial_port *) urb->context; | ||
302 | |||
303 | usb_serial_port_softint(port); | ||
304 | } | ||
305 | |||
306 | static void sierra_instat_callback(struct urb *urb) | 330 | static void sierra_instat_callback(struct urb *urb) |
307 | { | 331 | { |
308 | int err; | 332 | int err; |
333 | int status = urb->status; | ||
309 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; | 334 | struct usb_serial_port *port = (struct usb_serial_port *) urb->context; |
310 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); | 335 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); |
311 | struct usb_serial *serial = port->serial; | 336 | struct usb_serial *serial = port->serial; |
@@ -313,7 +338,7 @@ static void sierra_instat_callback(struct urb *urb) | |||
313 | dbg("%s", __FUNCTION__); | 338 | dbg("%s", __FUNCTION__); |
314 | dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); | 339 | dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); |
315 | 340 | ||
316 | if (urb->status == 0) { | 341 | if (status == 0) { |
317 | struct usb_ctrlrequest *req_pkt = | 342 | struct usb_ctrlrequest *req_pkt = |
318 | (struct usb_ctrlrequest *)urb->transfer_buffer; | 343 | (struct usb_ctrlrequest *)urb->transfer_buffer; |
319 | 344 | ||
@@ -344,10 +369,10 @@ static void sierra_instat_callback(struct urb *urb) | |||
344 | req_pkt->bRequestType,req_pkt->bRequest); | 369 | req_pkt->bRequestType,req_pkt->bRequest); |
345 | } | 370 | } |
346 | } else | 371 | } else |
347 | dbg("%s: error %d", __FUNCTION__, urb->status); | 372 | dbg("%s: error %d", __FUNCTION__, status); |
348 | 373 | ||
349 | /* Resubmit urb so we continue receiving IRQ data */ | 374 | /* Resubmit urb so we continue receiving IRQ data */ |
350 | if (urb->status != -ESHUTDOWN) { | 375 | if (status != -ESHUTDOWN) { |
351 | urb->dev = serial->dev; | 376 | urb->dev = serial->dev; |
352 | err = usb_submit_urb(urb, GFP_ATOMIC); | 377 | err = usb_submit_urb(urb, GFP_ATOMIC); |
353 | if (err) | 378 | if (err) |
@@ -358,46 +383,42 @@ static void sierra_instat_callback(struct urb *urb) | |||
358 | 383 | ||
359 | static int sierra_write_room(struct usb_serial_port *port) | 384 | static int sierra_write_room(struct usb_serial_port *port) |
360 | { | 385 | { |
361 | struct sierra_port_private *portdata; | 386 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); |
362 | int i; | 387 | unsigned long flags; |
363 | int data_len = 0; | ||
364 | struct urb *this_urb; | ||
365 | 388 | ||
366 | portdata = usb_get_serial_port_data(port); | 389 | dbg("%s - port %d", __FUNCTION__, port->number); |
367 | 390 | ||
368 | for (i=0; i < N_OUT_URB; i++) { | 391 | /* try to give a good number back based on if we have any free urbs at |
369 | this_urb = portdata->out_urbs[i]; | 392 | * this point in time */ |
370 | if (this_urb && this_urb->status != -EINPROGRESS) | 393 | spin_lock_irqsave(&portdata->lock, flags); |
371 | data_len += OUT_BUFLEN; | 394 | if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) { |
395 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
396 | dbg("%s - write limit hit\n", __FUNCTION__); | ||
397 | return 0; | ||
372 | } | 398 | } |
399 | spin_unlock_irqrestore(&portdata->lock, flags); | ||
373 | 400 | ||
374 | dbg("%s: %d", __FUNCTION__, data_len); | 401 | return 2048; |
375 | return data_len; | ||
376 | } | 402 | } |
377 | 403 | ||
378 | static int sierra_chars_in_buffer(struct usb_serial_port *port) | 404 | static int sierra_chars_in_buffer(struct usb_serial_port *port) |
379 | { | 405 | { |
380 | struct sierra_port_private *portdata; | 406 | dbg("%s - port %d", __FUNCTION__, port->number); |
381 | int i; | 407 | |
382 | int data_len = 0; | 408 | /* |
383 | struct urb *this_urb; | 409 | * We can't really account for how much data we |
384 | 410 | * have sent out, but hasn't made it through to the | |
385 | portdata = usb_get_serial_port_data(port); | 411 | * device as we can't see the backend here, so just |
386 | 412 | * tell the tty layer that everything is flushed. | |
387 | for (i=0; i < N_OUT_URB; i++) { | 413 | */ |
388 | this_urb = portdata->out_urbs[i]; | 414 | return 0; |
389 | if (this_urb && this_urb->status == -EINPROGRESS) | ||
390 | data_len += this_urb->transfer_buffer_length; | ||
391 | } | ||
392 | dbg("%s: %d", __FUNCTION__, data_len); | ||
393 | return data_len; | ||
394 | } | 415 | } |
395 | 416 | ||
396 | static int sierra_open(struct usb_serial_port *port, struct file *filp) | 417 | static int sierra_open(struct usb_serial_port *port, struct file *filp) |
397 | { | 418 | { |
398 | struct sierra_port_private *portdata; | 419 | struct sierra_port_private *portdata; |
399 | struct usb_serial *serial = port->serial; | 420 | struct usb_serial *serial = port->serial; |
400 | int i, err; | 421 | int i; |
401 | struct urb *urb; | 422 | struct urb *urb; |
402 | int result; | 423 | int result; |
403 | __u16 set_mode_dzero = 0x0000; | 424 | __u16 set_mode_dzero = 0x0000; |
@@ -413,7 +434,7 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
413 | /* Reset low level data toggle and start reading from endpoints */ | 434 | /* Reset low level data toggle and start reading from endpoints */ |
414 | for (i = 0; i < N_IN_URB; i++) { | 435 | for (i = 0; i < N_IN_URB; i++) { |
415 | urb = portdata->in_urbs[i]; | 436 | urb = portdata->in_urbs[i]; |
416 | if (! urb) | 437 | if (!urb) |
417 | continue; | 438 | continue; |
418 | if (urb->dev != serial->dev) { | 439 | if (urb->dev != serial->dev) { |
419 | dbg("%s: dev %p != %p", __FUNCTION__, | 440 | dbg("%s: dev %p != %p", __FUNCTION__, |
@@ -427,24 +448,13 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
427 | */ | 448 | */ |
428 | usb_clear_halt(urb->dev, urb->pipe); | 449 | usb_clear_halt(urb->dev, urb->pipe); |
429 | 450 | ||
430 | err = usb_submit_urb(urb, GFP_KERNEL); | 451 | result = usb_submit_urb(urb, GFP_KERNEL); |
431 | if (err) { | 452 | if (result) { |
432 | dbg("%s: submit urb %d failed (%d) %d", | 453 | dev_err(&port->dev, "submit urb %d failed (%d) %d", |
433 | __FUNCTION__, i, err, | 454 | i, result, urb->transfer_buffer_length); |
434 | urb->transfer_buffer_length); | ||
435 | } | 455 | } |
436 | } | 456 | } |
437 | 457 | ||
438 | /* Reset low level data toggle on out endpoints */ | ||
439 | for (i = 0; i < N_OUT_URB; i++) { | ||
440 | urb = portdata->out_urbs[i]; | ||
441 | if (! urb) | ||
442 | continue; | ||
443 | urb->dev = serial->dev; | ||
444 | /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), | ||
445 | usb_pipeout(urb->pipe), 0); */ | ||
446 | } | ||
447 | |||
448 | port->tty->low_latency = 1; | 458 | port->tty->low_latency = 1; |
449 | 459 | ||
450 | /* set mode to D0 */ | 460 | /* set mode to D0 */ |
@@ -455,7 +465,14 @@ static int sierra_open(struct usb_serial_port *port, struct file *filp) | |||
455 | 465 | ||
456 | sierra_send_setup(port); | 466 | sierra_send_setup(port); |
457 | 467 | ||
458 | return (0); | 468 | /* start up the interrupt endpoint if we have one */ |
469 | if (port->interrupt_in_urb) { | ||
470 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | ||
471 | if (result) | ||
472 | dev_err(&port->dev, "submit irq_in urb failed %d", | ||
473 | result); | ||
474 | } | ||
475 | return 0; | ||
459 | } | 476 | } |
460 | 477 | ||
461 | static void sierra_close(struct usb_serial_port *port, struct file *filp) | 478 | static void sierra_close(struct usb_serial_port *port, struct file *filp) |
@@ -475,71 +492,21 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp) | |||
475 | 492 | ||
476 | /* Stop reading/writing urbs */ | 493 | /* Stop reading/writing urbs */ |
477 | for (i = 0; i < N_IN_URB; i++) | 494 | for (i = 0; i < N_IN_URB; i++) |
478 | usb_unlink_urb(portdata->in_urbs[i]); | 495 | usb_kill_urb(portdata->in_urbs[i]); |
479 | for (i = 0; i < N_OUT_URB; i++) | ||
480 | usb_unlink_urb(portdata->out_urbs[i]); | ||
481 | } | 496 | } |
482 | port->tty = NULL; | ||
483 | } | ||
484 | |||
485 | /* Helper functions used by sierra_setup_urbs */ | ||
486 | static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, | ||
487 | int dir, void *ctx, char *buf, int len, | ||
488 | usb_complete_t callback) | ||
489 | { | ||
490 | struct urb *urb; | ||
491 | |||
492 | if (endpoint == -1) | ||
493 | return NULL; /* endpoint not needed */ | ||
494 | |||
495 | urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ | ||
496 | if (urb == NULL) { | ||
497 | dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint); | ||
498 | return NULL; | ||
499 | } | ||
500 | |||
501 | /* Fill URB using supplied data. */ | ||
502 | usb_fill_bulk_urb(urb, serial->dev, | ||
503 | usb_sndbulkpipe(serial->dev, endpoint) | dir, | ||
504 | buf, len, callback, ctx); | ||
505 | |||
506 | return urb; | ||
507 | } | ||
508 | 497 | ||
509 | /* Setup urbs */ | 498 | usb_kill_urb(port->interrupt_in_urb); |
510 | static void sierra_setup_urbs(struct usb_serial *serial) | ||
511 | { | ||
512 | int i,j; | ||
513 | struct usb_serial_port *port; | ||
514 | struct sierra_port_private *portdata; | ||
515 | |||
516 | dbg("%s", __FUNCTION__); | ||
517 | 499 | ||
518 | for (i = 0; i < serial->num_ports; i++) { | 500 | port->tty = NULL; |
519 | port = serial->port[i]; | ||
520 | portdata = usb_get_serial_port_data(port); | ||
521 | |||
522 | /* Do indat endpoints first */ | ||
523 | for (j = 0; j < N_IN_URB; ++j) { | ||
524 | portdata->in_urbs[j] = sierra_setup_urb (serial, | ||
525 | port->bulk_in_endpointAddress, USB_DIR_IN, port, | ||
526 | portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback); | ||
527 | } | ||
528 | |||
529 | /* outdat endpoints */ | ||
530 | for (j = 0; j < N_OUT_URB; ++j) { | ||
531 | portdata->out_urbs[j] = sierra_setup_urb (serial, | ||
532 | port->bulk_out_endpointAddress, USB_DIR_OUT, port, | ||
533 | portdata->out_buffer[j], OUT_BUFLEN, sierra_outdat_callback); | ||
534 | } | ||
535 | } | ||
536 | } | 501 | } |
537 | 502 | ||
538 | static int sierra_startup(struct usb_serial *serial) | 503 | static int sierra_startup(struct usb_serial *serial) |
539 | { | 504 | { |
540 | int i, err; | ||
541 | struct usb_serial_port *port; | 505 | struct usb_serial_port *port; |
542 | struct sierra_port_private *portdata; | 506 | struct sierra_port_private *portdata; |
507 | struct urb *urb; | ||
508 | int i; | ||
509 | int j; | ||
543 | 510 | ||
544 | dbg("%s", __FUNCTION__); | 511 | dbg("%s", __FUNCTION__); |
545 | 512 | ||
@@ -550,22 +517,31 @@ static int sierra_startup(struct usb_serial *serial) | |||
550 | if (!portdata) { | 517 | if (!portdata) { |
551 | dbg("%s: kmalloc for sierra_port_private (%d) failed!.", | 518 | dbg("%s: kmalloc for sierra_port_private (%d) failed!.", |
552 | __FUNCTION__, i); | 519 | __FUNCTION__, i); |
553 | return (1); | 520 | return -ENOMEM; |
554 | } | 521 | } |
522 | spin_lock_init(&portdata->lock); | ||
555 | 523 | ||
556 | usb_set_serial_port_data(port, portdata); | 524 | usb_set_serial_port_data(port, portdata); |
557 | 525 | ||
558 | if (! port->interrupt_in_urb) | 526 | /* initialize the in urbs */ |
559 | continue; | 527 | for (j = 0; j < N_IN_URB; ++j) { |
560 | err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | 528 | urb = usb_alloc_urb(0, GFP_KERNEL); |
561 | if (err) | 529 | if (urb == NULL) { |
562 | dbg("%s: submit irq_in urb failed %d", | 530 | dbg("%s: alloc for in port failed.", |
563 | __FUNCTION__, err); | 531 | __FUNCTION__); |
532 | continue; | ||
533 | } | ||
534 | /* Fill URB using supplied data. */ | ||
535 | usb_fill_bulk_urb(urb, serial->dev, | ||
536 | usb_rcvbulkpipe(serial->dev, | ||
537 | port->bulk_in_endpointAddress), | ||
538 | portdata->in_buffer[j], IN_BUFLEN, | ||
539 | sierra_indat_callback, port); | ||
540 | portdata->in_urbs[j] = urb; | ||
541 | } | ||
564 | } | 542 | } |
565 | 543 | ||
566 | sierra_setup_urbs(serial); | 544 | return 0; |
567 | |||
568 | return (0); | ||
569 | } | 545 | } |
570 | 546 | ||
571 | static void sierra_shutdown(struct usb_serial *serial) | 547 | static void sierra_shutdown(struct usb_serial *serial) |
@@ -576,22 +552,6 @@ static void sierra_shutdown(struct usb_serial *serial) | |||
576 | 552 | ||
577 | dbg("%s", __FUNCTION__); | 553 | dbg("%s", __FUNCTION__); |
578 | 554 | ||
579 | /* Stop reading/writing urbs */ | ||
580 | for (i = 0; i < serial->num_ports; ++i) { | ||
581 | port = serial->port[i]; | ||
582 | if (!port) | ||
583 | continue; | ||
584 | portdata = usb_get_serial_port_data(port); | ||
585 | if (!portdata) | ||
586 | continue; | ||
587 | |||
588 | for (j = 0; j < N_IN_URB; j++) | ||
589 | usb_unlink_urb(portdata->in_urbs[j]); | ||
590 | for (j = 0; j < N_OUT_URB; j++) | ||
591 | usb_unlink_urb(portdata->out_urbs[j]); | ||
592 | } | ||
593 | |||
594 | /* Now free them */ | ||
595 | for (i = 0; i < serial->num_ports; ++i) { | 555 | for (i = 0; i < serial->num_ports; ++i) { |
596 | port = serial->port[i]; | 556 | port = serial->port[i]; |
597 | if (!port) | 557 | if (!port) |
@@ -601,25 +561,12 @@ static void sierra_shutdown(struct usb_serial *serial) | |||
601 | continue; | 561 | continue; |
602 | 562 | ||
603 | for (j = 0; j < N_IN_URB; j++) { | 563 | for (j = 0; j < N_IN_URB; j++) { |
604 | if (portdata->in_urbs[j]) { | 564 | usb_kill_urb(portdata->in_urbs[j]); |
605 | usb_free_urb(portdata->in_urbs[j]); | 565 | usb_free_urb(portdata->in_urbs[j]); |
606 | portdata->in_urbs[j] = NULL; | 566 | portdata->in_urbs[j] = NULL; |
607 | } | ||
608 | } | 567 | } |
609 | for (j = 0; j < N_OUT_URB; j++) { | 568 | kfree(portdata); |
610 | if (portdata->out_urbs[j]) { | 569 | usb_set_serial_port_data(port, NULL); |
611 | usb_free_urb(portdata->out_urbs[j]); | ||
612 | portdata->out_urbs[j] = NULL; | ||
613 | } | ||
614 | } | ||
615 | } | ||
616 | |||
617 | /* Now free per port private data */ | ||
618 | for (i = 0; i < serial->num_ports; i++) { | ||
619 | port = serial->port[i]; | ||
620 | if (!port) | ||
621 | continue; | ||
622 | kfree(usb_get_serial_port_data(port)); | ||
623 | } | 570 | } |
624 | } | 571 | } |
625 | 572 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 3d505fd0645b..f98626ae75fe 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
@@ -1112,22 +1112,24 @@ static void ti_interrupt_callback(struct urb *urb) | |||
1112 | int length = urb->actual_length; | 1112 | int length = urb->actual_length; |
1113 | int port_number; | 1113 | int port_number; |
1114 | int function; | 1114 | int function; |
1115 | int status; | 1115 | int status = urb->status; |
1116 | int retval; | ||
1116 | __u8 msr; | 1117 | __u8 msr; |
1117 | 1118 | ||
1118 | dbg("%s", __FUNCTION__); | 1119 | dbg("%s", __FUNCTION__); |
1119 | 1120 | ||
1120 | switch (urb->status) { | 1121 | switch (status) { |
1121 | case 0: | 1122 | case 0: |
1122 | break; | 1123 | break; |
1123 | case -ECONNRESET: | 1124 | case -ECONNRESET: |
1124 | case -ENOENT: | 1125 | case -ENOENT: |
1125 | case -ESHUTDOWN: | 1126 | case -ESHUTDOWN: |
1126 | dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status); | 1127 | dbg("%s - urb shutting down, %d", __FUNCTION__, status); |
1127 | tdev->td_urb_error = 1; | 1128 | tdev->td_urb_error = 1; |
1128 | return; | 1129 | return; |
1129 | default: | 1130 | default: |
1130 | dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status); | 1131 | dev_err(dev, "%s - nonzero urb status, %d\n", |
1132 | __FUNCTION__, status); | ||
1131 | tdev->td_urb_error = 1; | 1133 | tdev->td_urb_error = 1; |
1132 | goto exit; | 1134 | goto exit; |
1133 | } | 1135 | } |
@@ -1175,9 +1177,10 @@ static void ti_interrupt_callback(struct urb *urb) | |||
1175 | } | 1177 | } |
1176 | 1178 | ||
1177 | exit: | 1179 | exit: |
1178 | status = usb_submit_urb(urb, GFP_ATOMIC); | 1180 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
1179 | if (status) | 1181 | if (retval) |
1180 | dev_err(dev, "%s - resubmit interrupt urb failed, %d\n", __FUNCTION__, status); | 1182 | dev_err(dev, "%s - resubmit interrupt urb failed, %d\n", |
1183 | __FUNCTION__, retval); | ||
1181 | } | 1184 | } |
1182 | 1185 | ||
1183 | 1186 | ||
@@ -1186,30 +1189,32 @@ static void ti_bulk_in_callback(struct urb *urb) | |||
1186 | struct ti_port *tport = (struct ti_port *)urb->context; | 1189 | struct ti_port *tport = (struct ti_port *)urb->context; |
1187 | struct usb_serial_port *port = tport->tp_port; | 1190 | struct usb_serial_port *port = tport->tp_port; |
1188 | struct device *dev = &urb->dev->dev; | 1191 | struct device *dev = &urb->dev->dev; |
1189 | int status = 0; | 1192 | int status = urb->status; |
1193 | int retval = 0; | ||
1190 | 1194 | ||
1191 | dbg("%s", __FUNCTION__); | 1195 | dbg("%s", __FUNCTION__); |
1192 | 1196 | ||
1193 | switch (urb->status) { | 1197 | switch (status) { |
1194 | case 0: | 1198 | case 0: |
1195 | break; | 1199 | break; |
1196 | case -ECONNRESET: | 1200 | case -ECONNRESET: |
1197 | case -ENOENT: | 1201 | case -ENOENT: |
1198 | case -ESHUTDOWN: | 1202 | case -ESHUTDOWN: |
1199 | dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status); | 1203 | dbg("%s - urb shutting down, %d", __FUNCTION__, status); |
1200 | tport->tp_tdev->td_urb_error = 1; | 1204 | tport->tp_tdev->td_urb_error = 1; |
1201 | wake_up_interruptible(&tport->tp_write_wait); | 1205 | wake_up_interruptible(&tport->tp_write_wait); |
1202 | return; | 1206 | return; |
1203 | default: | 1207 | default: |
1204 | dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status ); | 1208 | dev_err(dev, "%s - nonzero urb status, %d\n", |
1209 | __FUNCTION__, status ); | ||
1205 | tport->tp_tdev->td_urb_error = 1; | 1210 | tport->tp_tdev->td_urb_error = 1; |
1206 | wake_up_interruptible(&tport->tp_write_wait); | 1211 | wake_up_interruptible(&tport->tp_write_wait); |
1207 | } | 1212 | } |
1208 | 1213 | ||
1209 | if (urb->status == -EPIPE) | 1214 | if (status == -EPIPE) |
1210 | goto exit; | 1215 | goto exit; |
1211 | 1216 | ||
1212 | if (urb->status) { | 1217 | if (status) { |
1213 | dev_err(dev, "%s - stopping read!\n", __FUNCTION__); | 1218 | dev_err(dev, "%s - stopping read!\n", __FUNCTION__); |
1214 | return; | 1219 | return; |
1215 | } | 1220 | } |
@@ -1234,13 +1239,14 @@ exit: | |||
1234 | spin_lock(&tport->tp_lock); | 1239 | spin_lock(&tport->tp_lock); |
1235 | if (tport->tp_read_urb_state == TI_READ_URB_RUNNING) { | 1240 | if (tport->tp_read_urb_state == TI_READ_URB_RUNNING) { |
1236 | urb->dev = port->serial->dev; | 1241 | urb->dev = port->serial->dev; |
1237 | status = usb_submit_urb(urb, GFP_ATOMIC); | 1242 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
1238 | } else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING) { | 1243 | } else if (tport->tp_read_urb_state == TI_READ_URB_STOPPING) { |
1239 | tport->tp_read_urb_state = TI_READ_URB_STOPPED; | 1244 | tport->tp_read_urb_state = TI_READ_URB_STOPPED; |
1240 | } | 1245 | } |
1241 | spin_unlock(&tport->tp_lock); | 1246 | spin_unlock(&tport->tp_lock); |
1242 | if (status) | 1247 | if (retval) |
1243 | dev_err(dev, "%s - resubmit read urb failed, %d\n", __FUNCTION__, status); | 1248 | dev_err(dev, "%s - resubmit read urb failed, %d\n", |
1249 | __FUNCTION__, retval); | ||
1244 | } | 1250 | } |
1245 | 1251 | ||
1246 | 1252 | ||
@@ -1249,23 +1255,25 @@ static void ti_bulk_out_callback(struct urb *urb) | |||
1249 | struct ti_port *tport = (struct ti_port *)urb->context; | 1255 | struct ti_port *tport = (struct ti_port *)urb->context; |
1250 | struct usb_serial_port *port = tport->tp_port; | 1256 | struct usb_serial_port *port = tport->tp_port; |
1251 | struct device *dev = &urb->dev->dev; | 1257 | struct device *dev = &urb->dev->dev; |
1258 | int status = urb->status; | ||
1252 | 1259 | ||
1253 | dbg("%s - port %d", __FUNCTION__, port->number); | 1260 | dbg("%s - port %d", __FUNCTION__, port->number); |
1254 | 1261 | ||
1255 | tport->tp_write_urb_in_use = 0; | 1262 | tport->tp_write_urb_in_use = 0; |
1256 | 1263 | ||
1257 | switch (urb->status) { | 1264 | switch (status) { |
1258 | case 0: | 1265 | case 0: |
1259 | break; | 1266 | break; |
1260 | case -ECONNRESET: | 1267 | case -ECONNRESET: |
1261 | case -ENOENT: | 1268 | case -ENOENT: |
1262 | case -ESHUTDOWN: | 1269 | case -ESHUTDOWN: |
1263 | dbg("%s - urb shutting down, %d", __FUNCTION__, urb->status); | 1270 | dbg("%s - urb shutting down, %d", __FUNCTION__, status); |
1264 | tport->tp_tdev->td_urb_error = 1; | 1271 | tport->tp_tdev->td_urb_error = 1; |
1265 | wake_up_interruptible(&tport->tp_write_wait); | 1272 | wake_up_interruptible(&tport->tp_write_wait); |
1266 | return; | 1273 | return; |
1267 | default: | 1274 | default: |
1268 | dev_err(dev, "%s - nonzero urb status, %d\n", __FUNCTION__, urb->status); | 1275 | dev_err(dev, "%s - nonzero urb status, %d\n", |
1276 | __FUNCTION__, status); | ||
1269 | tport->tp_tdev->td_urb_error = 1; | 1277 | tport->tp_tdev->td_urb_error = 1; |
1270 | wake_up_interruptible(&tport->tp_write_wait); | 1278 | wake_up_interruptible(&tport->tp_write_wait); |
1271 | } | 1279 | } |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 87f378806db6..a3665659d13b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -46,6 +46,8 @@ static struct usb_driver usb_serial_driver = { | |||
46 | .name = "usbserial", | 46 | .name = "usbserial", |
47 | .probe = usb_serial_probe, | 47 | .probe = usb_serial_probe, |
48 | .disconnect = usb_serial_disconnect, | 48 | .disconnect = usb_serial_disconnect, |
49 | .suspend = usb_serial_suspend, | ||
50 | .resume = usb_serial_resume, | ||
49 | .no_dynamic_id = 1, | 51 | .no_dynamic_id = 1, |
50 | }; | 52 | }; |
51 | 53 | ||
@@ -120,11 +122,9 @@ static void return_serial(struct usb_serial *serial) | |||
120 | if (serial == NULL) | 122 | if (serial == NULL) |
121 | return; | 123 | return; |
122 | 124 | ||
123 | spin_lock(&table_lock); | ||
124 | for (i = 0; i < serial->num_ports; ++i) { | 125 | for (i = 0; i < serial->num_ports; ++i) { |
125 | serial_table[serial->minor + i] = NULL; | 126 | serial_table[serial->minor + i] = NULL; |
126 | } | 127 | } |
127 | spin_unlock(&table_lock); | ||
128 | } | 128 | } |
129 | 129 | ||
130 | static void destroy_serial(struct kref *kref) | 130 | static void destroy_serial(struct kref *kref) |
@@ -172,7 +172,9 @@ static void destroy_serial(struct kref *kref) | |||
172 | 172 | ||
173 | void usb_serial_put(struct usb_serial *serial) | 173 | void usb_serial_put(struct usb_serial *serial) |
174 | { | 174 | { |
175 | spin_lock(&table_lock); | ||
175 | kref_put(&serial->kref, destroy_serial); | 176 | kref_put(&serial->kref, destroy_serial); |
177 | spin_unlock(&table_lock); | ||
176 | } | 178 | } |
177 | 179 | ||
178 | /***************************************************************************** | 180 | /***************************************************************************** |
@@ -1069,6 +1071,35 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
1069 | dev_info(dev, "device disconnected\n"); | 1071 | dev_info(dev, "device disconnected\n"); |
1070 | } | 1072 | } |
1071 | 1073 | ||
1074 | int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) | ||
1075 | { | ||
1076 | struct usb_serial *serial = usb_get_intfdata(intf); | ||
1077 | struct usb_serial_port *port; | ||
1078 | int i, r = 0; | ||
1079 | |||
1080 | if (serial) { | ||
1081 | for (i = 0; i < serial->num_ports; ++i) { | ||
1082 | port = serial->port[i]; | ||
1083 | if (port) | ||
1084 | kill_traffic(port); | ||
1085 | } | ||
1086 | } | ||
1087 | |||
1088 | if (serial->type->suspend) | ||
1089 | serial->type->suspend(serial, message); | ||
1090 | |||
1091 | return r; | ||
1092 | } | ||
1093 | EXPORT_SYMBOL(usb_serial_suspend); | ||
1094 | |||
1095 | int usb_serial_resume(struct usb_interface *intf) | ||
1096 | { | ||
1097 | struct usb_serial *serial = usb_get_intfdata(intf); | ||
1098 | |||
1099 | return serial->type->resume(serial); | ||
1100 | } | ||
1101 | EXPORT_SYMBOL(usb_serial_resume); | ||
1102 | |||
1072 | static const struct tty_operations serial_ops = { | 1103 | static const struct tty_operations serial_ops = { |
1073 | .open = serial_open, | 1104 | .open = serial_open, |
1074 | .close = serial_close, | 1105 | .close = serial_close, |
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index ffbe601cde2a..7d84a7647e81 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c | |||
@@ -5,9 +5,9 @@ | |||
5 | * Copyright (C) 1999 - 2004 | 5 | * Copyright (C) 1999 - 2004 |
6 | * Greg Kroah-Hartman (greg@kroah.com) | 6 | * Greg Kroah-Hartman (greg@kroah.com) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or |
9 | * it under the terms of the GNU General Public License as published by | 9 | * modify it under the terms of the GNU General Public License version |
10 | * the Free Software Foundation; either version 2 of the License. | 10 | * 2 as published by the Free Software Foundation. |
11 | * | 11 | * |
12 | * See Documentation/usb/usb-serial.txt for more information on using this driver | 12 | * See Documentation/usb/usb-serial.txt for more information on using this driver |
13 | * | 13 | * |
@@ -273,7 +273,8 @@ struct visor_private { | |||
273 | int bytes_in; | 273 | int bytes_in; |
274 | int bytes_out; | 274 | int bytes_out; |
275 | int outstanding_urbs; | 275 | int outstanding_urbs; |
276 | int throttled; | 276 | unsigned char throttled; |
277 | unsigned char actually_throttled; | ||
277 | }; | 278 | }; |
278 | 279 | ||
279 | /* number of outstanding urbs to prevent userspace DoS from happening */ | 280 | /* number of outstanding urbs to prevent userspace DoS from happening */ |
@@ -484,16 +485,17 @@ static void visor_write_bulk_callback (struct urb *urb) | |||
484 | { | 485 | { |
485 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 486 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
486 | struct visor_private *priv = usb_get_serial_port_data(port); | 487 | struct visor_private *priv = usb_get_serial_port_data(port); |
488 | int status = urb->status; | ||
487 | unsigned long flags; | 489 | unsigned long flags; |
488 | 490 | ||
489 | /* free up the transfer buffer, as usb_free_urb() does not do this */ | 491 | /* free up the transfer buffer, as usb_free_urb() does not do this */ |
490 | kfree (urb->transfer_buffer); | 492 | kfree (urb->transfer_buffer); |
491 | 493 | ||
492 | dbg("%s - port %d", __FUNCTION__, port->number); | 494 | dbg("%s - port %d", __FUNCTION__, port->number); |
493 | 495 | ||
494 | if (urb->status) | 496 | if (status) |
495 | dbg("%s - nonzero write bulk status received: %d", | 497 | dbg("%s - nonzero write bulk status received: %d", |
496 | __FUNCTION__, urb->status); | 498 | __FUNCTION__, status); |
497 | 499 | ||
498 | spin_lock_irqsave(&priv->lock, flags); | 500 | spin_lock_irqsave(&priv->lock, flags); |
499 | --priv->outstanding_urbs; | 501 | --priv->outstanding_urbs; |
@@ -508,15 +510,16 @@ static void visor_read_bulk_callback (struct urb *urb) | |||
508 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 510 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
509 | struct visor_private *priv = usb_get_serial_port_data(port); | 511 | struct visor_private *priv = usb_get_serial_port_data(port); |
510 | unsigned char *data = urb->transfer_buffer; | 512 | unsigned char *data = urb->transfer_buffer; |
513 | int status = urb->status; | ||
511 | struct tty_struct *tty; | 514 | struct tty_struct *tty; |
512 | unsigned long flags; | ||
513 | int throttled; | ||
514 | int result; | 515 | int result; |
516 | int available_room; | ||
515 | 517 | ||
516 | dbg("%s - port %d", __FUNCTION__, port->number); | 518 | dbg("%s - port %d", __FUNCTION__, port->number); |
517 | 519 | ||
518 | if (urb->status) { | 520 | if (status) { |
519 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 521 | dbg("%s - nonzero read bulk status received: %d", |
522 | __FUNCTION__, status); | ||
520 | return; | 523 | return; |
521 | } | 524 | } |
522 | 525 | ||
@@ -524,17 +527,20 @@ static void visor_read_bulk_callback (struct urb *urb) | |||
524 | 527 | ||
525 | tty = port->tty; | 528 | tty = port->tty; |
526 | if (tty && urb->actual_length) { | 529 | if (tty && urb->actual_length) { |
527 | tty_buffer_request_room(tty, urb->actual_length); | 530 | available_room = tty_buffer_request_room(tty, urb->actual_length); |
528 | tty_insert_flip_string(tty, data, urb->actual_length); | 531 | if (available_room) { |
529 | tty_flip_buffer_push(tty); | 532 | tty_insert_flip_string(tty, data, available_room); |
533 | tty_flip_buffer_push(tty); | ||
534 | } | ||
535 | spin_lock(&priv->lock); | ||
536 | priv->bytes_in += available_room; | ||
537 | |||
538 | } else { | ||
539 | spin_lock(&priv->lock); | ||
530 | } | 540 | } |
531 | spin_lock_irqsave(&priv->lock, flags); | ||
532 | priv->bytes_in += urb->actual_length; | ||
533 | throttled = priv->throttled; | ||
534 | spin_unlock_irqrestore(&priv->lock, flags); | ||
535 | 541 | ||
536 | /* Continue trying to always read if we should */ | 542 | /* Continue trying to always read if we should */ |
537 | if (!throttled) { | 543 | if (!priv->throttled) { |
538 | usb_fill_bulk_urb (port->read_urb, port->serial->dev, | 544 | usb_fill_bulk_urb (port->read_urb, port->serial->dev, |
539 | usb_rcvbulkpipe(port->serial->dev, | 545 | usb_rcvbulkpipe(port->serial->dev, |
540 | port->bulk_in_endpointAddress), | 546 | port->bulk_in_endpointAddress), |
@@ -544,16 +550,19 @@ static void visor_read_bulk_callback (struct urb *urb) | |||
544 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); | 550 | result = usb_submit_urb(port->read_urb, GFP_ATOMIC); |
545 | if (result) | 551 | if (result) |
546 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); | 552 | dev_err(&port->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); |
553 | } else { | ||
554 | priv->actually_throttled = 1; | ||
547 | } | 555 | } |
548 | return; | 556 | spin_unlock(&priv->lock); |
549 | } | 557 | } |
550 | 558 | ||
551 | static void visor_read_int_callback (struct urb *urb) | 559 | static void visor_read_int_callback (struct urb *urb) |
552 | { | 560 | { |
553 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 561 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
562 | int status = urb->status; | ||
554 | int result; | 563 | int result; |
555 | 564 | ||
556 | switch (urb->status) { | 565 | switch (status) { |
557 | case 0: | 566 | case 0: |
558 | /* success */ | 567 | /* success */ |
559 | break; | 568 | break; |
@@ -562,11 +571,11 @@ static void visor_read_int_callback (struct urb *urb) | |||
562 | case -ESHUTDOWN: | 571 | case -ESHUTDOWN: |
563 | /* this urb is terminated, clean up */ | 572 | /* this urb is terminated, clean up */ |
564 | dbg("%s - urb shutting down with status: %d", | 573 | dbg("%s - urb shutting down with status: %d", |
565 | __FUNCTION__, urb->status); | 574 | __FUNCTION__, status); |
566 | return; | 575 | return; |
567 | default: | 576 | default: |
568 | dbg("%s - nonzero urb status received: %d", | 577 | dbg("%s - nonzero urb status received: %d", |
569 | __FUNCTION__, urb->status); | 578 | __FUNCTION__, status); |
570 | goto exit; | 579 | goto exit; |
571 | } | 580 | } |
572 | 581 | ||
@@ -608,6 +617,7 @@ static void visor_unthrottle (struct usb_serial_port *port) | |||
608 | dbg("%s - port %d", __FUNCTION__, port->number); | 617 | dbg("%s - port %d", __FUNCTION__, port->number); |
609 | spin_lock_irqsave(&priv->lock, flags); | 618 | spin_lock_irqsave(&priv->lock, flags); |
610 | priv->throttled = 0; | 619 | priv->throttled = 0; |
620 | priv->actually_throttled = 0; | ||
611 | spin_unlock_irqrestore(&priv->lock, flags); | 621 | spin_unlock_irqrestore(&priv->lock, flags); |
612 | 622 | ||
613 | port->read_urb->dev = port->serial->dev; | 623 | port->read_urb->dev = port->serial->dev; |
@@ -938,14 +948,6 @@ static void visor_set_termios (struct usb_serial_port *port, struct ktermios *ol | |||
938 | } | 948 | } |
939 | 949 | ||
940 | cflag = port->tty->termios->c_cflag; | 950 | cflag = port->tty->termios->c_cflag; |
941 | /* check that they really want us to change something */ | ||
942 | if (old_termios) { | ||
943 | if ((cflag == old_termios->c_cflag) && | ||
944 | (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { | ||
945 | dbg("%s - nothing to change...", __FUNCTION__); | ||
946 | return; | ||
947 | } | ||
948 | } | ||
949 | 951 | ||
950 | /* get the byte size */ | 952 | /* get the byte size */ |
951 | switch (cflag & CSIZE) { | 953 | switch (cflag & CSIZE) { |
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 27c5f8f9a2d5..cc8b44c08712 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
@@ -74,6 +74,7 @@ | |||
74 | #include <linux/tty_flip.h> | 74 | #include <linux/tty_flip.h> |
75 | #include <linux/module.h> | 75 | #include <linux/module.h> |
76 | #include <linux/spinlock.h> | 76 | #include <linux/spinlock.h> |
77 | #include <linux/mutex.h> | ||
77 | #include <asm/uaccess.h> | 78 | #include <asm/uaccess.h> |
78 | #include <asm/termbits.h> | 79 | #include <asm/termbits.h> |
79 | #include <linux/usb.h> | 80 | #include <linux/usb.h> |
@@ -203,7 +204,7 @@ static struct usb_serial_driver whiteheat_device = { | |||
203 | 204 | ||
204 | 205 | ||
205 | struct whiteheat_command_private { | 206 | struct whiteheat_command_private { |
206 | spinlock_t lock; | 207 | struct mutex mutex; |
207 | __u8 port_running; | 208 | __u8 port_running; |
208 | __u8 command_finished; | 209 | __u8 command_finished; |
209 | wait_queue_head_t wait_command; /* for handling sleeping while waiting for a command to finish */ | 210 | wait_queue_head_t wait_command; /* for handling sleeping while waiting for a command to finish */ |
@@ -232,6 +233,7 @@ struct whiteheat_private { | |||
232 | struct usb_serial_port *port; | 233 | struct usb_serial_port *port; |
233 | struct list_head tx_urbs_free; | 234 | struct list_head tx_urbs_free; |
234 | struct list_head tx_urbs_submitted; | 235 | struct list_head tx_urbs_submitted; |
236 | struct mutex deathwarrant; | ||
235 | }; | 237 | }; |
236 | 238 | ||
237 | 239 | ||
@@ -425,6 +427,7 @@ static int whiteheat_attach (struct usb_serial *serial) | |||
425 | } | 427 | } |
426 | 428 | ||
427 | spin_lock_init(&info->lock); | 429 | spin_lock_init(&info->lock); |
430 | mutex_init(&info->deathwarrant); | ||
428 | info->flags = 0; | 431 | info->flags = 0; |
429 | info->mcr = 0; | 432 | info->mcr = 0; |
430 | INIT_WORK(&info->rx_work, rx_data_softint); | 433 | INIT_WORK(&info->rx_work, rx_data_softint); |
@@ -495,7 +498,7 @@ static int whiteheat_attach (struct usb_serial *serial) | |||
495 | goto no_command_private; | 498 | goto no_command_private; |
496 | } | 499 | } |
497 | 500 | ||
498 | spin_lock_init(&command_info->lock); | 501 | mutex_init(&command_info->mutex); |
499 | command_info->port_running = 0; | 502 | command_info->port_running = 0; |
500 | init_waitqueue_head(&command_info->wait_command); | 503 | init_waitqueue_head(&command_info->wait_command); |
501 | usb_set_serial_port_data(command_port, command_info); | 504 | usb_set_serial_port_data(command_port, command_info); |
@@ -654,7 +657,6 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) | |||
654 | struct urb *urb; | 657 | struct urb *urb; |
655 | struct list_head *tmp; | 658 | struct list_head *tmp; |
656 | struct list_head *tmp2; | 659 | struct list_head *tmp2; |
657 | unsigned long flags; | ||
658 | 660 | ||
659 | dbg("%s - port %d", __FUNCTION__, port->number); | 661 | dbg("%s - port %d", __FUNCTION__, port->number); |
660 | 662 | ||
@@ -683,24 +685,32 @@ static void whiteheat_close(struct usb_serial_port *port, struct file * filp) | |||
683 | 685 | ||
684 | firm_close(port); | 686 | firm_close(port); |
685 | 687 | ||
688 | printk(KERN_ERR"Before processing rx_urbs_submitted.\n"); | ||
686 | /* shutdown our bulk reads and writes */ | 689 | /* shutdown our bulk reads and writes */ |
687 | spin_lock_irqsave(&info->lock, flags); | 690 | mutex_lock(&info->deathwarrant); |
691 | spin_lock_irq(&info->lock); | ||
688 | list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { | 692 | list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { |
689 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | 693 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); |
690 | urb = wrap->urb; | 694 | urb = wrap->urb; |
695 | list_del(tmp); | ||
696 | spin_unlock_irq(&info->lock); | ||
691 | usb_kill_urb(urb); | 697 | usb_kill_urb(urb); |
692 | list_move(tmp, &info->rx_urbs_free); | 698 | spin_lock_irq(&info->lock); |
699 | list_add(tmp, &info->rx_urbs_free); | ||
693 | } | 700 | } |
694 | list_for_each_safe(tmp, tmp2, &info->rx_urb_q) | 701 | list_for_each_safe(tmp, tmp2, &info->rx_urb_q) |
695 | list_move(tmp, &info->rx_urbs_free); | 702 | list_move(tmp, &info->rx_urbs_free); |
696 | |||
697 | list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) { | 703 | list_for_each_safe(tmp, tmp2, &info->tx_urbs_submitted) { |
698 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | 704 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); |
699 | urb = wrap->urb; | 705 | urb = wrap->urb; |
706 | list_del(tmp); | ||
707 | spin_unlock_irq(&info->lock); | ||
700 | usb_kill_urb(urb); | 708 | usb_kill_urb(urb); |
701 | list_move(tmp, &info->tx_urbs_free); | 709 | spin_lock_irq(&info->lock); |
710 | list_add(tmp, &info->tx_urbs_free); | ||
702 | } | 711 | } |
703 | spin_unlock_irqrestore(&info->lock, flags); | 712 | spin_unlock_irq(&info->lock); |
713 | mutex_unlock(&info->deathwarrant); | ||
704 | 714 | ||
705 | stop_command_port(port->serial); | 715 | stop_command_port(port->serial); |
706 | 716 | ||
@@ -872,7 +882,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un | |||
872 | } | 882 | } |
873 | 883 | ||
874 | 884 | ||
875 | static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios *old_termios) | 885 | static void whiteheat_set_termios(struct usb_serial_port *port, struct ktermios *old_termios) |
876 | { | 886 | { |
877 | dbg("%s -port %d", __FUNCTION__, port->number); | 887 | dbg("%s -port %d", __FUNCTION__, port->number); |
878 | 888 | ||
@@ -881,15 +891,6 @@ static void whiteheat_set_termios (struct usb_serial_port *port, struct ktermios | |||
881 | goto exit; | 891 | goto exit; |
882 | } | 892 | } |
883 | 893 | ||
884 | /* check that they really want us to change something */ | ||
885 | if (old_termios) { | ||
886 | if ((port->tty->termios->c_cflag == old_termios->c_cflag) && | ||
887 | (port->tty->termios->c_iflag == old_termios->c_iflag)) { | ||
888 | dbg("%s - nothing to change...", __FUNCTION__); | ||
889 | goto exit; | ||
890 | } | ||
891 | } | ||
892 | |||
893 | firm_setup_port(port); | 894 | firm_setup_port(port); |
894 | 895 | ||
895 | exit: | 896 | exit: |
@@ -920,7 +921,7 @@ static int whiteheat_chars_in_buffer(struct usb_serial_port *port) | |||
920 | spin_unlock_irqrestore(&info->lock, flags); | 921 | spin_unlock_irqrestore(&info->lock, flags); |
921 | 922 | ||
922 | dbg ("%s - returns %d", __FUNCTION__, chars); | 923 | dbg ("%s - returns %d", __FUNCTION__, chars); |
923 | return (chars); | 924 | return chars; |
924 | } | 925 | } |
925 | 926 | ||
926 | 927 | ||
@@ -962,54 +963,57 @@ static void whiteheat_unthrottle (struct usb_serial_port *port) | |||
962 | /***************************************************************************** | 963 | /***************************************************************************** |
963 | * Connect Tech's White Heat callback routines | 964 | * Connect Tech's White Heat callback routines |
964 | *****************************************************************************/ | 965 | *****************************************************************************/ |
965 | static void command_port_write_callback (struct urb *urb) | 966 | static void command_port_write_callback(struct urb *urb) |
966 | { | 967 | { |
968 | int status = urb->status; | ||
969 | |||
967 | dbg("%s", __FUNCTION__); | 970 | dbg("%s", __FUNCTION__); |
968 | 971 | ||
969 | if (urb->status) { | 972 | if (status) { |
970 | dbg ("nonzero urb status: %d", urb->status); | 973 | dbg("nonzero urb status: %d", status); |
971 | return; | 974 | return; |
972 | } | 975 | } |
973 | } | 976 | } |
974 | 977 | ||
975 | 978 | ||
976 | static void command_port_read_callback (struct urb *urb) | 979 | static void command_port_read_callback(struct urb *urb) |
977 | { | 980 | { |
978 | struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context; | 981 | struct usb_serial_port *command_port = (struct usb_serial_port *)urb->context; |
979 | struct whiteheat_command_private *command_info; | 982 | struct whiteheat_command_private *command_info; |
983 | int status = urb->status; | ||
980 | unsigned char *data = urb->transfer_buffer; | 984 | unsigned char *data = urb->transfer_buffer; |
981 | int result; | 985 | int result; |
982 | unsigned long flags; | ||
983 | 986 | ||
984 | dbg("%s", __FUNCTION__); | 987 | dbg("%s", __FUNCTION__); |
985 | 988 | ||
986 | if (urb->status) { | ||
987 | dbg("%s - nonzero urb status: %d", __FUNCTION__, urb->status); | ||
988 | return; | ||
989 | } | ||
990 | |||
991 | usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data); | ||
992 | |||
993 | command_info = usb_get_serial_port_data(command_port); | 989 | command_info = usb_get_serial_port_data(command_port); |
994 | if (!command_info) { | 990 | if (!command_info) { |
995 | dbg ("%s - command_info is NULL, exiting.", __FUNCTION__); | 991 | dbg ("%s - command_info is NULL, exiting.", __FUNCTION__); |
996 | return; | 992 | return; |
997 | } | 993 | } |
998 | spin_lock_irqsave(&command_info->lock, flags); | 994 | if (status) { |
995 | dbg("%s - nonzero urb status: %d", __FUNCTION__, status); | ||
996 | if (status != -ENOENT) | ||
997 | command_info->command_finished = WHITEHEAT_CMD_FAILURE; | ||
998 | wake_up(&command_info->wait_command); | ||
999 | return; | ||
1000 | } | ||
1001 | |||
1002 | usb_serial_debug_data(debug, &command_port->dev, __FUNCTION__, urb->actual_length, data); | ||
999 | 1003 | ||
1000 | if (data[0] == WHITEHEAT_CMD_COMPLETE) { | 1004 | if (data[0] == WHITEHEAT_CMD_COMPLETE) { |
1001 | command_info->command_finished = WHITEHEAT_CMD_COMPLETE; | 1005 | command_info->command_finished = WHITEHEAT_CMD_COMPLETE; |
1002 | wake_up_interruptible(&command_info->wait_command); | 1006 | wake_up(&command_info->wait_command); |
1003 | } else if (data[0] == WHITEHEAT_CMD_FAILURE) { | 1007 | } else if (data[0] == WHITEHEAT_CMD_FAILURE) { |
1004 | command_info->command_finished = WHITEHEAT_CMD_FAILURE; | 1008 | command_info->command_finished = WHITEHEAT_CMD_FAILURE; |
1005 | wake_up_interruptible(&command_info->wait_command); | 1009 | wake_up(&command_info->wait_command); |
1006 | } else if (data[0] == WHITEHEAT_EVENT) { | 1010 | } else if (data[0] == WHITEHEAT_EVENT) { |
1007 | /* These are unsolicited reports from the firmware, hence no waiting command to wakeup */ | 1011 | /* These are unsolicited reports from the firmware, hence no waiting command to wakeup */ |
1008 | dbg("%s - event received", __FUNCTION__); | 1012 | dbg("%s - event received", __FUNCTION__); |
1009 | } else if (data[0] == WHITEHEAT_GET_DTR_RTS) { | 1013 | } else if (data[0] == WHITEHEAT_GET_DTR_RTS) { |
1010 | memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1); | 1014 | memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1); |
1011 | command_info->command_finished = WHITEHEAT_CMD_COMPLETE; | 1015 | command_info->command_finished = WHITEHEAT_CMD_COMPLETE; |
1012 | wake_up_interruptible(&command_info->wait_command); | 1016 | wake_up(&command_info->wait_command); |
1013 | } else { | 1017 | } else { |
1014 | dbg("%s - bad reply from firmware", __FUNCTION__); | 1018 | dbg("%s - bad reply from firmware", __FUNCTION__); |
1015 | } | 1019 | } |
@@ -1017,7 +1021,6 @@ static void command_port_read_callback (struct urb *urb) | |||
1017 | /* Continue trying to always read */ | 1021 | /* Continue trying to always read */ |
1018 | command_port->read_urb->dev = command_port->serial->dev; | 1022 | command_port->read_urb->dev = command_port->serial->dev; |
1019 | result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC); | 1023 | result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC); |
1020 | spin_unlock_irqrestore(&command_info->lock, flags); | ||
1021 | if (result) | 1024 | if (result) |
1022 | dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); | 1025 | dbg("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); |
1023 | } | 1026 | } |
@@ -1029,6 +1032,7 @@ static void whiteheat_read_callback(struct urb *urb) | |||
1029 | struct whiteheat_urb_wrap *wrap; | 1032 | struct whiteheat_urb_wrap *wrap; |
1030 | unsigned char *data = urb->transfer_buffer; | 1033 | unsigned char *data = urb->transfer_buffer; |
1031 | struct whiteheat_private *info = usb_get_serial_port_data(port); | 1034 | struct whiteheat_private *info = usb_get_serial_port_data(port); |
1035 | int status = urb->status; | ||
1032 | 1036 | ||
1033 | dbg("%s - port %d", __FUNCTION__, port->number); | 1037 | dbg("%s - port %d", __FUNCTION__, port->number); |
1034 | 1038 | ||
@@ -1042,8 +1046,9 @@ static void whiteheat_read_callback(struct urb *urb) | |||
1042 | list_del(&wrap->list); | 1046 | list_del(&wrap->list); |
1043 | spin_unlock(&info->lock); | 1047 | spin_unlock(&info->lock); |
1044 | 1048 | ||
1045 | if (urb->status) { | 1049 | if (status) { |
1046 | dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status); | 1050 | dbg("%s - nonzero read bulk status received: %d", |
1051 | __FUNCTION__, status); | ||
1047 | spin_lock(&info->lock); | 1052 | spin_lock(&info->lock); |
1048 | list_add(&wrap->list, &info->rx_urbs_free); | 1053 | list_add(&wrap->list, &info->rx_urbs_free); |
1049 | spin_unlock(&info->lock); | 1054 | spin_unlock(&info->lock); |
@@ -1070,6 +1075,7 @@ static void whiteheat_write_callback(struct urb *urb) | |||
1070 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; | 1075 | struct usb_serial_port *port = (struct usb_serial_port *)urb->context; |
1071 | struct whiteheat_private *info = usb_get_serial_port_data(port); | 1076 | struct whiteheat_private *info = usb_get_serial_port_data(port); |
1072 | struct whiteheat_urb_wrap *wrap; | 1077 | struct whiteheat_urb_wrap *wrap; |
1078 | int status = urb->status; | ||
1073 | 1079 | ||
1074 | dbg("%s - port %d", __FUNCTION__, port->number); | 1080 | dbg("%s - port %d", __FUNCTION__, port->number); |
1075 | 1081 | ||
@@ -1083,8 +1089,9 @@ static void whiteheat_write_callback(struct urb *urb) | |||
1083 | list_move(&wrap->list, &info->tx_urbs_free); | 1089 | list_move(&wrap->list, &info->tx_urbs_free); |
1084 | spin_unlock(&info->lock); | 1090 | spin_unlock(&info->lock); |
1085 | 1091 | ||
1086 | if (urb->status) { | 1092 | if (status) { |
1087 | dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); | 1093 | dbg("%s - nonzero write bulk status received: %d", |
1094 | __FUNCTION__, status); | ||
1088 | return; | 1095 | return; |
1089 | } | 1096 | } |
1090 | 1097 | ||
@@ -1095,20 +1102,20 @@ static void whiteheat_write_callback(struct urb *urb) | |||
1095 | /***************************************************************************** | 1102 | /***************************************************************************** |
1096 | * Connect Tech's White Heat firmware interface | 1103 | * Connect Tech's White Heat firmware interface |
1097 | *****************************************************************************/ | 1104 | *****************************************************************************/ |
1098 | static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize) | 1105 | static int firm_send_command(struct usb_serial_port *port, __u8 command, __u8 *data, __u8 datasize) |
1099 | { | 1106 | { |
1100 | struct usb_serial_port *command_port; | 1107 | struct usb_serial_port *command_port; |
1101 | struct whiteheat_command_private *command_info; | 1108 | struct whiteheat_command_private *command_info; |
1102 | struct whiteheat_private *info; | 1109 | struct whiteheat_private *info; |
1103 | __u8 *transfer_buffer; | 1110 | __u8 *transfer_buffer; |
1104 | int retval = 0; | 1111 | int retval = 0; |
1105 | unsigned long flags; | 1112 | int t; |
1106 | 1113 | ||
1107 | dbg("%s - command %d", __FUNCTION__, command); | 1114 | dbg("%s - command %d", __FUNCTION__, command); |
1108 | 1115 | ||
1109 | command_port = port->serial->port[COMMAND_PORT]; | 1116 | command_port = port->serial->port[COMMAND_PORT]; |
1110 | command_info = usb_get_serial_port_data(command_port); | 1117 | command_info = usb_get_serial_port_data(command_port); |
1111 | spin_lock_irqsave(&command_info->lock, flags); | 1118 | mutex_lock(&command_info->mutex); |
1112 | command_info->command_finished = false; | 1119 | command_info->command_finished = false; |
1113 | 1120 | ||
1114 | transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer; | 1121 | transfer_buffer = (__u8 *)command_port->write_urb->transfer_buffer; |
@@ -1116,18 +1123,17 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 * | |||
1116 | memcpy (&transfer_buffer[1], data, datasize); | 1123 | memcpy (&transfer_buffer[1], data, datasize); |
1117 | command_port->write_urb->transfer_buffer_length = datasize + 1; | 1124 | command_port->write_urb->transfer_buffer_length = datasize + 1; |
1118 | command_port->write_urb->dev = port->serial->dev; | 1125 | command_port->write_urb->dev = port->serial->dev; |
1119 | retval = usb_submit_urb (command_port->write_urb, GFP_KERNEL); | 1126 | retval = usb_submit_urb (command_port->write_urb, GFP_NOIO); |
1120 | if (retval) { | 1127 | if (retval) { |
1121 | dbg("%s - submit urb failed", __FUNCTION__); | 1128 | dbg("%s - submit urb failed", __FUNCTION__); |
1122 | goto exit; | 1129 | goto exit; |
1123 | } | 1130 | } |
1124 | spin_unlock_irqrestore(&command_info->lock, flags); | ||
1125 | 1131 | ||
1126 | /* wait for the command to complete */ | 1132 | /* wait for the command to complete */ |
1127 | wait_event_interruptible_timeout(command_info->wait_command, | 1133 | t = wait_event_timeout(command_info->wait_command, |
1128 | (bool)command_info->command_finished, COMMAND_TIMEOUT); | 1134 | (bool)command_info->command_finished, COMMAND_TIMEOUT); |
1129 | 1135 | if (!t) | |
1130 | spin_lock_irqsave(&command_info->lock, flags); | 1136 | usb_kill_urb(command_port->write_urb); |
1131 | 1137 | ||
1132 | if (command_info->command_finished == false) { | 1138 | if (command_info->command_finished == false) { |
1133 | dbg("%s - command timed out.", __FUNCTION__); | 1139 | dbg("%s - command timed out.", __FUNCTION__); |
@@ -1152,7 +1158,7 @@ static int firm_send_command (struct usb_serial_port *port, __u8 command, __u8 * | |||
1152 | } | 1158 | } |
1153 | 1159 | ||
1154 | exit: | 1160 | exit: |
1155 | spin_unlock_irqrestore(&command_info->lock, flags); | 1161 | mutex_unlock(&command_info->mutex); |
1156 | return retval; | 1162 | return retval; |
1157 | } | 1163 | } |
1158 | 1164 | ||
@@ -1305,12 +1311,11 @@ static int start_command_port(struct usb_serial *serial) | |||
1305 | { | 1311 | { |
1306 | struct usb_serial_port *command_port; | 1312 | struct usb_serial_port *command_port; |
1307 | struct whiteheat_command_private *command_info; | 1313 | struct whiteheat_command_private *command_info; |
1308 | unsigned long flags; | ||
1309 | int retval = 0; | 1314 | int retval = 0; |
1310 | 1315 | ||
1311 | command_port = serial->port[COMMAND_PORT]; | 1316 | command_port = serial->port[COMMAND_PORT]; |
1312 | command_info = usb_get_serial_port_data(command_port); | 1317 | command_info = usb_get_serial_port_data(command_port); |
1313 | spin_lock_irqsave(&command_info->lock, flags); | 1318 | mutex_lock(&command_info->mutex); |
1314 | if (!command_info->port_running) { | 1319 | if (!command_info->port_running) { |
1315 | /* Work around HCD bugs */ | 1320 | /* Work around HCD bugs */ |
1316 | usb_clear_halt(serial->dev, command_port->read_urb->pipe); | 1321 | usb_clear_halt(serial->dev, command_port->read_urb->pipe); |
@@ -1325,7 +1330,7 @@ static int start_command_port(struct usb_serial *serial) | |||
1325 | command_info->port_running++; | 1330 | command_info->port_running++; |
1326 | 1331 | ||
1327 | exit: | 1332 | exit: |
1328 | spin_unlock_irqrestore(&command_info->lock, flags); | 1333 | mutex_unlock(&command_info->mutex); |
1329 | return retval; | 1334 | return retval; |
1330 | } | 1335 | } |
1331 | 1336 | ||
@@ -1334,15 +1339,14 @@ static void stop_command_port(struct usb_serial *serial) | |||
1334 | { | 1339 | { |
1335 | struct usb_serial_port *command_port; | 1340 | struct usb_serial_port *command_port; |
1336 | struct whiteheat_command_private *command_info; | 1341 | struct whiteheat_command_private *command_info; |
1337 | unsigned long flags; | ||
1338 | 1342 | ||
1339 | command_port = serial->port[COMMAND_PORT]; | 1343 | command_port = serial->port[COMMAND_PORT]; |
1340 | command_info = usb_get_serial_port_data(command_port); | 1344 | command_info = usb_get_serial_port_data(command_port); |
1341 | spin_lock_irqsave(&command_info->lock, flags); | 1345 | mutex_lock(&command_info->mutex); |
1342 | command_info->port_running--; | 1346 | command_info->port_running--; |
1343 | if (!command_info->port_running) | 1347 | if (!command_info->port_running) |
1344 | usb_kill_urb(command_port->read_urb); | 1348 | usb_kill_urb(command_port->read_urb); |
1345 | spin_unlock_irqrestore(&command_info->lock, flags); | 1349 | mutex_unlock(&command_info->mutex); |
1346 | } | 1350 | } |
1347 | 1351 | ||
1348 | 1352 | ||
@@ -1363,17 +1367,23 @@ static int start_port_read(struct usb_serial_port *port) | |||
1363 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | 1367 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); |
1364 | urb = wrap->urb; | 1368 | urb = wrap->urb; |
1365 | urb->dev = port->serial->dev; | 1369 | urb->dev = port->serial->dev; |
1370 | spin_unlock_irqrestore(&info->lock, flags); | ||
1366 | retval = usb_submit_urb(urb, GFP_KERNEL); | 1371 | retval = usb_submit_urb(urb, GFP_KERNEL); |
1367 | if (retval) { | 1372 | if (retval) { |
1373 | spin_lock_irqsave(&info->lock, flags); | ||
1368 | list_add(tmp, &info->rx_urbs_free); | 1374 | list_add(tmp, &info->rx_urbs_free); |
1369 | list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { | 1375 | list_for_each_safe(tmp, tmp2, &info->rx_urbs_submitted) { |
1370 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); | 1376 | wrap = list_entry(tmp, struct whiteheat_urb_wrap, list); |
1371 | urb = wrap->urb; | 1377 | urb = wrap->urb; |
1378 | list_del(tmp); | ||
1379 | spin_unlock_irqrestore(&info->lock, flags); | ||
1372 | usb_kill_urb(urb); | 1380 | usb_kill_urb(urb); |
1373 | list_move(tmp, &info->rx_urbs_free); | 1381 | spin_lock_irqsave(&info->lock, flags); |
1382 | list_add(tmp, &info->rx_urbs_free); | ||
1374 | } | 1383 | } |
1375 | break; | 1384 | break; |
1376 | } | 1385 | } |
1386 | spin_lock_irqsave(&info->lock, flags); | ||
1377 | list_add(tmp, &info->rx_urbs_submitted); | 1387 | list_add(tmp, &info->rx_urbs_submitted); |
1378 | } | 1388 | } |
1379 | 1389 | ||
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index e227f64d5641..47e56079925d 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c | |||
@@ -285,10 +285,15 @@ static int device_reset(struct scsi_cmnd *srb) | |||
285 | 285 | ||
286 | US_DEBUGP("%s called\n", __FUNCTION__); | 286 | US_DEBUGP("%s called\n", __FUNCTION__); |
287 | 287 | ||
288 | /* lock the device pointers and do the reset */ | 288 | result = usb_autopm_get_interface(us->pusb_intf); |
289 | mutex_lock(&(us->dev_mutex)); | 289 | if (result == 0) { |
290 | result = us->transport_reset(us); | 290 | |
291 | mutex_unlock(&us->dev_mutex); | 291 | /* lock the device pointers and do the reset */ |
292 | mutex_lock(&(us->dev_mutex)); | ||
293 | result = us->transport_reset(us); | ||
294 | mutex_unlock(&us->dev_mutex); | ||
295 | usb_autopm_put_interface(us->pusb_intf); | ||
296 | } | ||
292 | 297 | ||
293 | return result < 0 ? FAILED : SUCCESS; | 298 | return result < 0 ? FAILED : SUCCESS; |
294 | } | 299 | } |
@@ -321,10 +326,14 @@ void usb_stor_report_device_reset(struct us_data *us) | |||
321 | 326 | ||
322 | /* Report a driver-initiated bus reset to the SCSI layer. | 327 | /* Report a driver-initiated bus reset to the SCSI layer. |
323 | * Calling this for a SCSI-initiated reset is unnecessary but harmless. | 328 | * Calling this for a SCSI-initiated reset is unnecessary but harmless. |
324 | * The caller must own the SCSI host lock. */ | 329 | * The caller must not own the SCSI host lock. */ |
325 | void usb_stor_report_bus_reset(struct us_data *us) | 330 | void usb_stor_report_bus_reset(struct us_data *us) |
326 | { | 331 | { |
327 | scsi_report_bus_reset(us_to_host(us), 0); | 332 | struct Scsi_Host *host = us_to_host(us); |
333 | |||
334 | scsi_lock(host); | ||
335 | scsi_report_bus_reset(host, 0); | ||
336 | scsi_unlock(host); | ||
328 | } | 337 | } |
329 | 338 | ||
330 | /*********************************************************************** | 339 | /*********************************************************************** |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 54979c239c63..b6bf31a97b60 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -50,10 +50,10 @@ | |||
50 | /* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr> | 50 | /* patch submitted by Vivian Bregier <Vivian.Bregier@imag.fr> |
51 | */ | 51 | */ |
52 | UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, | 52 | UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, |
53 | "ATMEL", | 53 | "ATMEL", |
54 | "SND1 Storage", | 54 | "SND1 Storage", |
55 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 55 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
56 | US_FL_IGNORE_RESIDUE), | 56 | US_FL_IGNORE_RESIDUE), |
57 | 57 | ||
58 | /* modified by Tobias Lorenz <tobias.lorenz@gmx.net> */ | 58 | /* modified by Tobias Lorenz <tobias.lorenz@gmx.net> */ |
59 | UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0200, | 59 | UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0200, |
@@ -69,18 +69,18 @@ UNUSUAL_DEV( 0x03ee, 0x6906, 0x0003, 0x0003, | |||
69 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 69 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
70 | US_FL_IGNORE_RESIDUE ), | 70 | US_FL_IGNORE_RESIDUE ), |
71 | 71 | ||
72 | UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, | 72 | UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, |
73 | "HP", | 73 | "HP", |
74 | "CD-Writer+", | 74 | "CD-Writer+", |
75 | US_SC_8070, US_PR_CB, NULL, 0), | 75 | US_SC_8070, US_PR_CB, NULL, 0), |
76 | 76 | ||
77 | #ifdef CONFIG_USB_STORAGE_USBAT | 77 | #ifdef CONFIG_USB_STORAGE_USBAT |
78 | UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, | 78 | UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, |
79 | "HP", | 79 | "HP", |
80 | "CD-Writer+ 8200e", | 80 | "CD-Writer+ 8200e", |
81 | US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), | 81 | US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), |
82 | 82 | ||
83 | UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, | 83 | UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, |
84 | "HP", | 84 | "HP", |
85 | "CD-Writer+ CD-4e", | 85 | "CD-Writer+ CD-4e", |
86 | US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), | 86 | US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), |
@@ -115,10 +115,10 @@ UNUSUAL_DEV( 0x0411, 0x001c, 0x0113, 0x0113, | |||
115 | 115 | ||
116 | /* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */ | 116 | /* Submitted by Ernestas Vaiciukevicius <ernisv@gmail.com> */ |
117 | UNUSUAL_DEV( 0x0419, 0x0100, 0x0100, 0x0100, | 117 | UNUSUAL_DEV( 0x0419, 0x0100, 0x0100, 0x0100, |
118 | "Samsung Info. Systems America, Inc.", | 118 | "Samsung Info. Systems America, Inc.", |
119 | "MP3 Player", | 119 | "MP3 Player", |
120 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 120 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
121 | US_FL_IGNORE_RESIDUE ), | 121 | US_FL_IGNORE_RESIDUE ), |
122 | 122 | ||
123 | /* Reported by Orgad Shaneh <orgads@gmail.com> */ | 123 | /* Reported by Orgad Shaneh <orgads@gmail.com> */ |
124 | UNUSUAL_DEV( 0x0419, 0xaace, 0x0100, 0x0100, | 124 | UNUSUAL_DEV( 0x0419, 0xaace, 0x0100, 0x0100, |
@@ -256,10 +256,10 @@ UNUSUAL_DEV( 0x0457, 0x0150, 0x0100, 0x0100, | |||
256 | * the revision to my model only | 256 | * the revision to my model only |
257 | */ | 257 | */ |
258 | UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, | 258 | UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, |
259 | "USB 2.0", | 259 | "USB 2.0", |
260 | "Flash Disk", | 260 | "Flash Disk", |
261 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 261 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
262 | US_FL_NOT_LOCKABLE ), | 262 | US_FL_NOT_LOCKABLE ), |
263 | 263 | ||
264 | #ifdef CONFIG_USB_STORAGE_KARMA | 264 | #ifdef CONFIG_USB_STORAGE_KARMA |
265 | UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, | 265 | UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, |
@@ -408,19 +408,19 @@ UNUSUAL_DEV( 0x04da, 0x2373, 0x0000, 0x9999, | |||
408 | /* Most of the following entries were developed with the help of | 408 | /* Most of the following entries were developed with the help of |
409 | * Shuttle/SCM directly. | 409 | * Shuttle/SCM directly. |
410 | */ | 410 | */ |
411 | UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200, | 411 | UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200, |
412 | "Matshita", | 412 | "Matshita", |
413 | "LS-120", | 413 | "LS-120", |
414 | US_SC_8020, US_PR_CB, NULL, 0), | 414 | US_SC_8020, US_PR_CB, NULL, 0), |
415 | 415 | ||
416 | UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, | 416 | UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, |
417 | "Shuttle", | 417 | "Shuttle", |
418 | "eUSCSI Bridge", | 418 | "eUSCSI Bridge", |
419 | US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, | 419 | US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, |
420 | US_FL_SCM_MULT_TARG ), | 420 | US_FL_SCM_MULT_TARG ), |
421 | 421 | ||
422 | #ifdef CONFIG_USB_STORAGE_SDDR09 | 422 | #ifdef CONFIG_USB_STORAGE_SDDR09 |
423 | UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, | 423 | UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, |
424 | "Sandisk", | 424 | "Sandisk", |
425 | "ImageMate SDDR09", | 425 | "ImageMate SDDR09", |
426 | US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, | 426 | US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, |
@@ -431,52 +431,52 @@ UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, | |||
431 | "SCM Microsystems", | 431 | "SCM Microsystems", |
432 | "eUSB SmartMedia / CompactFlash Adapter", | 432 | "eUSB SmartMedia / CompactFlash Adapter", |
433 | US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, | 433 | US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, |
434 | 0), | 434 | 0), |
435 | #endif | 435 | #endif |
436 | 436 | ||
437 | /* Reported by Markus Demleitner <msdemlei@cl.uni-heidelberg.de> */ | 437 | /* Reported by Markus Demleitner <msdemlei@cl.uni-heidelberg.de> */ |
438 | UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0100, | 438 | UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0100, |
439 | "SCM Microsystems Inc.", | 439 | "SCM Microsystems Inc.", |
440 | "eUSB MMC Adapter", | 440 | "eUSB MMC Adapter", |
441 | US_SC_SCSI, US_PR_CB, NULL, | 441 | US_SC_SCSI, US_PR_CB, NULL, |
442 | US_FL_SINGLE_LUN), | 442 | US_FL_SINGLE_LUN), |
443 | 443 | ||
444 | /* Reported by Daniel Nouri <dpunktnpunkt@web.de> */ | 444 | /* Reported by Daniel Nouri <dpunktnpunkt@web.de> */ |
445 | UNUSUAL_DEV( 0x04e6, 0x0006, 0x0205, 0x0205, | 445 | UNUSUAL_DEV( 0x04e6, 0x0006, 0x0205, 0x0205, |
446 | "Shuttle", | 446 | "Shuttle", |
447 | "eUSB MMC Adapter", | 447 | "eUSB MMC Adapter", |
448 | US_SC_SCSI, US_PR_DEVICE, NULL, | 448 | US_SC_SCSI, US_PR_DEVICE, NULL, |
449 | US_FL_SINGLE_LUN), | 449 | US_FL_SINGLE_LUN), |
450 | 450 | ||
451 | UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200, | 451 | UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200, |
452 | "Sony", | 452 | "Sony", |
453 | "Hifd", | 453 | "Hifd", |
454 | US_SC_SCSI, US_PR_CB, NULL, | 454 | US_SC_SCSI, US_PR_CB, NULL, |
455 | US_FL_SINGLE_LUN), | 455 | US_FL_SINGLE_LUN), |
456 | 456 | ||
457 | UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200, | 457 | UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200, |
458 | "Shuttle", | 458 | "Shuttle", |
459 | "eUSB ATA/ATAPI Adapter", | 459 | "eUSB ATA/ATAPI Adapter", |
460 | US_SC_8020, US_PR_CB, NULL, 0), | 460 | US_SC_8020, US_PR_CB, NULL, 0), |
461 | 461 | ||
462 | UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200, | 462 | UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200, |
463 | "Shuttle", | 463 | "Shuttle", |
464 | "eUSB CompactFlash Adapter", | 464 | "eUSB CompactFlash Adapter", |
465 | US_SC_8020, US_PR_CB, NULL, 0), | 465 | US_SC_8020, US_PR_CB, NULL, 0), |
466 | 466 | ||
467 | UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100, | 467 | UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100, |
468 | "Shuttle", | 468 | "Shuttle", |
469 | "eUSCSI Bridge", | 469 | "eUSCSI Bridge", |
470 | US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, | 470 | US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, |
471 | US_FL_SCM_MULT_TARG ), | 471 | US_FL_SCM_MULT_TARG ), |
472 | 472 | ||
473 | UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100, | 473 | UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100, |
474 | "Shuttle", | 474 | "Shuttle", |
475 | "eUSCSI Bridge", | 475 | "eUSCSI Bridge", |
476 | US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, | 476 | US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, |
477 | US_FL_SCM_MULT_TARG ), | 477 | US_FL_SCM_MULT_TARG ), |
478 | 478 | ||
479 | UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, | 479 | UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, |
480 | "Shuttle", | 480 | "Shuttle", |
481 | "CD-RW Device", | 481 | "CD-RW Device", |
482 | US_SC_8020, US_PR_CB, NULL, 0), | 482 | US_SC_8020, US_PR_CB, NULL, 0), |
@@ -556,9 +556,9 @@ UNUSUAL_DEV( 0x052b, 0x1911, 0x0100, 0x0100, | |||
556 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 556 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
557 | US_FL_IGNORE_RESIDUE ), | 557 | US_FL_IGNORE_RESIDUE ), |
558 | 558 | ||
559 | UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, | 559 | UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450, |
560 | "Sony", | 560 | "Sony", |
561 | "DSC-S30/S70/S75/505V/F505/F707/F717/P8", | 561 | "DSC-S30/S70/S75/505V/F505/F707/F717/P8", |
562 | US_SC_SCSI, US_PR_DEVICE, NULL, | 562 | US_SC_SCSI, US_PR_DEVICE, NULL, |
563 | US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ), | 563 | US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE | US_FL_NO_WP_DETECT ), |
564 | 564 | ||
@@ -572,7 +572,7 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0610, | |||
572 | 572 | ||
573 | 573 | ||
574 | /* Reported by wim@geeks.nl */ | 574 | /* Reported by wim@geeks.nl */ |
575 | UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, | 575 | UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, |
576 | "Sony", | 576 | "Sony", |
577 | "Memorystick NW-MS7", | 577 | "Memorystick NW-MS7", |
578 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 578 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
@@ -593,21 +593,21 @@ UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x2000, | |||
593 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 593 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
594 | US_FL_SINGLE_LUN ), | 594 | US_FL_SINGLE_LUN ), |
595 | 595 | ||
596 | UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100, | 596 | UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100, |
597 | "Sony", | 597 | "Sony", |
598 | "Memorystick MSAC-US1", | 598 | "Memorystick MSAC-US1", |
599 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 599 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
600 | US_FL_SINGLE_LUN ), | 600 | US_FL_SINGLE_LUN ), |
601 | 601 | ||
602 | /* Submitted by Klaus Mueller <k.mueller@intershop.de> */ | 602 | /* Submitted by Klaus Mueller <k.mueller@intershop.de> */ |
603 | UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310, | 603 | UNUSUAL_DEV( 0x054c, 0x002e, 0x0106, 0x0310, |
604 | "Sony", | 604 | "Sony", |
605 | "Handycam", | 605 | "Handycam", |
606 | US_SC_SCSI, US_PR_DEVICE, NULL, | 606 | US_SC_SCSI, US_PR_DEVICE, NULL, |
607 | US_FL_SINGLE_LUN ), | 607 | US_FL_SINGLE_LUN ), |
608 | 608 | ||
609 | /* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */ | 609 | /* Submitted by Rajesh Kumble Nayak <nayak@obs-nice.fr> */ |
610 | UNUSUAL_DEV( 0x054c, 0x002e, 0x0500, 0x0500, | 610 | UNUSUAL_DEV( 0x054c, 0x002e, 0x0500, 0x0500, |
611 | "Sony", | 611 | "Sony", |
612 | "Handycam HC-85", | 612 | "Handycam HC-85", |
613 | US_SC_UFI, US_PR_DEVICE, NULL, | 613 | US_SC_UFI, US_PR_DEVICE, NULL, |
@@ -648,26 +648,26 @@ UNUSUAL_DEV( 0x054c, 0x016a, 0x0000, 0x9999, | |||
648 | 648 | ||
649 | /* Submitted by Frank Engel <frankie@cse.unsw.edu.au> */ | 649 | /* Submitted by Frank Engel <frankie@cse.unsw.edu.au> */ |
650 | UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999, | 650 | UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999, |
651 | "Sony", | 651 | "Sony", |
652 | "PEG Mass Storage", | 652 | "PEG Mass Storage", |
653 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 653 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
654 | US_FL_FIX_INQUIRY ), | 654 | US_FL_FIX_INQUIRY ), |
655 | 655 | ||
656 | /* floppy reports multiple luns */ | 656 | /* floppy reports multiple luns */ |
657 | UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210, | 657 | UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210, |
658 | "SAMSUNG", | 658 | "SAMSUNG", |
659 | "SFD-321U [FW 0C]", | 659 | "SFD-321U [FW 0C]", |
660 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 660 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
661 | US_FL_SINGLE_LUN ), | 661 | US_FL_SINGLE_LUN ), |
662 | 662 | ||
663 | 663 | ||
664 | UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, | 664 | UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, |
665 | "Y-E Data", | 665 | "Y-E Data", |
666 | "Flashbuster-U", | 666 | "Flashbuster-U", |
667 | US_SC_DEVICE, US_PR_CB, NULL, | 667 | US_SC_DEVICE, US_PR_CB, NULL, |
668 | US_FL_SINGLE_LUN), | 668 | US_FL_SINGLE_LUN), |
669 | 669 | ||
670 | UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999, | 670 | UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999, |
671 | "Y-E Data", | 671 | "Y-E Data", |
672 | "Flashbuster-U", | 672 | "Flashbuster-U", |
673 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 673 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
@@ -677,7 +677,7 @@ UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999, | |||
677 | * This entry is needed only because the device reports | 677 | * This entry is needed only because the device reports |
678 | * bInterfaceClass = 0xff (vendor-specific) | 678 | * bInterfaceClass = 0xff (vendor-specific) |
679 | */ | 679 | */ |
680 | UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, | 680 | UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, |
681 | "Y-E Data", | 681 | "Y-E Data", |
682 | "Silicon Media R/W", | 682 | "Silicon Media R/W", |
683 | US_SC_DEVICE, US_PR_DEVICE, NULL, 0), | 683 | US_SC_DEVICE, US_PR_DEVICE, NULL, 0), |
@@ -825,13 +825,13 @@ UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999, | |||
825 | US_SC_SCSI, US_PR_BULK, NULL, | 825 | US_SC_SCSI, US_PR_BULK, NULL, |
826 | US_FL_FIX_INQUIRY ), | 826 | US_FL_FIX_INQUIRY ), |
827 | 827 | ||
828 | UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, | 828 | UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, |
829 | "TEAC", | 829 | "TEAC", |
830 | "Floppy Drive", | 830 | "Floppy Drive", |
831 | US_SC_UFI, US_PR_CB, NULL, 0 ), | 831 | US_SC_UFI, US_PR_CB, NULL, 0 ), |
832 | 832 | ||
833 | #ifdef CONFIG_USB_STORAGE_SDDR09 | 833 | #ifdef CONFIG_USB_STORAGE_SDDR09 |
834 | UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, | 834 | UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, |
835 | "Olympus", | 835 | "Olympus", |
836 | "Camedia MAUSB-2", | 836 | "Camedia MAUSB-2", |
837 | US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, | 837 | US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, |
@@ -867,14 +867,14 @@ UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001, | |||
867 | 867 | ||
868 | /* Reported by Miguel A. Fosas <amn3s1a@ono.com> */ | 868 | /* Reported by Miguel A. Fosas <amn3s1a@ono.com> */ |
869 | UNUSUAL_DEV( 0x0686, 0x4017, 0x0001, 0x0001, | 869 | UNUSUAL_DEV( 0x0686, 0x4017, 0x0001, 0x0001, |
870 | "Minolta", | 870 | "Minolta", |
871 | "DIMAGE E223", | 871 | "DIMAGE E223", |
872 | US_SC_SCSI, US_PR_DEVICE, NULL, 0 ), | 872 | US_SC_SCSI, US_PR_DEVICE, NULL, 0 ), |
873 | 873 | ||
874 | UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100, | 874 | UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100, |
875 | "Hagiwara", | 875 | "Hagiwara", |
876 | "Flashgate", | 876 | "Flashgate", |
877 | US_SC_SCSI, US_PR_BULK, NULL, 0 ), | 877 | US_SC_SCSI, US_PR_BULK, NULL, 0 ), |
878 | 878 | ||
879 | /* Reported by David Hamilton <niftimusmaximus@lycos.com> */ | 879 | /* Reported by David Hamilton <niftimusmaximus@lycos.com> */ |
880 | UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001, | 880 | UNUSUAL_DEV( 0x069b, 0x3004, 0x0001, 0x0001, |
@@ -918,7 +918,7 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, | |||
918 | US_FL_SINGLE_LUN ), | 918 | US_FL_SINGLE_LUN ), |
919 | 919 | ||
920 | #ifdef CONFIG_USB_STORAGE_SDDR09 | 920 | #ifdef CONFIG_USB_STORAGE_SDDR09 |
921 | UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, | 921 | UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, |
922 | "Sandisk", | 922 | "Sandisk", |
923 | "ImageMate SDDR-09", | 923 | "ImageMate SDDR-09", |
924 | US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, | 924 | US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, |
@@ -939,17 +939,17 @@ UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0000, 0x9999, | |||
939 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 939 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
940 | US_FL_FIX_CAPACITY), | 940 | US_FL_FIX_CAPACITY), |
941 | 941 | ||
942 | UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133, | 942 | UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0133, |
943 | "Microtech", | 943 | "Microtech", |
944 | "USB-SCSI-DB25", | 944 | "USB-SCSI-DB25", |
945 | US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, | 945 | US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init, |
946 | US_FL_SCM_MULT_TARG ), | 946 | US_FL_SCM_MULT_TARG ), |
947 | 947 | ||
948 | UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100, | 948 | UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100, |
949 | "Microtech", | 949 | "Microtech", |
950 | "USB-SCSI-HD50", | 950 | "USB-SCSI-HD50", |
951 | US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, | 951 | US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, |
952 | US_FL_SCM_MULT_TARG ), | 952 | US_FL_SCM_MULT_TARG ), |
953 | 953 | ||
954 | #ifdef CONFIG_USB_STORAGE_DPCM | 954 | #ifdef CONFIG_USB_STORAGE_DPCM |
955 | UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, | 955 | UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, |
@@ -1053,10 +1053,10 @@ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, | |||
1053 | * as "DualSlot CompactFlash(TM) & MStick Drive USB" | 1053 | * as "DualSlot CompactFlash(TM) & MStick Drive USB" |
1054 | */ | 1054 | */ |
1055 | UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff, | 1055 | UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff, |
1056 | "DataFab Systems Inc.", | 1056 | "DataFab Systems Inc.", |
1057 | "USB CF+MS", | 1057 | "USB CF+MS", |
1058 | US_SC_SCSI, US_PR_DATAFAB, NULL, | 1058 | US_SC_SCSI, US_PR_DATAFAB, NULL, |
1059 | 0 ), | 1059 | 0 ), |
1060 | 1060 | ||
1061 | #endif | 1061 | #endif |
1062 | 1062 | ||
@@ -1119,10 +1119,10 @@ UNUSUAL_DEV( 0x08bd, 0x1100, 0x0000, 0x0000, | |||
1119 | * US_FL_IGNORE_RESIDUE Needed | 1119 | * US_FL_IGNORE_RESIDUE Needed |
1120 | */ | 1120 | */ |
1121 | UNUSUAL_DEV( 0x08ca, 0x3103, 0x0100, 0x0100, | 1121 | UNUSUAL_DEV( 0x08ca, 0x3103, 0x0100, 0x0100, |
1122 | "AIPTEK", | 1122 | "AIPTEK", |
1123 | "Aiptek USB Keychain MP3 Player", | 1123 | "Aiptek USB Keychain MP3 Player", |
1124 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1124 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1125 | US_FL_IGNORE_RESIDUE), | 1125 | US_FL_IGNORE_RESIDUE), |
1126 | 1126 | ||
1127 | /* Entry needed for flags. Moreover, all devices with this ID use | 1127 | /* Entry needed for flags. Moreover, all devices with this ID use |
1128 | * bulk-only transport, but _some_ falsely report Control/Bulk instead. | 1128 | * bulk-only transport, but _some_ falsely report Control/Bulk instead. |
@@ -1166,26 +1166,26 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, | |||
1166 | * Submitted by James Courtier-Dutton <James@superbug.demon.co.uk> | 1166 | * Submitted by James Courtier-Dutton <James@superbug.demon.co.uk> |
1167 | */ | 1167 | */ |
1168 | UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000, | 1168 | UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000, |
1169 | "Pentax", | 1169 | "Pentax", |
1170 | "Optio 2/3/400", | 1170 | "Optio 2/3/400", |
1171 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1171 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1172 | US_FL_FIX_INQUIRY ), | 1172 | US_FL_FIX_INQUIRY ), |
1173 | 1173 | ||
1174 | 1174 | ||
1175 | /* Submitted by Per Winkvist <per.winkvist@uk.com> */ | 1175 | /* Submitted by Per Winkvist <per.winkvist@uk.com> */ |
1176 | UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff, | 1176 | UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff, |
1177 | "Pentax", | 1177 | "Pentax", |
1178 | "Optio S/S4", | 1178 | "Optio S/S4", |
1179 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1179 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1180 | US_FL_FIX_INQUIRY ), | 1180 | US_FL_FIX_INQUIRY ), |
1181 | 1181 | ||
1182 | /* These are virtual windows driver CDs, which the zd1211rw driver | 1182 | /* These are virtual windows driver CDs, which the zd1211rw driver |
1183 | * automatically converts into WLAN devices. */ | 1183 | * automatically converts into WLAN devices. */ |
1184 | UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, | 1184 | UNUSUAL_DEV( 0x0ace, 0x2011, 0x0101, 0x0101, |
1185 | "ZyXEL", | 1185 | "ZyXEL", |
1186 | "G-220F USB-WLAN Install", | 1186 | "G-220F USB-WLAN Install", |
1187 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 1187 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
1188 | US_FL_IGNORE_DEVICE ), | 1188 | US_FL_IGNORE_DEVICE ), |
1189 | 1189 | ||
1190 | UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, | 1190 | UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, |
1191 | "SiteCom", | 1191 | "SiteCom", |
@@ -1211,17 +1211,17 @@ UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, | |||
1211 | 1211 | ||
1212 | #ifdef CONFIG_USB_STORAGE_DATAFAB | 1212 | #ifdef CONFIG_USB_STORAGE_DATAFAB |
1213 | UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, | 1213 | UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, |
1214 | "Acomdata", | 1214 | "Acomdata", |
1215 | "CF", | 1215 | "CF", |
1216 | US_SC_SCSI, US_PR_DATAFAB, NULL, | 1216 | US_SC_SCSI, US_PR_DATAFAB, NULL, |
1217 | US_FL_SINGLE_LUN ), | 1217 | US_FL_SINGLE_LUN ), |
1218 | #endif | 1218 | #endif |
1219 | #ifdef CONFIG_USB_STORAGE_SDDR55 | 1219 | #ifdef CONFIG_USB_STORAGE_SDDR55 |
1220 | UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, | 1220 | UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, |
1221 | "Acomdata", | 1221 | "Acomdata", |
1222 | "SM", | 1222 | "SM", |
1223 | US_SC_SCSI, US_PR_SDDR55, NULL, | 1223 | US_SC_SCSI, US_PR_SDDR55, NULL, |
1224 | US_FL_SINGLE_LUN ), | 1224 | US_FL_SINGLE_LUN ), |
1225 | #endif | 1225 | #endif |
1226 | 1226 | ||
1227 | /* Submitted by: Nick Sillik <n.sillik@temple.edu> | 1227 | /* Submitted by: Nick Sillik <n.sillik@temple.edu> |
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 8e898e3d861e..bef8bcd9bd98 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -191,16 +191,13 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) | |||
191 | { | 191 | { |
192 | struct us_data *us = usb_get_intfdata(iface); | 192 | struct us_data *us = usb_get_intfdata(iface); |
193 | 193 | ||
194 | US_DEBUGP("%s\n", __FUNCTION__); | ||
195 | |||
194 | /* Wait until no command is running */ | 196 | /* Wait until no command is running */ |
195 | mutex_lock(&us->dev_mutex); | 197 | mutex_lock(&us->dev_mutex); |
196 | 198 | ||
197 | US_DEBUGP("%s\n", __FUNCTION__); | ||
198 | if (us->suspend_resume_hook) | 199 | if (us->suspend_resume_hook) |
199 | (us->suspend_resume_hook)(us, US_SUSPEND); | 200 | (us->suspend_resume_hook)(us, US_SUSPEND); |
200 | iface->dev.power.power_state.event = message.event; | ||
201 | |||
202 | /* When runtime PM is working, we'll set a flag to indicate | ||
203 | * whether we should autoresume when a SCSI request arrives. */ | ||
204 | 201 | ||
205 | mutex_unlock(&us->dev_mutex); | 202 | mutex_unlock(&us->dev_mutex); |
206 | return 0; | 203 | return 0; |
@@ -210,14 +207,25 @@ static int storage_resume(struct usb_interface *iface) | |||
210 | { | 207 | { |
211 | struct us_data *us = usb_get_intfdata(iface); | 208 | struct us_data *us = usb_get_intfdata(iface); |
212 | 209 | ||
213 | mutex_lock(&us->dev_mutex); | ||
214 | |||
215 | US_DEBUGP("%s\n", __FUNCTION__); | 210 | US_DEBUGP("%s\n", __FUNCTION__); |
211 | |||
216 | if (us->suspend_resume_hook) | 212 | if (us->suspend_resume_hook) |
217 | (us->suspend_resume_hook)(us, US_RESUME); | 213 | (us->suspend_resume_hook)(us, US_RESUME); |
218 | iface->dev.power.power_state.event = PM_EVENT_ON; | ||
219 | 214 | ||
220 | mutex_unlock(&us->dev_mutex); | 215 | return 0; |
216 | } | ||
217 | |||
218 | static int storage_reset_resume(struct usb_interface *iface) | ||
219 | { | ||
220 | struct us_data *us = usb_get_intfdata(iface); | ||
221 | |||
222 | US_DEBUGP("%s\n", __FUNCTION__); | ||
223 | |||
224 | /* Report the reset to the SCSI core */ | ||
225 | usb_stor_report_bus_reset(us); | ||
226 | |||
227 | /* FIXME: Notify the subdrivers that they need to reinitialize | ||
228 | * the device */ | ||
221 | return 0; | 229 | return 0; |
222 | } | 230 | } |
223 | 231 | ||
@@ -228,7 +236,7 @@ static int storage_resume(struct usb_interface *iface) | |||
228 | * a USB port reset, whether from this driver or a different one. | 236 | * a USB port reset, whether from this driver or a different one. |
229 | */ | 237 | */ |
230 | 238 | ||
231 | static void storage_pre_reset(struct usb_interface *iface) | 239 | static int storage_pre_reset(struct usb_interface *iface) |
232 | { | 240 | { |
233 | struct us_data *us = usb_get_intfdata(iface); | 241 | struct us_data *us = usb_get_intfdata(iface); |
234 | 242 | ||
@@ -236,22 +244,23 @@ static void storage_pre_reset(struct usb_interface *iface) | |||
236 | 244 | ||
237 | /* Make sure no command runs during the reset */ | 245 | /* Make sure no command runs during the reset */ |
238 | mutex_lock(&us->dev_mutex); | 246 | mutex_lock(&us->dev_mutex); |
247 | return 0; | ||
239 | } | 248 | } |
240 | 249 | ||
241 | static void storage_post_reset(struct usb_interface *iface) | 250 | static int storage_post_reset(struct usb_interface *iface) |
242 | { | 251 | { |
243 | struct us_data *us = usb_get_intfdata(iface); | 252 | struct us_data *us = usb_get_intfdata(iface); |
244 | 253 | ||
245 | US_DEBUGP("%s\n", __FUNCTION__); | 254 | US_DEBUGP("%s\n", __FUNCTION__); |
246 | 255 | ||
247 | /* Report the reset to the SCSI core */ | 256 | /* Report the reset to the SCSI core */ |
248 | scsi_lock(us_to_host(us)); | ||
249 | usb_stor_report_bus_reset(us); | 257 | usb_stor_report_bus_reset(us); |
250 | scsi_unlock(us_to_host(us)); | ||
251 | 258 | ||
252 | /* FIXME: Notify the subdrivers that they need to reinitialize | 259 | /* FIXME: Notify the subdrivers that they need to reinitialize |
253 | * the device */ | 260 | * the device */ |
261 | |||
254 | mutex_unlock(&us->dev_mutex); | 262 | mutex_unlock(&us->dev_mutex); |
263 | return 0; | ||
255 | } | 264 | } |
256 | 265 | ||
257 | /* | 266 | /* |
@@ -300,6 +309,7 @@ static int usb_stor_control_thread(void * __us) | |||
300 | { | 309 | { |
301 | struct us_data *us = (struct us_data *)__us; | 310 | struct us_data *us = (struct us_data *)__us; |
302 | struct Scsi_Host *host = us_to_host(us); | 311 | struct Scsi_Host *host = us_to_host(us); |
312 | int autopm_rc; | ||
303 | 313 | ||
304 | current->flags |= PF_NOFREEZE; | 314 | current->flags |= PF_NOFREEZE; |
305 | 315 | ||
@@ -310,6 +320,9 @@ static int usb_stor_control_thread(void * __us) | |||
310 | 320 | ||
311 | US_DEBUGP("*** thread awakened.\n"); | 321 | US_DEBUGP("*** thread awakened.\n"); |
312 | 322 | ||
323 | /* Autoresume the device */ | ||
324 | autopm_rc = usb_autopm_get_interface(us->pusb_intf); | ||
325 | |||
313 | /* lock the device pointers */ | 326 | /* lock the device pointers */ |
314 | mutex_lock(&(us->dev_mutex)); | 327 | mutex_lock(&(us->dev_mutex)); |
315 | 328 | ||
@@ -368,6 +381,12 @@ static int usb_stor_control_thread(void * __us) | |||
368 | us->srb->result = SAM_STAT_GOOD; | 381 | us->srb->result = SAM_STAT_GOOD; |
369 | } | 382 | } |
370 | 383 | ||
384 | /* Did the autoresume fail? */ | ||
385 | else if (autopm_rc < 0) { | ||
386 | US_DEBUGP("Could not wake device\n"); | ||
387 | us->srb->result = DID_ERROR << 16; | ||
388 | } | ||
389 | |||
371 | /* we've got a command, let's do it! */ | 390 | /* we've got a command, let's do it! */ |
372 | else { | 391 | else { |
373 | US_DEBUG(usb_stor_show_command(us->srb)); | 392 | US_DEBUG(usb_stor_show_command(us->srb)); |
@@ -410,25 +429,21 @@ SkipForAbort: | |||
410 | 429 | ||
411 | /* unlock the device pointers */ | 430 | /* unlock the device pointers */ |
412 | mutex_unlock(&us->dev_mutex); | 431 | mutex_unlock(&us->dev_mutex); |
413 | } /* for (;;) */ | ||
414 | 432 | ||
415 | scsi_host_put(host); | 433 | /* Start an autosuspend */ |
434 | if (autopm_rc == 0) | ||
435 | usb_autopm_put_interface(us->pusb_intf); | ||
436 | } /* for (;;) */ | ||
416 | 437 | ||
417 | /* notify the exit routine that we're actually exiting now | 438 | /* Wait until we are told to stop */ |
418 | * | 439 | for (;;) { |
419 | * complete()/wait_for_completion() is similar to up()/down(), | 440 | set_current_state(TASK_INTERRUPTIBLE); |
420 | * except that complete() is safe in the case where the structure | 441 | if (kthread_should_stop()) |
421 | * is getting deleted in a parallel mode of execution (i.e. just | 442 | break; |
422 | * after the down() -- that's necessary for the thread-shutdown | 443 | schedule(); |
423 | * case. | 444 | } |
424 | * | 445 | __set_current_state(TASK_RUNNING); |
425 | * complete_and_exit() goes even further than this -- it is safe in | 446 | return 0; |
426 | * the case that the thread of the caller is going away (not just | ||
427 | * the structure) -- this is necessary for the module-remove case. | ||
428 | * This is important in preemption kernels, which transfer the flow | ||
429 | * of execution immediately upon a complete(). | ||
430 | */ | ||
431 | complete_and_exit(&threads_gone, 0); | ||
432 | } | 447 | } |
433 | 448 | ||
434 | /*********************************************************************** | 449 | /*********************************************************************** |
@@ -796,19 +811,13 @@ static int usb_stor_acquire_resources(struct us_data *us) | |||
796 | } | 811 | } |
797 | 812 | ||
798 | /* Start up our control thread */ | 813 | /* Start up our control thread */ |
799 | th = kthread_create(usb_stor_control_thread, us, "usb-storage"); | 814 | th = kthread_run(usb_stor_control_thread, us, "usb-storage"); |
800 | if (IS_ERR(th)) { | 815 | if (IS_ERR(th)) { |
801 | printk(KERN_WARNING USB_STORAGE | 816 | printk(KERN_WARNING USB_STORAGE |
802 | "Unable to start control thread\n"); | 817 | "Unable to start control thread\n"); |
803 | return PTR_ERR(th); | 818 | return PTR_ERR(th); |
804 | } | 819 | } |
805 | 820 | us->ctl_thread = th; | |
806 | /* Take a reference to the host for the control thread and | ||
807 | * count it among all the threads we have launched. Then | ||
808 | * start it up. */ | ||
809 | scsi_host_get(us_to_host(us)); | ||
810 | atomic_inc(&total_threads); | ||
811 | wake_up_process(th); | ||
812 | 821 | ||
813 | return 0; | 822 | return 0; |
814 | } | 823 | } |
@@ -825,6 +834,8 @@ static void usb_stor_release_resources(struct us_data *us) | |||
825 | US_DEBUGP("-- sending exit command to thread\n"); | 834 | US_DEBUGP("-- sending exit command to thread\n"); |
826 | set_bit(US_FLIDX_DISCONNECTING, &us->flags); | 835 | set_bit(US_FLIDX_DISCONNECTING, &us->flags); |
827 | up(&us->sema); | 836 | up(&us->sema); |
837 | if (us->ctl_thread) | ||
838 | kthread_stop(us->ctl_thread); | ||
828 | 839 | ||
829 | /* Call the destructor routine, if it exists */ | 840 | /* Call the destructor routine, if it exists */ |
830 | if (us->extra_destructor) { | 841 | if (us->extra_destructor) { |
@@ -938,6 +949,7 @@ retry: | |||
938 | } | 949 | } |
939 | 950 | ||
940 | scsi_host_put(us_to_host(us)); | 951 | scsi_host_put(us_to_host(us)); |
952 | usb_autopm_put_interface(us->pusb_intf); | ||
941 | complete_and_exit(&threads_gone, 0); | 953 | complete_and_exit(&threads_gone, 0); |
942 | } | 954 | } |
943 | 955 | ||
@@ -1027,6 +1039,7 @@ static int storage_probe(struct usb_interface *intf, | |||
1027 | * start it up. */ | 1039 | * start it up. */ |
1028 | scsi_host_get(us_to_host(us)); | 1040 | scsi_host_get(us_to_host(us)); |
1029 | atomic_inc(&total_threads); | 1041 | atomic_inc(&total_threads); |
1042 | usb_autopm_get_interface(intf); /* dropped in the scanning thread */ | ||
1030 | wake_up_process(th); | 1043 | wake_up_process(th); |
1031 | 1044 | ||
1032 | return 0; | 1045 | return 0; |
@@ -1059,10 +1072,12 @@ static struct usb_driver usb_storage_driver = { | |||
1059 | #ifdef CONFIG_PM | 1072 | #ifdef CONFIG_PM |
1060 | .suspend = storage_suspend, | 1073 | .suspend = storage_suspend, |
1061 | .resume = storage_resume, | 1074 | .resume = storage_resume, |
1075 | .reset_resume = storage_reset_resume, | ||
1062 | #endif | 1076 | #endif |
1063 | .pre_reset = storage_pre_reset, | 1077 | .pre_reset = storage_pre_reset, |
1064 | .post_reset = storage_post_reset, | 1078 | .post_reset = storage_post_reset, |
1065 | .id_table = storage_usb_ids, | 1079 | .id_table = storage_usb_ids, |
1080 | .supports_autosuspend = 1, | ||
1066 | }; | 1081 | }; |
1067 | 1082 | ||
1068 | static int __init usb_stor_init(void) | 1083 | static int __init usb_stor_init(void) |
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 6dac1ffdde86..6445665b1577 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h | |||
@@ -144,6 +144,7 @@ struct us_data { | |||
144 | unsigned char *sensebuf; /* sense data buffer */ | 144 | unsigned char *sensebuf; /* sense data buffer */ |
145 | dma_addr_t cr_dma; /* buffer DMA addresses */ | 145 | dma_addr_t cr_dma; /* buffer DMA addresses */ |
146 | dma_addr_t iobuf_dma; | 146 | dma_addr_t iobuf_dma; |
147 | struct task_struct *ctl_thread; /* the control thread */ | ||
147 | 148 | ||
148 | /* mutual exclusion and synchronization structures */ | 149 | /* mutual exclusion and synchronization structures */ |
149 | struct semaphore sema; /* to sleep thread on */ | 150 | struct semaphore sema; /* to sleep thread on */ |
diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index 8432bf171d2e..8de11deb5d14 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c | |||
@@ -34,9 +34,6 @@ static struct usb_device_id skel_table [] = { | |||
34 | }; | 34 | }; |
35 | MODULE_DEVICE_TABLE(usb, skel_table); | 35 | MODULE_DEVICE_TABLE(usb, skel_table); |
36 | 36 | ||
37 | /* to prevent a race between open and disconnect */ | ||
38 | static DEFINE_MUTEX(skel_open_lock); | ||
39 | |||
40 | 37 | ||
41 | /* Get a minor range for your devices from the usb maintainer */ | 38 | /* Get a minor range for your devices from the usb maintainer */ |
42 | #define USB_SKEL_MINOR_BASE 192 | 39 | #define USB_SKEL_MINOR_BASE 192 |
@@ -54,16 +51,21 @@ struct usb_skel { | |||
54 | struct usb_device *udev; /* the usb device for this device */ | 51 | struct usb_device *udev; /* the usb device for this device */ |
55 | struct usb_interface *interface; /* the interface for this device */ | 52 | struct usb_interface *interface; /* the interface for this device */ |
56 | struct semaphore limit_sem; /* limiting the number of writes in progress */ | 53 | struct semaphore limit_sem; /* limiting the number of writes in progress */ |
54 | struct usb_anchor submitted; /* in case we need to retract our submissions */ | ||
57 | unsigned char *bulk_in_buffer; /* the buffer to receive data */ | 55 | unsigned char *bulk_in_buffer; /* the buffer to receive data */ |
58 | size_t bulk_in_size; /* the size of the receive buffer */ | 56 | size_t bulk_in_size; /* the size of the receive buffer */ |
59 | __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ | 57 | __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ |
60 | __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ | 58 | __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ |
59 | int errors; /* the last request tanked */ | ||
60 | int open_count; /* count the number of openers */ | ||
61 | spinlock_t err_lock; /* lock for errors */ | ||
61 | struct kref kref; | 62 | struct kref kref; |
62 | struct mutex io_mutex; /* synchronize I/O with disconnect */ | 63 | struct mutex io_mutex; /* synchronize I/O with disconnect */ |
63 | }; | 64 | }; |
64 | #define to_skel_dev(d) container_of(d, struct usb_skel, kref) | 65 | #define to_skel_dev(d) container_of(d, struct usb_skel, kref) |
65 | 66 | ||
66 | static struct usb_driver skel_driver; | 67 | static struct usb_driver skel_driver; |
68 | static void skel_draw_down(struct usb_skel *dev); | ||
67 | 69 | ||
68 | static void skel_delete(struct kref *kref) | 70 | static void skel_delete(struct kref *kref) |
69 | { | 71 | { |
@@ -83,10 +85,8 @@ static int skel_open(struct inode *inode, struct file *file) | |||
83 | 85 | ||
84 | subminor = iminor(inode); | 86 | subminor = iminor(inode); |
85 | 87 | ||
86 | mutex_lock(&skel_open_lock); | ||
87 | interface = usb_find_interface(&skel_driver, subminor); | 88 | interface = usb_find_interface(&skel_driver, subminor); |
88 | if (!interface) { | 89 | if (!interface) { |
89 | mutex_unlock(&skel_open_lock); | ||
90 | err ("%s - error, can't find device for minor %d", | 90 | err ("%s - error, can't find device for minor %d", |
91 | __FUNCTION__, subminor); | 91 | __FUNCTION__, subminor); |
92 | retval = -ENODEV; | 92 | retval = -ENODEV; |
@@ -95,22 +95,33 @@ static int skel_open(struct inode *inode, struct file *file) | |||
95 | 95 | ||
96 | dev = usb_get_intfdata(interface); | 96 | dev = usb_get_intfdata(interface); |
97 | if (!dev) { | 97 | if (!dev) { |
98 | mutex_unlock(&skel_open_lock); | ||
99 | retval = -ENODEV; | 98 | retval = -ENODEV; |
100 | goto exit; | 99 | goto exit; |
101 | } | 100 | } |
102 | 101 | ||
103 | /* increment our usage count for the device */ | 102 | /* increment our usage count for the device */ |
104 | kref_get(&dev->kref); | 103 | kref_get(&dev->kref); |
105 | /* now we can drop the lock */ | ||
106 | mutex_unlock(&skel_open_lock); | ||
107 | 104 | ||
108 | /* prevent the device from being autosuspended */ | 105 | /* lock the device to allow correctly handling errors |
109 | retval = usb_autopm_get_interface(interface); | 106 | * in resumption */ |
110 | if (retval) { | 107 | mutex_lock(&dev->io_mutex); |
108 | |||
109 | if (!dev->open_count++) { | ||
110 | retval = usb_autopm_get_interface(interface); | ||
111 | if (retval) { | ||
112 | dev->open_count--; | ||
113 | mutex_unlock(&dev->io_mutex); | ||
114 | kref_put(&dev->kref, skel_delete); | ||
115 | goto exit; | ||
116 | } | ||
117 | } /* else { //uncomment this block if you want exclusive open | ||
118 | retval = -EBUSY; | ||
119 | dev->open_count--; | ||
120 | mutex_unlock(&dev->io_mutex); | ||
111 | kref_put(&dev->kref, skel_delete); | 121 | kref_put(&dev->kref, skel_delete); |
112 | goto exit; | 122 | goto exit; |
113 | } | 123 | } */ |
124 | /* prevent the device from being autosuspended */ | ||
114 | 125 | ||
115 | /* save our object in the file's private structure */ | 126 | /* save our object in the file's private structure */ |
116 | file->private_data = dev; | 127 | file->private_data = dev; |
@@ -129,7 +140,7 @@ static int skel_release(struct inode *inode, struct file *file) | |||
129 | 140 | ||
130 | /* allow the device to be autosuspended */ | 141 | /* allow the device to be autosuspended */ |
131 | mutex_lock(&dev->io_mutex); | 142 | mutex_lock(&dev->io_mutex); |
132 | if (dev->interface) | 143 | if (!--dev->open_count && dev->interface) |
133 | usb_autopm_put_interface(dev->interface); | 144 | usb_autopm_put_interface(dev->interface); |
134 | mutex_unlock(&dev->io_mutex); | 145 | mutex_unlock(&dev->io_mutex); |
135 | 146 | ||
@@ -138,6 +149,30 @@ static int skel_release(struct inode *inode, struct file *file) | |||
138 | return 0; | 149 | return 0; |
139 | } | 150 | } |
140 | 151 | ||
152 | static int skel_flush(struct file *file, fl_owner_t id) | ||
153 | { | ||
154 | struct usb_skel *dev; | ||
155 | int res; | ||
156 | |||
157 | dev = (struct usb_skel *)file->private_data; | ||
158 | if (dev == NULL) | ||
159 | return -ENODEV; | ||
160 | |||
161 | /* wait for io to stop */ | ||
162 | mutex_lock(&dev->io_mutex); | ||
163 | skel_draw_down(dev); | ||
164 | |||
165 | /* read out errors, leave subsequent opens a clean slate */ | ||
166 | spin_lock_irq(&dev->err_lock); | ||
167 | res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0; | ||
168 | dev->errors = 0; | ||
169 | spin_unlock_irq(&dev->err_lock); | ||
170 | |||
171 | mutex_unlock(&dev->io_mutex); | ||
172 | |||
173 | return res; | ||
174 | } | ||
175 | |||
141 | static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos) | 176 | static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos) |
142 | { | 177 | { |
143 | struct usb_skel *dev; | 178 | struct usb_skel *dev; |
@@ -179,12 +214,16 @@ static void skel_write_bulk_callback(struct urb *urb) | |||
179 | dev = (struct usb_skel *)urb->context; | 214 | dev = (struct usb_skel *)urb->context; |
180 | 215 | ||
181 | /* sync/async unlink faults aren't errors */ | 216 | /* sync/async unlink faults aren't errors */ |
182 | if (urb->status && | 217 | if (urb->status) { |
183 | !(urb->status == -ENOENT || | 218 | if(!(urb->status == -ENOENT || |
184 | urb->status == -ECONNRESET || | 219 | urb->status == -ECONNRESET || |
185 | urb->status == -ESHUTDOWN)) { | 220 | urb->status == -ESHUTDOWN)) |
186 | err("%s - nonzero write bulk status received: %d", | 221 | err("%s - nonzero write bulk status received: %d", |
187 | __FUNCTION__, urb->status); | 222 | __FUNCTION__, urb->status); |
223 | |||
224 | spin_lock(&dev->err_lock); | ||
225 | dev->errors = urb->status; | ||
226 | spin_unlock(&dev->err_lock); | ||
188 | } | 227 | } |
189 | 228 | ||
190 | /* free up our allocated buffer */ | 229 | /* free up our allocated buffer */ |
@@ -213,6 +252,17 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou | |||
213 | goto exit; | 252 | goto exit; |
214 | } | 253 | } |
215 | 254 | ||
255 | spin_lock_irq(&dev->err_lock); | ||
256 | if ((retval = dev->errors) < 0) { | ||
257 | /* any error is reported once */ | ||
258 | dev->errors = 0; | ||
259 | /* to preserve notifications about reset */ | ||
260 | retval = (retval == -EPIPE) ? retval : -EIO; | ||
261 | } | ||
262 | spin_unlock_irq(&dev->err_lock); | ||
263 | if (retval < 0) | ||
264 | goto error; | ||
265 | |||
216 | /* create a urb, and a buffer for it, and copy the data to the urb */ | 266 | /* create a urb, and a buffer for it, and copy the data to the urb */ |
217 | urb = usb_alloc_urb(0, GFP_KERNEL); | 267 | urb = usb_alloc_urb(0, GFP_KERNEL); |
218 | if (!urb) { | 268 | if (!urb) { |
@@ -244,13 +294,14 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou | |||
244 | usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), | 294 | usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), |
245 | buf, writesize, skel_write_bulk_callback, dev); | 295 | buf, writesize, skel_write_bulk_callback, dev); |
246 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 296 | urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
297 | usb_anchor_urb(urb, &dev->submitted); | ||
247 | 298 | ||
248 | /* send the data out the bulk port */ | 299 | /* send the data out the bulk port */ |
249 | retval = usb_submit_urb(urb, GFP_KERNEL); | 300 | retval = usb_submit_urb(urb, GFP_KERNEL); |
250 | mutex_unlock(&dev->io_mutex); | 301 | mutex_unlock(&dev->io_mutex); |
251 | if (retval) { | 302 | if (retval) { |
252 | err("%s - failed submitting write urb, error %d", __FUNCTION__, retval); | 303 | err("%s - failed submitting write urb, error %d", __FUNCTION__, retval); |
253 | goto error; | 304 | goto error_unanchor; |
254 | } | 305 | } |
255 | 306 | ||
256 | /* release our reference to this urb, the USB core will eventually free it entirely */ | 307 | /* release our reference to this urb, the USB core will eventually free it entirely */ |
@@ -259,6 +310,8 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, size_t cou | |||
259 | 310 | ||
260 | return writesize; | 311 | return writesize; |
261 | 312 | ||
313 | error_unanchor: | ||
314 | usb_unanchor_urb(urb); | ||
262 | error: | 315 | error: |
263 | if (urb) { | 316 | if (urb) { |
264 | usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma); | 317 | usb_buffer_free(dev->udev, writesize, buf, urb->transfer_dma); |
@@ -276,6 +329,7 @@ static const struct file_operations skel_fops = { | |||
276 | .write = skel_write, | 329 | .write = skel_write, |
277 | .open = skel_open, | 330 | .open = skel_open, |
278 | .release = skel_release, | 331 | .release = skel_release, |
332 | .flush = skel_flush, | ||
279 | }; | 333 | }; |
280 | 334 | ||
281 | /* | 335 | /* |
@@ -306,6 +360,8 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i | |||
306 | kref_init(&dev->kref); | 360 | kref_init(&dev->kref); |
307 | sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); | 361 | sema_init(&dev->limit_sem, WRITES_IN_FLIGHT); |
308 | mutex_init(&dev->io_mutex); | 362 | mutex_init(&dev->io_mutex); |
363 | spin_lock_init(&dev->err_lock); | ||
364 | init_usb_anchor(&dev->submitted); | ||
309 | 365 | ||
310 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | 366 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
311 | dev->interface = interface; | 367 | dev->interface = interface; |
@@ -368,22 +424,18 @@ static void skel_disconnect(struct usb_interface *interface) | |||
368 | struct usb_skel *dev; | 424 | struct usb_skel *dev; |
369 | int minor = interface->minor; | 425 | int minor = interface->minor; |
370 | 426 | ||
371 | /* prevent skel_open() from racing skel_disconnect() */ | ||
372 | mutex_lock(&skel_open_lock); | ||
373 | |||
374 | dev = usb_get_intfdata(interface); | 427 | dev = usb_get_intfdata(interface); |
375 | usb_set_intfdata(interface, NULL); | 428 | usb_set_intfdata(interface, NULL); |
376 | 429 | ||
377 | /* give back our minor */ | 430 | /* give back our minor */ |
378 | usb_deregister_dev(interface, &skel_class); | 431 | usb_deregister_dev(interface, &skel_class); |
379 | mutex_unlock(&skel_open_lock); | ||
380 | 432 | ||
381 | /* prevent more I/O from starting */ | 433 | /* prevent more I/O from starting */ |
382 | mutex_lock(&dev->io_mutex); | 434 | mutex_lock(&dev->io_mutex); |
383 | dev->interface = NULL; | 435 | dev->interface = NULL; |
384 | mutex_unlock(&dev->io_mutex); | 436 | mutex_unlock(&dev->io_mutex); |
385 | 437 | ||
386 | 438 | usb_kill_anchored_urbs(&dev->submitted); | |
387 | 439 | ||
388 | /* decrement our usage count */ | 440 | /* decrement our usage count */ |
389 | kref_put(&dev->kref, skel_delete); | 441 | kref_put(&dev->kref, skel_delete); |
@@ -391,10 +443,59 @@ static void skel_disconnect(struct usb_interface *interface) | |||
391 | info("USB Skeleton #%d now disconnected", minor); | 443 | info("USB Skeleton #%d now disconnected", minor); |
392 | } | 444 | } |
393 | 445 | ||
446 | static void skel_draw_down(struct usb_skel *dev) | ||
447 | { | ||
448 | int time; | ||
449 | |||
450 | time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000); | ||
451 | if (!time) | ||
452 | usb_kill_anchored_urbs(&dev->submitted); | ||
453 | } | ||
454 | |||
455 | static int skel_suspend(struct usb_interface *intf, pm_message_t message) | ||
456 | { | ||
457 | struct usb_skel *dev = usb_get_intfdata(intf); | ||
458 | |||
459 | if (!dev) | ||
460 | return 0; | ||
461 | skel_draw_down(dev); | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int skel_resume (struct usb_interface *intf) | ||
466 | { | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static int skel_pre_reset(struct usb_interface *intf) | ||
471 | { | ||
472 | struct usb_skel *dev = usb_get_intfdata(intf); | ||
473 | |||
474 | mutex_lock(&dev->io_mutex); | ||
475 | skel_draw_down(dev); | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
480 | static int skel_post_reset(struct usb_interface *intf) | ||
481 | { | ||
482 | struct usb_skel *dev = usb_get_intfdata(intf); | ||
483 | |||
484 | /* we are sure no URBs are active - no locking needed */ | ||
485 | dev->errors = -EPIPE; | ||
486 | mutex_unlock(&dev->io_mutex); | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | |||
394 | static struct usb_driver skel_driver = { | 491 | static struct usb_driver skel_driver = { |
395 | .name = "skeleton", | 492 | .name = "skeleton", |
396 | .probe = skel_probe, | 493 | .probe = skel_probe, |
397 | .disconnect = skel_disconnect, | 494 | .disconnect = skel_disconnect, |
495 | .suspend = skel_suspend, | ||
496 | .resume = skel_resume, | ||
497 | .pre_reset = skel_pre_reset, | ||
498 | .post_reset = skel_post_reset, | ||
398 | .id_table = skel_table, | 499 | .id_table = skel_table, |
399 | .supports_autosuspend = 1, | 500 | .supports_autosuspend = 1, |
400 | }; | 501 | }; |