blob: c87660b5edc3443583375c1dcb202d5705c42584 [file] [log] [blame]
Tony Olechd774efe2006-09-13 11:27:35 +01001/*
2* Host Controller Driver for the Elan Digital Systems U132 adapter
3*
4* Copyright(C) 2006 Elan Digital Systems Limited
5* http://www.elandigitalsystems.com
6*
7* Author and Maintainer - Tony Olech - Elan Digital Systems
8* tony.olech@elandigitalsystems.com
9*
10* This program is free software;you can redistribute it and/or
11* modify it under the terms of the GNU General Public License as
12* published by the Free Software Foundation, version 2.
13*
14*
15* This driver was written by Tony Olech(tony.olech@elandigitalsystems.com)
16* based on various USB host drivers in the 2.6.15 linux kernel
17* with constant reference to the 3rd Edition of Linux Device Drivers
18* published by O'Reilly
19*
20* The U132 adapter is a USB to CardBus adapter specifically designed
21* for PC cards that contain an OHCI host controller. Typical PC cards
22* are the Orange Mobile 3G Option GlobeTrotter Fusion card.
23*
24* The U132 adapter will *NOT *work with PC cards that do not contain
25* an OHCI controller. A simple way to test whether a PC card has an
26* OHCI controller as an interface is to insert the PC card directly
27* into a laptop(or desktop) with a CardBus slot and if "lspci" shows
28* a new USB controller and "lsusb -v" shows a new OHCI Host Controller
29* then there is a good chance that the U132 adapter will support the
30* PC card.(you also need the specific client driver for the PC card)
31*
32* Please inform the Author and Maintainer about any PC cards that
33* contain OHCI Host Controller and work when directly connected to
34* an embedded CardBus slot but do not work when they are connected
35* via an ELAN U132 adapter.
36*
37*/
Tony Olechd774efe2006-09-13 11:27:35 +010038#include <linux/kernel.h>
39#include <linux/module.h>
40#include <linux/moduleparam.h>
41#include <linux/delay.h>
42#include <linux/ioport.h>
Tony Olech4b873612006-12-06 13:16:22 +000043#include <linux/pci_ids.h>
Tony Olechd774efe2006-09-13 11:27:35 +010044#include <linux/sched.h>
45#include <linux/slab.h>
Tony Olechd774efe2006-09-13 11:27:35 +010046#include <linux/errno.h>
47#include <linux/init.h>
48#include <linux/timer.h>
49#include <linux/list.h>
50#include <linux/interrupt.h>
51#include <linux/usb.h>
52#include <linux/workqueue.h>
53#include <linux/platform_device.h>
Matthias Kaehlcked2066eb2007-07-13 21:26:59 +020054#include <linux/mutex.h>
Tony Olechd774efe2006-09-13 11:27:35 +010055#include <asm/io.h>
56#include <asm/irq.h>
57#include <asm/system.h>
58#include <asm/byteorder.h>
59#include "../core/hcd.h"
David Brownell47f84682007-04-29 10:21:14 -070060
61 /* FIXME ohci.h is ONLY for internal use by the OHCI driver.
62 * If you're going to try stuff like this, you need to split
63 * out shareable stuff (register declarations?) into its own
64 * file, maybe name <linux/usb/ohci.h>
65 */
66
Tony Olechd774efe2006-09-13 11:27:35 +010067#include "ohci.h"
68#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
69#define OHCI_INTR_INIT (OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | \
70 OHCI_INTR_WDH)
71MODULE_AUTHOR("Tony Olech - Elan Digital Systems Limited");
72MODULE_DESCRIPTION("U132 USB Host Controller Driver");
73MODULE_LICENSE("GPL");
74#define INT_MODULE_PARM(n, v) static int n = v;module_param(n, int, 0444)
75INT_MODULE_PARM(testing, 0);
76/* Some boards misreport power switching/overcurrent*/
77static int distrust_firmware = 1;
78module_param(distrust_firmware, bool, 0);
79MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
80 "t setup");
Adrian Bunk27a3de42006-11-20 03:23:54 +010081static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
Tony Olechd774efe2006-09-13 11:27:35 +010082/*
83* u132_module_lock exists to protect access to global variables
84*
85*/
Matthias Kaehlcked2066eb2007-07-13 21:26:59 +020086static struct mutex u132_module_lock;
Tony Olechd774efe2006-09-13 11:27:35 +010087static int u132_exiting = 0;
88static int u132_instances = 0;
89static struct list_head u132_static_list;
90/*
91* end of the global variables protected by u132_module_lock
92*/
93static struct workqueue_struct *workqueue;
94#define MAX_U132_PORTS 7
95#define MAX_U132_ADDRS 128
96#define MAX_U132_UDEVS 4
97#define MAX_U132_ENDPS 100
98#define MAX_U132_RINGS 4
99static const char *cc_to_text[16] = {
100 "No Error ",
101 "CRC Error ",
102 "Bit Stuff ",
103 "Data Togg ",
104 "Stall ",
105 "DevNotResp ",
106 "PIDCheck ",
107 "UnExpPID ",
108 "DataOver ",
109 "DataUnder ",
110 "(for hw) ",
111 "(for hw) ",
112 "BufferOver ",
113 "BuffUnder ",
114 "(for HCD) ",
115 "(for HCD) "
116};
117struct u132_port {
118 struct u132 *u132;
119 int reset;
120 int enable;
121 int power;
122 int Status;
123};
124struct u132_addr {
125 u8 address;
126};
127struct u132_udev {
128 struct kref kref;
129 struct usb_device *usb_device;
130 u8 enumeration;
131 u8 udev_number;
132 u8 usb_addr;
133 u8 portnumber;
134 u8 endp_number_in[16];
135 u8 endp_number_out[16];
136};
137#define ENDP_QUEUE_SHIFT 3
138#define ENDP_QUEUE_SIZE (1<<ENDP_QUEUE_SHIFT)
139#define ENDP_QUEUE_MASK (ENDP_QUEUE_SIZE-1)
140struct u132_urbq {
141 struct list_head urb_more;
142 struct urb *urb;
143};
144struct u132_spin {
145 spinlock_t slock;
146};
147struct u132_endp {
148 struct kref kref;
149 u8 udev_number;
150 u8 endp_number;
151 u8 usb_addr;
152 u8 usb_endp;
153 struct u132 *u132;
154 struct list_head endp_ring;
155 struct u132_ring *ring;
156 unsigned toggle_bits:2;
157 unsigned active:1;
158 unsigned delayed:1;
159 unsigned input:1;
160 unsigned output:1;
161 unsigned pipetype:2;
162 unsigned dequeueing:1;
163 unsigned edset_flush:1;
164 unsigned spare_bits:14;
165 unsigned long jiffies;
166 struct usb_host_endpoint *hep;
167 struct u132_spin queue_lock;
168 u16 queue_size;
169 u16 queue_last;
170 u16 queue_next;
171 struct urb *urb_list[ENDP_QUEUE_SIZE];
172 struct list_head urb_more;
David Howellsc4028952006-11-22 14:57:56 +0000173 struct delayed_work scheduler;
Tony Olechd774efe2006-09-13 11:27:35 +0100174};
175struct u132_ring {
176 unsigned in_use:1;
177 unsigned length:7;
178 u8 number;
179 struct u132 *u132;
180 struct u132_endp *curr_endp;
David Howellsc4028952006-11-22 14:57:56 +0000181 struct delayed_work scheduler;
Tony Olechd774efe2006-09-13 11:27:35 +0100182};
Tony Olechd774efe2006-09-13 11:27:35 +0100183struct u132 {
184 struct kref kref;
185 struct list_head u132_list;
186 struct semaphore sw_lock;
187 struct semaphore scheduler_lock;
188 struct u132_platform_data *board;
189 struct platform_device *platform_dev;
190 struct u132_ring ring[MAX_U132_RINGS];
191 int sequence_num;
192 int going;
193 int power;
194 int reset;
195 int num_ports;
196 u32 hc_control;
197 u32 hc_fminterval;
198 u32 hc_roothub_status;
199 u32 hc_roothub_a;
200 u32 hc_roothub_portstatus[MAX_ROOT_PORTS];
201 int flags;
202 unsigned long next_statechange;
David Howellsc4028952006-11-22 14:57:56 +0000203 struct delayed_work monitor;
Tony Olechd774efe2006-09-13 11:27:35 +0100204 int num_endpoints;
205 struct u132_addr addr[MAX_U132_ADDRS];
206 struct u132_udev udev[MAX_U132_UDEVS];
207 struct u132_port port[MAX_U132_PORTS];
208 struct u132_endp *endp[MAX_U132_ENDPS];
209};
Adrian Bunk9ce85402006-11-20 03:24:44 +0100210
Tony Olechd774efe2006-09-13 11:27:35 +0100211/*
Matt LaPlante0779bf22006-11-30 05:24:39 +0100212* these cannot be inlines because we need the structure offset!!
Tony Olechd774efe2006-09-13 11:27:35 +0100213* Does anyone have a better way?????
214*/
Tony Olech4b873612006-12-06 13:16:22 +0000215#define ftdi_read_pcimem(pdev, member, data) usb_ftdi_elan_read_pcimem(pdev, \
216 offsetof(struct ohci_regs, member), 0, data);
217#define ftdi_write_pcimem(pdev, member, data) usb_ftdi_elan_write_pcimem(pdev, \
218 offsetof(struct ohci_regs, member), 0, data);
Tony Olechd774efe2006-09-13 11:27:35 +0100219#define u132_read_pcimem(u132, member, data) \
220 usb_ftdi_elan_read_pcimem(u132->platform_dev, offsetof(struct \
221 ohci_regs, member), 0, data);
222#define u132_write_pcimem(u132, member, data) \
223 usb_ftdi_elan_write_pcimem(u132->platform_dev, offsetof(struct \
224 ohci_regs, member), 0, data);
Tony Olechd774efe2006-09-13 11:27:35 +0100225static inline struct u132 *udev_to_u132(struct u132_udev *udev)
226{
227 u8 udev_number = udev->udev_number;
228 return container_of(udev, struct u132, udev[udev_number]);
229}
230
231static inline struct u132 *hcd_to_u132(struct usb_hcd *hcd)
232{
233 return (struct u132 *)(hcd->hcd_priv);
234}
235
236static inline struct usb_hcd *u132_to_hcd(struct u132 *u132)
237{
238 return container_of((void *)u132, struct usb_hcd, hcd_priv);
239}
240
241static inline void u132_disable(struct u132 *u132)
242{
243 u132_to_hcd(u132)->state = HC_STATE_HALT;
244}
245
246
247#define kref_to_u132(d) container_of(d, struct u132, kref)
248#define kref_to_u132_endp(d) container_of(d, struct u132_endp, kref)
249#define kref_to_u132_udev(d) container_of(d, struct u132_udev, kref)
250#include "../misc/usb_u132.h"
251static const char hcd_name[] = "u132_hcd";
252#define PORT_C_MASK ((USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | \
253 USB_PORT_STAT_C_SUSPEND | USB_PORT_STAT_C_OVERCURRENT | \
254 USB_PORT_STAT_C_RESET) << 16)
255static void u132_hcd_delete(struct kref *kref)
256{
257 struct u132 *u132 = kref_to_u132(kref);
258 struct platform_device *pdev = u132->platform_dev;
259 struct usb_hcd *hcd = u132_to_hcd(u132);
260 u132->going += 1;
Matthias Kaehlcked2066eb2007-07-13 21:26:59 +0200261 mutex_lock(&u132_module_lock);
Tony Olechd774efe2006-09-13 11:27:35 +0100262 list_del_init(&u132->u132_list);
263 u132_instances -= 1;
Matthias Kaehlcked2066eb2007-07-13 21:26:59 +0200264 mutex_unlock(&u132_module_lock);
Tony Olechd774efe2006-09-13 11:27:35 +0100265 dev_warn(&u132->platform_dev->dev, "FREEING the hcd=%p and thus the u13"
266 "2=%p going=%d pdev=%p\n", hcd, u132, u132->going, pdev);
267 usb_put_hcd(hcd);
268}
269
270static inline void u132_u132_put_kref(struct u132 *u132)
271{
272 kref_put(&u132->kref, u132_hcd_delete);
273}
274
275static inline void u132_u132_init_kref(struct u132 *u132)
276{
277 kref_init(&u132->kref);
278}
279
280static void u132_udev_delete(struct kref *kref)
281{
282 struct u132_udev *udev = kref_to_u132_udev(kref);
283 udev->udev_number = 0;
284 udev->usb_device = NULL;
285 udev->usb_addr = 0;
286 udev->enumeration = 0;
287}
288
289static inline void u132_udev_put_kref(struct u132 *u132, struct u132_udev *udev)
290{
291 kref_put(&udev->kref, u132_udev_delete);
292}
293
294static inline void u132_udev_get_kref(struct u132 *u132, struct u132_udev *udev)
295{
296 kref_get(&udev->kref);
297}
298
299static inline void u132_udev_init_kref(struct u132 *u132,
300 struct u132_udev *udev)
301{
302 kref_init(&udev->kref);
303}
304
305static inline void u132_ring_put_kref(struct u132 *u132, struct u132_ring *ring)
306{
307 kref_put(&u132->kref, u132_hcd_delete);
308}
309
310static void u132_ring_requeue_work(struct u132 *u132, struct u132_ring *ring,
311 unsigned int delta)
312{
313 if (delta > 0) {
314 if (queue_delayed_work(workqueue, &ring->scheduler, delta))
315 return;
David Howellsc4028952006-11-22 14:57:56 +0000316 } else if (queue_delayed_work(workqueue, &ring->scheduler, 0))
Tony Olechd774efe2006-09-13 11:27:35 +0100317 return;
318 kref_put(&u132->kref, u132_hcd_delete);
319 return;
320}
321
322static void u132_ring_queue_work(struct u132 *u132, struct u132_ring *ring,
323 unsigned int delta)
324{
325 kref_get(&u132->kref);
326 u132_ring_requeue_work(u132, ring, delta);
327 return;
328}
329
330static void u132_ring_cancel_work(struct u132 *u132, struct u132_ring *ring)
331{
332 if (cancel_delayed_work(&ring->scheduler)) {
333 kref_put(&u132->kref, u132_hcd_delete);
334 }
335}
336
337static void u132_endp_delete(struct kref *kref)
338{
339 struct u132_endp *endp = kref_to_u132_endp(kref);
340 struct u132 *u132 = endp->u132;
341 u8 usb_addr = endp->usb_addr;
342 u8 usb_endp = endp->usb_endp;
343 u8 address = u132->addr[usb_addr].address;
344 struct u132_udev *udev = &u132->udev[address];
345 u8 endp_number = endp->endp_number;
346 struct usb_host_endpoint *hep = endp->hep;
347 struct u132_ring *ring = endp->ring;
348 struct list_head *head = &endp->endp_ring;
349 ring->length -= 1;
350 if (endp == ring->curr_endp) {
351 if (list_empty(head)) {
352 ring->curr_endp = NULL;
353 list_del(head);
354 } else {
355 struct u132_endp *next_endp = list_entry(head->next,
356 struct u132_endp, endp_ring);
357 ring->curr_endp = next_endp;
358 list_del(head);
359 }} else
360 list_del(head);
361 if (endp->input) {
362 udev->endp_number_in[usb_endp] = 0;
363 u132_udev_put_kref(u132, udev);
364 }
365 if (endp->output) {
366 udev->endp_number_out[usb_endp] = 0;
367 u132_udev_put_kref(u132, udev);
368 }
369 u132->endp[endp_number - 1] = NULL;
370 hep->hcpriv = NULL;
371 kfree(endp);
372 u132_u132_put_kref(u132);
373}
374
375static inline void u132_endp_put_kref(struct u132 *u132, struct u132_endp *endp)
376{
377 kref_put(&endp->kref, u132_endp_delete);
378}
379
380static inline void u132_endp_get_kref(struct u132 *u132, struct u132_endp *endp)
381{
382 kref_get(&endp->kref);
383}
384
385static inline void u132_endp_init_kref(struct u132 *u132,
386 struct u132_endp *endp)
387{
388 kref_init(&endp->kref);
389 kref_get(&u132->kref);
390}
391
392static void u132_endp_queue_work(struct u132 *u132, struct u132_endp *endp,
393 unsigned int delta)
394{
David Howellsc4028952006-11-22 14:57:56 +0000395 if (queue_delayed_work(workqueue, &endp->scheduler, delta))
396 kref_get(&endp->kref);
Tony Olechd774efe2006-09-13 11:27:35 +0100397}
398
399static void u132_endp_cancel_work(struct u132 *u132, struct u132_endp *endp)
400{
401 if (cancel_delayed_work(&endp->scheduler))
402 kref_put(&endp->kref, u132_endp_delete);
403}
404
405static inline void u132_monitor_put_kref(struct u132 *u132)
406{
407 kref_put(&u132->kref, u132_hcd_delete);
408}
409
410static void u132_monitor_queue_work(struct u132 *u132, unsigned int delta)
411{
David Howellsc4028952006-11-22 14:57:56 +0000412 if (queue_delayed_work(workqueue, &u132->monitor, delta))
413 kref_get(&u132->kref);
Tony Olechd774efe2006-09-13 11:27:35 +0100414}
415
416static void u132_monitor_requeue_work(struct u132 *u132, unsigned int delta)
417{
David Howellsc4028952006-11-22 14:57:56 +0000418 if (!queue_delayed_work(workqueue, &u132->monitor, delta))
419 kref_put(&u132->kref, u132_hcd_delete);
Tony Olechd774efe2006-09-13 11:27:35 +0100420}
421
422static void u132_monitor_cancel_work(struct u132 *u132)
423{
424 if (cancel_delayed_work(&u132->monitor))
425 kref_put(&u132->kref, u132_hcd_delete);
426}
427
428static int read_roothub_info(struct u132 *u132)
429{
430 u32 revision;
431 int retval;
432 retval = u132_read_pcimem(u132, revision, &revision);
433 if (retval) {
434 dev_err(&u132->platform_dev->dev, "error %d accessing device co"
435 "ntrol\n", retval);
436 return retval;
437 } else if ((revision & 0xFF) == 0x10) {
438 } else if ((revision & 0xFF) == 0x11) {
439 } else {
440 dev_err(&u132->platform_dev->dev, "device revision is not valid"
441 " %08X\n", revision);
442 return -ENODEV;
443 }
444 retval = u132_read_pcimem(u132, control, &u132->hc_control);
445 if (retval) {
446 dev_err(&u132->platform_dev->dev, "error %d accessing device co"
447 "ntrol\n", retval);
448 return retval;
449 }
450 retval = u132_read_pcimem(u132, roothub.status,
451 &u132->hc_roothub_status);
452 if (retval) {
453 dev_err(&u132->platform_dev->dev, "error %d accessing device re"
454 "g roothub.status\n", retval);
455 return retval;
456 }
457 retval = u132_read_pcimem(u132, roothub.a, &u132->hc_roothub_a);
458 if (retval) {
459 dev_err(&u132->platform_dev->dev, "error %d accessing device re"
460 "g roothub.a\n", retval);
461 return retval;
462 }
463 {
464 int I = u132->num_ports;
465 int i = 0;
466 while (I-- > 0) {
467 retval = u132_read_pcimem(u132, roothub.portstatus[i],
468 &u132->hc_roothub_portstatus[i]);
469 if (retval) {
470 dev_err(&u132->platform_dev->dev, "error %d acc"
471 "essing device roothub.portstatus[%d]\n"
472 , retval, i);
473 return retval;
474 } else
475 i += 1;
476 }
477 }
478 return 0;
479}
480
David Howellsc4028952006-11-22 14:57:56 +0000481static void u132_hcd_monitor_work(struct work_struct *work)
Tony Olechd774efe2006-09-13 11:27:35 +0100482{
David Howellsc4028952006-11-22 14:57:56 +0000483 struct u132 *u132 = container_of(work, struct u132, monitor.work);
Tony Olechd774efe2006-09-13 11:27:35 +0100484 if (u132->going > 1) {
485 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
486 , u132->going);
487 u132_monitor_put_kref(u132);
488 return;
489 } else if (u132->going > 0) {
490 dev_err(&u132->platform_dev->dev, "device is being removed\n");
491 u132_monitor_put_kref(u132);
492 return;
493 } else {
494 int retval;
495 down(&u132->sw_lock);
496 retval = read_roothub_info(u132);
497 if (retval) {
498 struct usb_hcd *hcd = u132_to_hcd(u132);
499 u132_disable(u132);
500 u132->going = 1;
501 up(&u132->sw_lock);
502 usb_hc_died(hcd);
503 ftdi_elan_gone_away(u132->platform_dev);
504 u132_monitor_put_kref(u132);
505 return;
506 } else {
507 u132_monitor_requeue_work(u132, 500);
508 up(&u132->sw_lock);
509 return;
510 }
511 }
512}
513
514static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
515 struct urb *urb, int status)
516{
517 struct u132_ring *ring;
518 unsigned long irqs;
519 struct usb_hcd *hcd = u132_to_hcd(u132);
520 urb->error_count = 0;
521 urb->status = status;
522 urb->hcpriv = NULL;
523 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
Alan Sterne9df41c2007-08-08 11:48:02 -0400524 usb_hcd_unlink_urb_from_ep(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +0100525 endp->queue_next += 1;
526 if (ENDP_QUEUE_SIZE > --endp->queue_size) {
527 endp->active = 0;
528 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
529 } else {
530 struct list_head *next = endp->urb_more.next;
531 struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
532 urb_more);
533 list_del(next);
534 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
535 urbq->urb;
536 endp->active = 0;
537 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
538 kfree(urbq);
539 } down(&u132->scheduler_lock);
540 ring = endp->ring;
541 ring->in_use = 0;
542 u132_ring_cancel_work(u132, ring);
543 u132_ring_queue_work(u132, ring, 0);
544 up(&u132->scheduler_lock);
545 u132_endp_put_kref(u132, endp);
David Howells7d12e782006-10-05 14:55:46 +0100546 usb_hcd_giveback_urb(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +0100547 return;
548}
549
550static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,
551 struct urb *urb, int status)
552{
553 u132_endp_put_kref(u132, endp);
554}
555
556static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
557 struct urb *urb, int status)
558{
559 unsigned long irqs;
560 struct usb_hcd *hcd = u132_to_hcd(u132);
561 urb->error_count = 0;
562 urb->status = status;
563 urb->hcpriv = NULL;
564 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
Alan Sterne9df41c2007-08-08 11:48:02 -0400565 usb_hcd_unlink_urb_from_ep(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +0100566 endp->queue_next += 1;
567 if (ENDP_QUEUE_SIZE > --endp->queue_size) {
568 endp->active = 0;
569 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
570 } else {
571 struct list_head *next = endp->urb_more.next;
572 struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
573 urb_more);
574 list_del(next);
575 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
576 urbq->urb;
577 endp->active = 0;
578 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
579 kfree(urbq);
David Howells7d12e782006-10-05 14:55:46 +0100580 } usb_hcd_giveback_urb(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +0100581 return;
582}
583
584static inline int edset_input(struct u132 *u132, struct u132_ring *ring,
585 struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
586 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
587 int toggle_bits, int error_count, int condition_code, int repeat_number,
588 int halted, int skipped, int actual, int non_null))
589{
590 return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
591 urb, address, endp->usb_endp, toggle_bits, callback);
592}
593
594static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,
595 struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
596 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
597 int toggle_bits, int error_count, int condition_code, int repeat_number,
598 int halted, int skipped, int actual, int non_null))
599{
600 return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
601 urb, address, endp->usb_endp, toggle_bits, callback);
602}
603
604static inline int edset_single(struct u132 *u132, struct u132_ring *ring,
605 struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
606 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
607 int toggle_bits, int error_count, int condition_code, int repeat_number,
608 int halted, int skipped, int actual, int non_null))
609{
610 return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
611 endp, urb, address, endp->usb_endp, toggle_bits, callback);
612}
613
614static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
615 struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
616 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
617 int toggle_bits, int error_count, int condition_code, int repeat_number,
618 int halted, int skipped, int actual, int non_null))
619{
620 return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
621 endp, urb, address, endp->usb_endp, toggle_bits, callback);
622}
623
624
625/*
626* must not LOCK sw_lock
627*
628*/
629static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
630 int len, int toggle_bits, int error_count, int condition_code,
631 int repeat_number, int halted, int skipped, int actual, int non_null)
632{
633 struct u132_endp *endp = data;
634 struct u132 *u132 = endp->u132;
635 u8 address = u132->addr[endp->usb_addr].address;
636 struct u132_udev *udev = &u132->udev[address];
637 down(&u132->scheduler_lock);
638 if (u132->going > 1) {
639 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
640 , u132->going);
641 up(&u132->scheduler_lock);
642 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
643 return;
644 } else if (endp->dequeueing) {
645 endp->dequeueing = 0;
646 up(&u132->scheduler_lock);
647 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
648 return;
649 } else if (u132->going > 0) {
650 dev_err(&u132->platform_dev->dev, "device is being removed urb="
651 "%p status=%d\n", urb, urb->status);
652 up(&u132->scheduler_lock);
653 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
654 return;
655 } else if (urb->status == -EINPROGRESS) {
656 struct u132_ring *ring = endp->ring;
657 u8 *u = urb->transfer_buffer + urb->actual_length;
658 u8 *b = buf;
659 int L = len;
660 while (L-- > 0) {
661 *u++ = *b++;
662 }
663 urb->actual_length += len;
664 if ((condition_code == TD_CC_NOERROR) &&
665 (urb->transfer_buffer_length > urb->actual_length)) {
666 endp->toggle_bits = toggle_bits;
667 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
668 1 & toggle_bits);
669 if (urb->actual_length > 0) {
670 int retval;
671 up(&u132->scheduler_lock);
672 retval = edset_single(u132, ring, endp, urb,
673 address, endp->toggle_bits,
674 u132_hcd_interrupt_recv);
675 if (retval == 0) {
676 } else
677 u132_hcd_giveback_urb(u132, endp, urb,
678 retval);
679 } else {
680 ring->in_use = 0;
681 endp->active = 0;
682 endp->jiffies = jiffies +
683 msecs_to_jiffies(urb->interval);
684 u132_ring_cancel_work(u132, ring);
685 u132_ring_queue_work(u132, ring, 0);
686 up(&u132->scheduler_lock);
687 u132_endp_put_kref(u132, endp);
688 }
689 return;
690 } else if ((condition_code == TD_DATAUNDERRUN) &&
691 ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
692 endp->toggle_bits = toggle_bits;
693 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
694 1 & toggle_bits);
695 up(&u132->scheduler_lock);
696 u132_hcd_giveback_urb(u132, endp, urb, 0);
697 return;
698 } else {
699 if (condition_code == TD_CC_NOERROR) {
700 endp->toggle_bits = toggle_bits;
701 usb_settoggle(udev->usb_device, endp->usb_endp,
702 0, 1 & toggle_bits);
703 } else if (condition_code == TD_CC_STALL) {
704 endp->toggle_bits = 0x2;
705 usb_settoggle(udev->usb_device, endp->usb_endp,
706 0, 0);
707 } else {
708 endp->toggle_bits = 0x2;
709 usb_settoggle(udev->usb_device, endp->usb_endp,
710 0, 0);
711 dev_err(&u132->platform_dev->dev, "urb=%p givin"
712 "g back INTERRUPT %s\n", urb,
713 cc_to_text[condition_code]);
714 }
715 up(&u132->scheduler_lock);
716 u132_hcd_giveback_urb(u132, endp, urb,
717 cc_to_error[condition_code]);
718 return;
719 }
720 } else {
721 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
722 "s=%d\n", urb, urb->status);
723 up(&u132->scheduler_lock);
724 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
725 return;
726 }
727}
728
729static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
730 int len, int toggle_bits, int error_count, int condition_code,
731 int repeat_number, int halted, int skipped, int actual, int non_null)
732{
733 struct u132_endp *endp = data;
734 struct u132 *u132 = endp->u132;
735 u8 address = u132->addr[endp->usb_addr].address;
736 down(&u132->scheduler_lock);
737 if (u132->going > 1) {
738 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
739 , u132->going);
740 up(&u132->scheduler_lock);
741 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
742 return;
743 } else if (endp->dequeueing) {
744 endp->dequeueing = 0;
745 up(&u132->scheduler_lock);
746 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
747 return;
748 } else if (u132->going > 0) {
749 dev_err(&u132->platform_dev->dev, "device is being removed urb="
750 "%p status=%d\n", urb, urb->status);
751 up(&u132->scheduler_lock);
752 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
753 return;
754 } else if (urb->status == -EINPROGRESS) {
755 struct u132_ring *ring = endp->ring;
756 urb->actual_length += len;
757 endp->toggle_bits = toggle_bits;
758 if (urb->transfer_buffer_length > urb->actual_length) {
759 int retval;
760 up(&u132->scheduler_lock);
761 retval = edset_output(u132, ring, endp, urb, address,
762 endp->toggle_bits, u132_hcd_bulk_output_sent);
763 if (retval == 0) {
764 } else
765 u132_hcd_giveback_urb(u132, endp, urb, retval);
766 return;
767 } else {
768 up(&u132->scheduler_lock);
769 u132_hcd_giveback_urb(u132, endp, urb, 0);
770 return;
771 }
772 } else {
773 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
774 "s=%d\n", urb, urb->status);
775 up(&u132->scheduler_lock);
776 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
777 return;
778 }
779}
780
781static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
782 int len, int toggle_bits, int error_count, int condition_code,
783 int repeat_number, int halted, int skipped, int actual, int non_null)
784{
785 struct u132_endp *endp = data;
786 struct u132 *u132 = endp->u132;
787 u8 address = u132->addr[endp->usb_addr].address;
788 struct u132_udev *udev = &u132->udev[address];
789 down(&u132->scheduler_lock);
790 if (u132->going > 1) {
791 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
792 , u132->going);
793 up(&u132->scheduler_lock);
794 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
795 return;
796 } else if (endp->dequeueing) {
797 endp->dequeueing = 0;
798 up(&u132->scheduler_lock);
799 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
800 return;
801 } else if (u132->going > 0) {
802 dev_err(&u132->platform_dev->dev, "device is being removed urb="
803 "%p status=%d\n", urb, urb->status);
804 up(&u132->scheduler_lock);
805 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
806 return;
807 } else if (urb->status == -EINPROGRESS) {
808 struct u132_ring *ring = endp->ring;
809 u8 *u = urb->transfer_buffer + urb->actual_length;
810 u8 *b = buf;
811 int L = len;
812 while (L-- > 0) {
813 *u++ = *b++;
814 }
815 urb->actual_length += len;
816 if ((condition_code == TD_CC_NOERROR) &&
817 (urb->transfer_buffer_length > urb->actual_length)) {
818 int retval;
819 endp->toggle_bits = toggle_bits;
820 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
821 1 & toggle_bits);
822 up(&u132->scheduler_lock);
823 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
824 ring->number, endp, urb, address,
825 endp->usb_endp, endp->toggle_bits,
826 u132_hcd_bulk_input_recv);
827 if (retval == 0) {
828 } else
829 u132_hcd_giveback_urb(u132, endp, urb, retval);
830 return;
831 } else if (condition_code == TD_CC_NOERROR) {
832 endp->toggle_bits = toggle_bits;
833 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
834 1 & toggle_bits);
835 up(&u132->scheduler_lock);
836 u132_hcd_giveback_urb(u132, endp, urb,
837 cc_to_error[condition_code]);
838 return;
839 } else if ((condition_code == TD_DATAUNDERRUN) &&
840 ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
841 endp->toggle_bits = toggle_bits;
842 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
843 1 & toggle_bits);
844 up(&u132->scheduler_lock);
845 u132_hcd_giveback_urb(u132, endp, urb, 0);
846 return;
847 } else if (condition_code == TD_DATAUNDERRUN) {
848 endp->toggle_bits = toggle_bits;
849 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
850 1 & toggle_bits);
851 dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
852 ") giving back BULK IN %s\n", urb,
853 cc_to_text[condition_code]);
854 up(&u132->scheduler_lock);
855 u132_hcd_giveback_urb(u132, endp, urb, 0);
856 return;
857 } else if (condition_code == TD_CC_STALL) {
858 endp->toggle_bits = 0x2;
859 usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
860 up(&u132->scheduler_lock);
861 u132_hcd_giveback_urb(u132, endp, urb,
862 cc_to_error[condition_code]);
863 return;
864 } else {
865 endp->toggle_bits = 0x2;
866 usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
867 dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
868 "ULK IN code=%d %s\n", urb, condition_code,
869 cc_to_text[condition_code]);
870 up(&u132->scheduler_lock);
871 u132_hcd_giveback_urb(u132, endp, urb,
872 cc_to_error[condition_code]);
873 return;
874 }
875 } else {
876 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
877 "s=%d\n", urb, urb->status);
878 up(&u132->scheduler_lock);
879 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
880 return;
881 }
882}
883
884static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
885 int len, int toggle_bits, int error_count, int condition_code,
886 int repeat_number, int halted, int skipped, int actual, int non_null)
887{
888 struct u132_endp *endp = data;
889 struct u132 *u132 = endp->u132;
890 down(&u132->scheduler_lock);
891 if (u132->going > 1) {
892 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
893 , u132->going);
894 up(&u132->scheduler_lock);
895 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
896 return;
897 } else if (endp->dequeueing) {
898 endp->dequeueing = 0;
899 up(&u132->scheduler_lock);
900 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
901 return;
902 } else if (u132->going > 0) {
903 dev_err(&u132->platform_dev->dev, "device is being removed urb="
904 "%p status=%d\n", urb, urb->status);
905 up(&u132->scheduler_lock);
906 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
907 return;
908 } else if (urb->status == -EINPROGRESS) {
909 up(&u132->scheduler_lock);
910 u132_hcd_giveback_urb(u132, endp, urb, 0);
911 return;
912 } else {
913 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
914 "s=%d\n", urb, urb->status);
915 up(&u132->scheduler_lock);
916 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
917 return;
918 }
919}
920
921static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
922 int len, int toggle_bits, int error_count, int condition_code,
923 int repeat_number, int halted, int skipped, int actual, int non_null)
924{
925 struct u132_endp *endp = data;
926 struct u132 *u132 = endp->u132;
927 u8 address = u132->addr[endp->usb_addr].address;
928 down(&u132->scheduler_lock);
929 if (u132->going > 1) {
930 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
931 , u132->going);
932 up(&u132->scheduler_lock);
933 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
934 return;
935 } else if (endp->dequeueing) {
936 endp->dequeueing = 0;
937 up(&u132->scheduler_lock);
938 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
939 return;
940 } else if (u132->going > 0) {
941 dev_err(&u132->platform_dev->dev, "device is being removed urb="
942 "%p status=%d\n", urb, urb->status);
943 up(&u132->scheduler_lock);
944 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
945 return;
946 } else if (urb->status == -EINPROGRESS) {
947 struct u132_ring *ring = endp->ring;
948 u8 *u = urb->transfer_buffer;
949 u8 *b = buf;
950 int L = len;
951 while (L-- > 0) {
952 *u++ = *b++;
953 }
954 urb->actual_length = len;
955 if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
956 TD_DATAUNDERRUN) && ((urb->transfer_flags &
957 URB_SHORT_NOT_OK) == 0))) {
958 int retval;
959 up(&u132->scheduler_lock);
960 retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
961 ring->number, endp, urb, address,
962 endp->usb_endp, 0x3,
963 u132_hcd_configure_empty_sent);
964 if (retval == 0) {
965 } else
966 u132_hcd_giveback_urb(u132, endp, urb, retval);
967 return;
968 } else if (condition_code == TD_CC_STALL) {
969 up(&u132->scheduler_lock);
970 dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
971 "NPUT STALL urb %p\n", urb);
972 u132_hcd_giveback_urb(u132, endp, urb,
973 cc_to_error[condition_code]);
974 return;
975 } else {
976 up(&u132->scheduler_lock);
977 dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
978 "PUT %s urb %p\n", cc_to_text[condition_code],
979 urb);
980 u132_hcd_giveback_urb(u132, endp, urb,
981 cc_to_error[condition_code]);
982 return;
983 }
984 } else {
985 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
986 "s=%d\n", urb, urb->status);
987 up(&u132->scheduler_lock);
988 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
989 return;
990 }
991}
992
993static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
994 int len, int toggle_bits, int error_count, int condition_code,
995 int repeat_number, int halted, int skipped, int actual, int non_null)
996{
997 struct u132_endp *endp = data;
998 struct u132 *u132 = endp->u132;
999 down(&u132->scheduler_lock);
1000 if (u132->going > 1) {
1001 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1002 , u132->going);
1003 up(&u132->scheduler_lock);
1004 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1005 return;
1006 } else if (endp->dequeueing) {
1007 endp->dequeueing = 0;
1008 up(&u132->scheduler_lock);
1009 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1010 return;
1011 } else if (u132->going > 0) {
1012 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1013 "%p status=%d\n", urb, urb->status);
1014 up(&u132->scheduler_lock);
1015 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1016 return;
1017 } else if (urb->status == -EINPROGRESS) {
1018 up(&u132->scheduler_lock);
1019 u132_hcd_giveback_urb(u132, endp, urb, 0);
1020 return;
1021 } else {
1022 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1023 "s=%d\n", urb, urb->status);
1024 up(&u132->scheduler_lock);
1025 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1026 return;
1027 }
1028}
1029
1030static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
1031 int len, int toggle_bits, int error_count, int condition_code,
1032 int repeat_number, int halted, int skipped, int actual, int non_null)
1033{
1034 struct u132_endp *endp = data;
1035 struct u132 *u132 = endp->u132;
1036 u8 address = u132->addr[endp->usb_addr].address;
1037 down(&u132->scheduler_lock);
1038 if (u132->going > 1) {
1039 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1040 , u132->going);
1041 up(&u132->scheduler_lock);
1042 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1043 return;
1044 } else if (endp->dequeueing) {
1045 endp->dequeueing = 0;
1046 up(&u132->scheduler_lock);
1047 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1048 return;
1049 } else if (u132->going > 0) {
1050 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1051 "%p status=%d\n", urb, urb->status);
1052 up(&u132->scheduler_lock);
1053 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1054 return;
1055 } else if (urb->status == -EINPROGRESS) {
1056 if (usb_pipein(urb->pipe)) {
1057 int retval;
1058 struct u132_ring *ring = endp->ring;
1059 up(&u132->scheduler_lock);
1060 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
1061 ring->number, endp, urb, address,
1062 endp->usb_endp, 0,
1063 u132_hcd_configure_input_recv);
1064 if (retval == 0) {
1065 } else
1066 u132_hcd_giveback_urb(u132, endp, urb, retval);
1067 return;
1068 } else {
1069 int retval;
1070 struct u132_ring *ring = endp->ring;
1071 up(&u132->scheduler_lock);
1072 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
1073 ring->number, endp, urb, address,
1074 endp->usb_endp, 0,
1075 u132_hcd_configure_empty_recv);
1076 if (retval == 0) {
1077 } else
1078 u132_hcd_giveback_urb(u132, endp, urb, retval);
1079 return;
1080 }
1081 } else {
1082 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1083 "s=%d\n", urb, urb->status);
1084 up(&u132->scheduler_lock);
1085 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1086 return;
1087 }
1088}
1089
1090static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
1091 u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
1092 int repeat_number, int halted, int skipped, int actual, int non_null)
1093{
1094 struct u132_endp *endp = data;
1095 struct u132 *u132 = endp->u132;
1096 u8 address = u132->addr[endp->usb_addr].address;
1097 struct u132_udev *udev = &u132->udev[address];
1098 down(&u132->scheduler_lock);
1099 if (u132->going > 1) {
1100 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1101 , u132->going);
1102 up(&u132->scheduler_lock);
1103 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1104 return;
1105 } else if (endp->dequeueing) {
1106 endp->dequeueing = 0;
1107 up(&u132->scheduler_lock);
1108 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1109 return;
1110 } else if (u132->going > 0) {
1111 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1112 "%p status=%d\n", urb, urb->status);
1113 up(&u132->scheduler_lock);
1114 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1115 return;
1116 } else if (urb->status == -EINPROGRESS) {
1117 u132->addr[0].address = 0;
1118 endp->usb_addr = udev->usb_addr;
1119 up(&u132->scheduler_lock);
1120 u132_hcd_giveback_urb(u132, endp, urb, 0);
1121 return;
1122 } else {
1123 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1124 "s=%d\n", urb, urb->status);
1125 up(&u132->scheduler_lock);
1126 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1127 return;
1128 }
1129}
1130
1131static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
1132 u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
1133 int repeat_number, int halted, int skipped, int actual, int non_null)
1134{
1135 struct u132_endp *endp = data;
1136 struct u132 *u132 = endp->u132;
1137 down(&u132->scheduler_lock);
1138 if (u132->going > 1) {
1139 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1140 , u132->going);
1141 up(&u132->scheduler_lock);
1142 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1143 return;
1144 } else if (endp->dequeueing) {
1145 endp->dequeueing = 0;
1146 up(&u132->scheduler_lock);
1147 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1148 return;
1149 } else if (u132->going > 0) {
1150 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1151 "%p status=%d\n", urb, urb->status);
1152 up(&u132->scheduler_lock);
1153 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1154 return;
1155 } else if (urb->status == -EINPROGRESS) {
1156 int retval;
1157 struct u132_ring *ring = endp->ring;
1158 up(&u132->scheduler_lock);
1159 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
1160 ring->number, endp, urb, 0, endp->usb_endp, 0,
1161 u132_hcd_enumeration_empty_recv);
1162 if (retval == 0) {
1163 } else
1164 u132_hcd_giveback_urb(u132, endp, urb, retval);
1165 return;
1166 } else {
1167 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1168 "s=%d\n", urb, urb->status);
1169 up(&u132->scheduler_lock);
1170 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1171 return;
1172 }
1173}
1174
1175static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
1176 int len, int toggle_bits, int error_count, int condition_code,
1177 int repeat_number, int halted, int skipped, int actual, int non_null)
1178{
1179 struct u132_endp *endp = data;
1180 struct u132 *u132 = endp->u132;
1181 down(&u132->scheduler_lock);
1182 if (u132->going > 1) {
1183 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1184 , u132->going);
1185 up(&u132->scheduler_lock);
1186 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1187 return;
1188 } else if (endp->dequeueing) {
1189 endp->dequeueing = 0;
1190 up(&u132->scheduler_lock);
1191 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1192 return;
1193 } else if (u132->going > 0) {
1194 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1195 "%p status=%d\n", urb, urb->status);
1196 up(&u132->scheduler_lock);
1197 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1198 return;
1199 } else if (urb->status == -EINPROGRESS) {
1200 up(&u132->scheduler_lock);
1201 u132_hcd_giveback_urb(u132, endp, urb, 0);
1202 return;
1203 } else {
1204 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1205 "s=%d\n", urb, urb->status);
1206 up(&u132->scheduler_lock);
1207 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1208 return;
1209 }
1210}
1211
1212static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
1213 int len, int toggle_bits, int error_count, int condition_code,
1214 int repeat_number, int halted, int skipped, int actual, int non_null)
1215{
1216 struct u132_endp *endp = data;
1217 struct u132 *u132 = endp->u132;
1218 u8 address = u132->addr[endp->usb_addr].address;
1219 down(&u132->scheduler_lock);
1220 if (u132->going > 1) {
1221 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1222 , u132->going);
1223 up(&u132->scheduler_lock);
1224 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1225 return;
1226 } else if (endp->dequeueing) {
1227 endp->dequeueing = 0;
1228 up(&u132->scheduler_lock);
1229 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1230 return;
1231 } else if (u132->going > 0) {
1232 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1233 "%p status=%d\n", urb, urb->status);
1234 up(&u132->scheduler_lock);
1235 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1236 return;
1237 } else if (urb->status == -EINPROGRESS) {
1238 int retval;
1239 struct u132_ring *ring = endp->ring;
1240 u8 *u = urb->transfer_buffer;
1241 u8 *b = buf;
1242 int L = len;
1243 while (L-- > 0) {
1244 *u++ = *b++;
1245 }
1246 urb->actual_length = len;
1247 up(&u132->scheduler_lock);
1248 retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
1249 ring->number, endp, urb, address, endp->usb_endp, 0x3,
1250 u132_hcd_initial_empty_sent);
1251 if (retval == 0) {
1252 } else
1253 u132_hcd_giveback_urb(u132, endp, urb, retval);
1254 return;
1255 } else {
1256 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1257 "s=%d\n", urb, urb->status);
1258 up(&u132->scheduler_lock);
1259 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1260 return;
1261 }
1262}
1263
1264static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
1265 int len, int toggle_bits, int error_count, int condition_code,
1266 int repeat_number, int halted, int skipped, int actual, int non_null)
1267{
1268 struct u132_endp *endp = data;
1269 struct u132 *u132 = endp->u132;
1270 u8 address = u132->addr[endp->usb_addr].address;
1271 down(&u132->scheduler_lock);
1272 if (u132->going > 1) {
1273 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1274 , u132->going);
1275 up(&u132->scheduler_lock);
1276 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1277 return;
1278 } else if (endp->dequeueing) {
1279 endp->dequeueing = 0;
1280 up(&u132->scheduler_lock);
1281 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1282 return;
1283 } else if (u132->going > 0) {
1284 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1285 "%p status=%d\n", urb, urb->status);
1286 up(&u132->scheduler_lock);
1287 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1288 return;
1289 } else if (urb->status == -EINPROGRESS) {
1290 int retval;
1291 struct u132_ring *ring = endp->ring;
1292 up(&u132->scheduler_lock);
1293 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
1294 ring->number, endp, urb, address, endp->usb_endp, 0,
1295 u132_hcd_initial_input_recv);
1296 if (retval == 0) {
1297 } else
1298 u132_hcd_giveback_urb(u132, endp, urb, retval);
1299 return;
1300 } else {
1301 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1302 "s=%d\n", urb, urb->status);
1303 up(&u132->scheduler_lock);
1304 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1305 return;
1306 }
1307}
1308
Tony Olechd774efe2006-09-13 11:27:35 +01001309/*
1310* this work function is only executed from the work queue
1311*
1312*/
David Howellsc4028952006-11-22 14:57:56 +00001313static void u132_hcd_ring_work_scheduler(struct work_struct *work)
Tony Olechd774efe2006-09-13 11:27:35 +01001314{
David Howellsc4028952006-11-22 14:57:56 +00001315 struct u132_ring *ring =
1316 container_of(work, struct u132_ring, scheduler.work);
Tony Olechd774efe2006-09-13 11:27:35 +01001317 struct u132 *u132 = ring->u132;
1318 down(&u132->scheduler_lock);
1319 if (ring->in_use) {
1320 up(&u132->scheduler_lock);
1321 u132_ring_put_kref(u132, ring);
1322 return;
1323 } else if (ring->curr_endp) {
1324 struct u132_endp *last_endp = ring->curr_endp;
1325 struct list_head *scan;
1326 struct list_head *head = &last_endp->endp_ring;
1327 unsigned long wakeup = 0;
1328 list_for_each(scan, head) {
1329 struct u132_endp *endp = list_entry(scan,
1330 struct u132_endp, endp_ring);
1331 if (endp->queue_next == endp->queue_last) {
1332 } else if ((endp->delayed == 0)
1333 || time_after_eq(jiffies, endp->jiffies)) {
1334 ring->curr_endp = endp;
1335 u132_endp_cancel_work(u132, last_endp);
1336 u132_endp_queue_work(u132, last_endp, 0);
1337 up(&u132->scheduler_lock);
1338 u132_ring_put_kref(u132, ring);
1339 return;
1340 } else {
1341 unsigned long delta = endp->jiffies - jiffies;
1342 if (delta > wakeup)
1343 wakeup = delta;
1344 }
1345 }
1346 if (last_endp->queue_next == last_endp->queue_last) {
1347 } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
1348 last_endp->jiffies)) {
1349 u132_endp_cancel_work(u132, last_endp);
1350 u132_endp_queue_work(u132, last_endp, 0);
1351 up(&u132->scheduler_lock);
1352 u132_ring_put_kref(u132, ring);
1353 return;
1354 } else {
1355 unsigned long delta = last_endp->jiffies - jiffies;
1356 if (delta > wakeup)
1357 wakeup = delta;
1358 }
1359 if (wakeup > 0) {
1360 u132_ring_requeue_work(u132, ring, wakeup);
1361 up(&u132->scheduler_lock);
1362 return;
1363 } else {
1364 up(&u132->scheduler_lock);
1365 u132_ring_put_kref(u132, ring);
1366 return;
1367 }
1368 } else {
1369 up(&u132->scheduler_lock);
1370 u132_ring_put_kref(u132, ring);
1371 return;
1372 }
1373}
1374
David Howellsc4028952006-11-22 14:57:56 +00001375static void u132_hcd_endp_work_scheduler(struct work_struct *work)
Tony Olechd774efe2006-09-13 11:27:35 +01001376{
1377 struct u132_ring *ring;
David Howellsc4028952006-11-22 14:57:56 +00001378 struct u132_endp *endp =
1379 container_of(work, struct u132_endp, scheduler.work);
Tony Olechd774efe2006-09-13 11:27:35 +01001380 struct u132 *u132 = endp->u132;
1381 down(&u132->scheduler_lock);
1382 ring = endp->ring;
1383 if (endp->edset_flush) {
1384 endp->edset_flush = 0;
1385 if (endp->dequeueing)
1386 usb_ftdi_elan_edset_flush(u132->platform_dev,
1387 ring->number, endp);
1388 up(&u132->scheduler_lock);
1389 u132_endp_put_kref(u132, endp);
1390 return;
1391 } else if (endp->active) {
1392 up(&u132->scheduler_lock);
1393 u132_endp_put_kref(u132, endp);
1394 return;
1395 } else if (ring->in_use) {
1396 up(&u132->scheduler_lock);
1397 u132_endp_put_kref(u132, endp);
1398 return;
1399 } else if (endp->queue_next == endp->queue_last) {
1400 up(&u132->scheduler_lock);
1401 u132_endp_put_kref(u132, endp);
1402 return;
1403 } else if (endp->pipetype == PIPE_INTERRUPT) {
1404 u8 address = u132->addr[endp->usb_addr].address;
1405 if (ring->in_use) {
1406 up(&u132->scheduler_lock);
1407 u132_endp_put_kref(u132, endp);
1408 return;
1409 } else {
1410 int retval;
1411 struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
1412 endp->queue_next];
1413 endp->active = 1;
1414 ring->curr_endp = endp;
1415 ring->in_use = 1;
1416 up(&u132->scheduler_lock);
1417 retval = edset_single(u132, ring, endp, urb, address,
1418 endp->toggle_bits, u132_hcd_interrupt_recv);
1419 if (retval == 0) {
1420 } else
1421 u132_hcd_giveback_urb(u132, endp, urb, retval);
1422 return;
1423 }
1424 } else if (endp->pipetype == PIPE_CONTROL) {
1425 u8 address = u132->addr[endp->usb_addr].address;
1426 if (ring->in_use) {
1427 up(&u132->scheduler_lock);
1428 u132_endp_put_kref(u132, endp);
1429 return;
1430 } else if (address == 0) {
1431 int retval;
1432 struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
1433 endp->queue_next];
1434 endp->active = 1;
1435 ring->curr_endp = endp;
1436 ring->in_use = 1;
1437 up(&u132->scheduler_lock);
1438 retval = edset_setup(u132, ring, endp, urb, address,
1439 0x2, u132_hcd_initial_setup_sent);
1440 if (retval == 0) {
1441 } else
1442 u132_hcd_giveback_urb(u132, endp, urb, retval);
1443 return;
1444 } else if (endp->usb_addr == 0) {
1445 int retval;
1446 struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
1447 endp->queue_next];
1448 endp->active = 1;
1449 ring->curr_endp = endp;
1450 ring->in_use = 1;
1451 up(&u132->scheduler_lock);
1452 retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
1453 u132_hcd_enumeration_address_sent);
1454 if (retval == 0) {
1455 } else
1456 u132_hcd_giveback_urb(u132, endp, urb, retval);
1457 return;
1458 } else {
1459 int retval;
1460 u8 address = u132->addr[endp->usb_addr].address;
1461 struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
1462 endp->queue_next];
1463 endp->active = 1;
1464 ring->curr_endp = endp;
1465 ring->in_use = 1;
1466 up(&u132->scheduler_lock);
1467 retval = edset_setup(u132, ring, endp, urb, address,
1468 0x2, u132_hcd_configure_setup_sent);
1469 if (retval == 0) {
1470 } else
1471 u132_hcd_giveback_urb(u132, endp, urb, retval);
1472 return;
1473 }
1474 } else {
1475 if (endp->input) {
1476 u8 address = u132->addr[endp->usb_addr].address;
1477 if (ring->in_use) {
1478 up(&u132->scheduler_lock);
1479 u132_endp_put_kref(u132, endp);
1480 return;
1481 } else {
1482 int retval;
1483 struct urb *urb = endp->urb_list[
1484 ENDP_QUEUE_MASK & endp->queue_next];
1485 endp->active = 1;
1486 ring->curr_endp = endp;
1487 ring->in_use = 1;
1488 up(&u132->scheduler_lock);
1489 retval = edset_input(u132, ring, endp, urb,
1490 address, endp->toggle_bits,
1491 u132_hcd_bulk_input_recv);
1492 if (retval == 0) {
1493 } else
1494 u132_hcd_giveback_urb(u132, endp, urb,
1495 retval);
1496 return;
1497 }
1498 } else { /* output pipe */
1499 u8 address = u132->addr[endp->usb_addr].address;
1500 if (ring->in_use) {
1501 up(&u132->scheduler_lock);
1502 u132_endp_put_kref(u132, endp);
1503 return;
1504 } else {
1505 int retval;
1506 struct urb *urb = endp->urb_list[
1507 ENDP_QUEUE_MASK & endp->queue_next];
1508 endp->active = 1;
1509 ring->curr_endp = endp;
1510 ring->in_use = 1;
1511 up(&u132->scheduler_lock);
1512 retval = edset_output(u132, ring, endp, urb,
1513 address, endp->toggle_bits,
1514 u132_hcd_bulk_output_sent);
1515 if (retval == 0) {
1516 } else
1517 u132_hcd_giveback_urb(u132, endp, urb,
1518 retval);
1519 return;
1520 }
1521 }
1522 }
1523}
Gabriel C5b570d42007-07-30 12:57:03 +02001524#ifdef CONFIG_PM
Tony Olechd774efe2006-09-13 11:27:35 +01001525
1526static void port_power(struct u132 *u132, int pn, int is_on)
1527{
1528 u132->port[pn].power = is_on;
1529}
1530
Gabriel C5b570d42007-07-30 12:57:03 +02001531#endif
1532
Tony Olechd774efe2006-09-13 11:27:35 +01001533static void u132_power(struct u132 *u132, int is_on)
1534{
1535 struct usb_hcd *hcd = u132_to_hcd(u132)
1536 ; /* hub is inactive unless the port is powered */
1537 if (is_on) {
1538 if (u132->power)
1539 return;
1540 u132->power = 1;
1541 hcd->self.controller->power.power_state = PMSG_ON;
1542 } else {
1543 u132->power = 0;
1544 hcd->state = HC_STATE_HALT;
1545 hcd->self.controller->power.power_state = PMSG_SUSPEND;
1546 }
1547}
1548
1549static int u132_periodic_reinit(struct u132 *u132)
1550{
1551 int retval;
1552 u32 fi = u132->hc_fminterval & 0x03fff;
1553 u32 fit;
1554 u32 fminterval;
1555 retval = u132_read_pcimem(u132, fminterval, &fminterval);
1556 if (retval)
1557 return retval;
1558 fit = fminterval & FIT;
1559 retval = u132_write_pcimem(u132, fminterval,
1560 (fit ^ FIT) | u132->hc_fminterval);
1561 if (retval)
1562 return retval;
1563 retval = u132_write_pcimem(u132, periodicstart,
1564 ((9 *fi) / 10) & 0x3fff);
1565 if (retval)
1566 return retval;
1567 return 0;
1568}
1569
1570static char *hcfs2string(int state)
1571{
1572 switch (state) {
1573 case OHCI_USB_RESET:
1574 return "reset";
1575 case OHCI_USB_RESUME:
1576 return "resume";
1577 case OHCI_USB_OPER:
1578 return "operational";
1579 case OHCI_USB_SUSPEND:
1580 return "suspend";
1581 }
1582 return "?";
1583}
1584
Tony Olechd774efe2006-09-13 11:27:35 +01001585static int u132_init(struct u132 *u132)
1586{
1587 int retval;
1588 u32 control;
1589 u132_disable(u132);
Tony Olech4b873612006-12-06 13:16:22 +00001590 u132->next_statechange = jiffies;
Tony Olechd774efe2006-09-13 11:27:35 +01001591 retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
1592 if (retval)
1593 return retval;
1594 retval = u132_read_pcimem(u132, control, &control);
1595 if (retval)
1596 return retval;
1597 if (u132->num_ports == 0) {
1598 u32 rh_a = -1;
1599 retval = u132_read_pcimem(u132, roothub.a, &rh_a);
1600 if (retval)
1601 return retval;
1602 u132->num_ports = rh_a & RH_A_NDP;
1603 retval = read_roothub_info(u132);
1604 if (retval)
1605 return retval;
1606 }
1607 if (u132->num_ports > MAX_U132_PORTS) {
1608 return -EINVAL;
1609 }
1610 return 0;
1611}
1612
1613
1614/* Start an OHCI controller, set the BUS operational
1615* resets USB and controller
1616* enable interrupts
1617*/
1618static int u132_run(struct u132 *u132)
1619{
1620 int retval;
1621 u32 control;
1622 u32 status;
1623 u32 fminterval;
1624 u32 periodicstart;
1625 u32 cmdstatus;
1626 u32 roothub_a;
1627 int mask = OHCI_INTR_INIT;
1628 int first = u132->hc_fminterval == 0;
1629 int sleep_time = 0;
1630 int reset_timeout = 30; /* ... allow extra time */
1631 u132_disable(u132);
1632 if (first) {
1633 u32 temp;
1634 retval = u132_read_pcimem(u132, fminterval, &temp);
1635 if (retval)
1636 return retval;
1637 u132->hc_fminterval = temp & 0x3fff;
1638 if (u132->hc_fminterval != FI) {
1639 }
1640 u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
1641 }
1642 retval = u132_read_pcimem(u132, control, &u132->hc_control);
1643 if (retval)
1644 return retval;
1645 dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
1646 "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
1647 u132->hc_control);
1648 switch (u132->hc_control & OHCI_CTRL_HCFS) {
1649 case OHCI_USB_OPER:
1650 sleep_time = 0;
1651 break;
1652 case OHCI_USB_SUSPEND:
1653 case OHCI_USB_RESUME:
1654 u132->hc_control &= OHCI_CTRL_RWC;
1655 u132->hc_control |= OHCI_USB_RESUME;
1656 sleep_time = 10;
1657 break;
1658 default:
1659 u132->hc_control &= OHCI_CTRL_RWC;
1660 u132->hc_control |= OHCI_USB_RESET;
1661 sleep_time = 50;
1662 break;
1663 }
1664 retval = u132_write_pcimem(u132, control, u132->hc_control);
1665 if (retval)
1666 return retval;
1667 retval = u132_read_pcimem(u132, control, &control);
1668 if (retval)
1669 return retval;
1670 msleep(sleep_time);
1671 retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
1672 if (retval)
1673 return retval;
1674 if (!(roothub_a & RH_A_NPS)) {
1675 int temp; /* power down each port */
1676 for (temp = 0; temp < u132->num_ports; temp++) {
1677 retval = u132_write_pcimem(u132,
1678 roothub.portstatus[temp], RH_PS_LSDA);
1679 if (retval)
1680 return retval;
1681 }
1682 }
1683 retval = u132_read_pcimem(u132, control, &control);
1684 if (retval)
1685 return retval;
1686 retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
1687 if (retval)
1688 return retval;
Tony Olech4b873612006-12-06 13:16:22 +00001689 retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
Tony Olechd774efe2006-09-13 11:27:35 +01001690 if (retval)
1691 return retval;
1692 extra:{
1693 retval = u132_read_pcimem(u132, cmdstatus, &status);
1694 if (retval)
1695 return retval;
1696 if (0 != (status & OHCI_HCR)) {
1697 if (--reset_timeout == 0) {
1698 dev_err(&u132->platform_dev->dev, "USB HC reset"
1699 " timed out!\n");
1700 return -ENODEV;
1701 } else {
1702 msleep(5);
1703 goto extra;
1704 }
1705 }
1706 }
1707 if (u132->flags & OHCI_QUIRK_INITRESET) {
1708 retval = u132_write_pcimem(u132, control, u132->hc_control);
1709 if (retval)
1710 return retval;
1711 retval = u132_read_pcimem(u132, control, &control);
1712 if (retval)
1713 return retval;
1714 }
1715 retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
1716 if (retval)
1717 return retval;
1718 retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
1719 if (retval)
1720 return retval;
1721 retval = u132_write_pcimem(u132, hcca, 0x00000000);
1722 if (retval)
1723 return retval;
1724 retval = u132_periodic_reinit(u132);
1725 if (retval)
1726 return retval;
1727 retval = u132_read_pcimem(u132, fminterval, &fminterval);
1728 if (retval)
1729 return retval;
1730 retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
1731 if (retval)
1732 return retval;
1733 if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
1734 if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
1735 u132->flags |= OHCI_QUIRK_INITRESET;
1736 goto retry;
1737 } else
1738 dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
1739 "\n", fminterval, periodicstart);
1740 } /* start controller operations */
1741 u132->hc_control &= OHCI_CTRL_RWC;
1742 u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
1743 retval = u132_write_pcimem(u132, control, u132->hc_control);
1744 if (retval)
1745 return retval;
Tony Olech4b873612006-12-06 13:16:22 +00001746 retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
Tony Olechd774efe2006-09-13 11:27:35 +01001747 if (retval)
1748 return retval;
1749 retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
1750 if (retval)
1751 return retval;
1752 retval = u132_read_pcimem(u132, control, &control);
1753 if (retval)
1754 return retval;
1755 u132_to_hcd(u132)->state = HC_STATE_RUNNING;
1756 retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
1757 if (retval)
1758 return retval;
1759 retval = u132_write_pcimem(u132, intrstatus, mask);
1760 if (retval)
1761 return retval;
1762 retval = u132_write_pcimem(u132, intrdisable,
1763 OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
1764 OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
1765 OHCI_INTR_SO);
1766 if (retval)
1767 return retval; /* handle root hub init quirks ... */
1768 retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
1769 if (retval)
1770 return retval;
1771 roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
1772 if (u132->flags & OHCI_QUIRK_SUPERIO) {
1773 roothub_a |= RH_A_NOCP;
1774 roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
1775 retval = u132_write_pcimem(u132, roothub.a, roothub_a);
1776 if (retval)
1777 return retval;
1778 } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
1779 roothub_a |= RH_A_NPS;
1780 retval = u132_write_pcimem(u132, roothub.a, roothub_a);
1781 if (retval)
1782 return retval;
1783 }
1784 retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
1785 if (retval)
1786 return retval;
1787 retval = u132_write_pcimem(u132, roothub.b,
1788 (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
1789 if (retval)
1790 return retval;
1791 retval = u132_read_pcimem(u132, control, &control);
1792 if (retval)
1793 return retval;
1794 mdelay((roothub_a >> 23) & 0x1fe);
1795 u132_to_hcd(u132)->state = HC_STATE_RUNNING;
1796 return 0;
1797}
1798
1799static void u132_hcd_stop(struct usb_hcd *hcd)
1800{
1801 struct u132 *u132 = hcd_to_u132(hcd);
1802 if (u132->going > 1) {
Tony Olech4b873612006-12-06 13:16:22 +00001803 dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
1804 "een removed %d\n", u132, hcd, u132->going);
Tony Olechd774efe2006-09-13 11:27:35 +01001805 } else if (u132->going > 0) {
1806 dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
1807 "ed\n", hcd);
1808 } else {
1809 down(&u132->sw_lock);
1810 msleep(100);
1811 u132_power(u132, 0);
1812 up(&u132->sw_lock);
1813 }
1814}
1815
1816static int u132_hcd_start(struct usb_hcd *hcd)
1817{
1818 struct u132 *u132 = hcd_to_u132(hcd);
1819 if (u132->going > 1) {
1820 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1821 , u132->going);
1822 return -ENODEV;
1823 } else if (u132->going > 0) {
1824 dev_err(&u132->platform_dev->dev, "device is being removed\n");
1825 return -ESHUTDOWN;
1826 } else if (hcd->self.controller) {
1827 int retval;
1828 struct platform_device *pdev =
1829 to_platform_device(hcd->self.controller);
1830 u16 vendor = ((struct u132_platform_data *)
1831 (pdev->dev.platform_data))->vendor;
1832 u16 device = ((struct u132_platform_data *)
1833 (pdev->dev.platform_data))->device;
1834 down(&u132->sw_lock);
1835 msleep(10);
1836 if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
1837 u132->flags = OHCI_QUIRK_AMD756;
1838 } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
1839 dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
1840 "ounds unavailable\n");
1841 } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
1842 u132->flags |= OHCI_QUIRK_ZFMICRO;
1843 retval = u132_run(u132);
1844 if (retval) {
1845 u132_disable(u132);
1846 u132->going = 1;
1847 }
1848 msleep(100);
1849 up(&u132->sw_lock);
1850 return retval;
1851 } else {
1852 dev_err(&u132->platform_dev->dev, "platform_device missing\n");
1853 return -ENODEV;
1854 }
1855}
1856
1857static int u132_hcd_reset(struct usb_hcd *hcd)
1858{
1859 struct u132 *u132 = hcd_to_u132(hcd);
1860 if (u132->going > 1) {
1861 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1862 , u132->going);
1863 return -ENODEV;
1864 } else if (u132->going > 0) {
1865 dev_err(&u132->platform_dev->dev, "device is being removed\n");
1866 return -ESHUTDOWN;
1867 } else {
1868 int retval;
1869 down(&u132->sw_lock);
1870 retval = u132_init(u132);
1871 if (retval) {
1872 u132_disable(u132);
1873 u132->going = 1;
1874 }
1875 up(&u132->sw_lock);
1876 return retval;
1877 }
1878}
1879
1880static int create_endpoint_and_queue_int(struct u132 *u132,
Alan Sterne9df41c2007-08-08 11:48:02 -04001881 struct u132_udev *udev, struct urb *urb,
Tony Olechd774efe2006-09-13 11:27:35 +01001882 struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
1883 gfp_t mem_flags)
1884{
1885 struct u132_ring *ring;
1886 unsigned long irqs;
Alan Sterne9df41c2007-08-08 11:48:02 -04001887 int rc;
1888 u8 endp_number;
1889 struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
1890
Tony Olechd774efe2006-09-13 11:27:35 +01001891 if (!endp) {
1892 return -ENOMEM;
1893 }
Alan Sterne9df41c2007-08-08 11:48:02 -04001894
1895 spin_lock_init(&endp->queue_lock.slock);
1896 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
1897 rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
1898 if (rc) {
1899 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
1900 kfree(endp);
1901 return rc;
1902 }
1903
1904 endp_number = ++u132->num_endpoints;
1905 urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
David Howellsc4028952006-11-22 14:57:56 +00001906 INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
Tony Olechd774efe2006-09-13 11:27:35 +01001907 INIT_LIST_HEAD(&endp->urb_more);
1908 ring = endp->ring = &u132->ring[0];
1909 if (ring->curr_endp) {
1910 list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
1911 } else {
1912 INIT_LIST_HEAD(&endp->endp_ring);
1913 ring->curr_endp = endp;
1914 }
1915 ring->length += 1;
1916 endp->dequeueing = 0;
1917 endp->edset_flush = 0;
1918 endp->active = 0;
1919 endp->delayed = 0;
1920 endp->endp_number = endp_number;
1921 endp->u132 = u132;
Alan Sterne9df41c2007-08-08 11:48:02 -04001922 endp->hep = urb->ep;
Tony Olechd774efe2006-09-13 11:27:35 +01001923 endp->pipetype = usb_pipetype(urb->pipe);
1924 u132_endp_init_kref(u132, endp);
1925 if (usb_pipein(urb->pipe)) {
1926 endp->toggle_bits = 0x2;
1927 usb_settoggle(udev->usb_device, usb_endp, 0, 0);
1928 endp->input = 1;
1929 endp->output = 0;
1930 udev->endp_number_in[usb_endp] = endp_number;
1931 u132_udev_get_kref(u132, udev);
1932 } else {
1933 endp->toggle_bits = 0x2;
1934 usb_settoggle(udev->usb_device, usb_endp, 1, 0);
1935 endp->input = 0;
1936 endp->output = 1;
1937 udev->endp_number_out[usb_endp] = endp_number;
1938 u132_udev_get_kref(u132, udev);
1939 }
1940 urb->hcpriv = u132;
Tony Olechd774efe2006-09-13 11:27:35 +01001941 endp->delayed = 1;
1942 endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
1943 endp->udev_number = address;
1944 endp->usb_addr = usb_addr;
1945 endp->usb_endp = usb_endp;
1946 endp->queue_size = 1;
1947 endp->queue_last = 0;
1948 endp->queue_next = 0;
1949 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
1950 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
1951 u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
1952 return 0;
1953}
1954
Alan Sterne9df41c2007-08-08 11:48:02 -04001955static int queue_int_on_old_endpoint(struct u132 *u132,
1956 struct u132_udev *udev, struct urb *urb,
Tony Olechd774efe2006-09-13 11:27:35 +01001957 struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
1958 u8 usb_endp, u8 address)
1959{
1960 urb->hcpriv = u132;
1961 endp->delayed = 1;
1962 endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
1963 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
1964 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
1965 } else {
1966 struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
1967 GFP_ATOMIC);
1968 if (urbq == NULL) {
1969 endp->queue_size -= 1;
1970 return -ENOMEM;
1971 } else {
1972 list_add_tail(&urbq->urb_more, &endp->urb_more);
1973 urbq->urb = urb;
1974 }
1975 }
1976 return 0;
1977}
1978
1979static int create_endpoint_and_queue_bulk(struct u132 *u132,
Alan Sterne9df41c2007-08-08 11:48:02 -04001980 struct u132_udev *udev, struct urb *urb,
Tony Olechd774efe2006-09-13 11:27:35 +01001981 struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
1982 gfp_t mem_flags)
1983{
1984 int ring_number;
1985 struct u132_ring *ring;
1986 unsigned long irqs;
Alan Sterne9df41c2007-08-08 11:48:02 -04001987 int rc;
1988 u8 endp_number;
1989 struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
1990
Tony Olechd774efe2006-09-13 11:27:35 +01001991 if (!endp) {
1992 return -ENOMEM;
1993 }
Alan Sterne9df41c2007-08-08 11:48:02 -04001994
1995 spin_lock_init(&endp->queue_lock.slock);
1996 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
1997 rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
1998 if (rc) {
1999 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2000 kfree(endp);
2001 return rc;
2002 }
2003
2004 endp_number = ++u132->num_endpoints;
2005 urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
David Howellsc4028952006-11-22 14:57:56 +00002006 INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
Tony Olechd774efe2006-09-13 11:27:35 +01002007 INIT_LIST_HEAD(&endp->urb_more);
2008 endp->dequeueing = 0;
2009 endp->edset_flush = 0;
2010 endp->active = 0;
2011 endp->delayed = 0;
2012 endp->endp_number = endp_number;
2013 endp->u132 = u132;
Alan Sterne9df41c2007-08-08 11:48:02 -04002014 endp->hep = urb->ep;
Tony Olechd774efe2006-09-13 11:27:35 +01002015 endp->pipetype = usb_pipetype(urb->pipe);
2016 u132_endp_init_kref(u132, endp);
2017 if (usb_pipein(urb->pipe)) {
2018 endp->toggle_bits = 0x2;
2019 usb_settoggle(udev->usb_device, usb_endp, 0, 0);
2020 ring_number = 3;
2021 endp->input = 1;
2022 endp->output = 0;
2023 udev->endp_number_in[usb_endp] = endp_number;
2024 u132_udev_get_kref(u132, udev);
2025 } else {
2026 endp->toggle_bits = 0x2;
2027 usb_settoggle(udev->usb_device, usb_endp, 1, 0);
2028 ring_number = 2;
2029 endp->input = 0;
2030 endp->output = 1;
2031 udev->endp_number_out[usb_endp] = endp_number;
2032 u132_udev_get_kref(u132, udev);
2033 }
2034 ring = endp->ring = &u132->ring[ring_number - 1];
2035 if (ring->curr_endp) {
2036 list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
2037 } else {
2038 INIT_LIST_HEAD(&endp->endp_ring);
2039 ring->curr_endp = endp;
2040 }
2041 ring->length += 1;
2042 urb->hcpriv = u132;
Tony Olechd774efe2006-09-13 11:27:35 +01002043 endp->udev_number = address;
2044 endp->usb_addr = usb_addr;
2045 endp->usb_endp = usb_endp;
2046 endp->queue_size = 1;
2047 endp->queue_last = 0;
2048 endp->queue_next = 0;
2049 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
2050 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2051 u132_endp_queue_work(u132, endp, 0);
2052 return 0;
2053}
2054
2055static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
Alan Sterne9df41c2007-08-08 11:48:02 -04002056 struct urb *urb,
Tony Olechd774efe2006-09-13 11:27:35 +01002057 struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
2058 u8 usb_endp, u8 address)
2059{
2060 urb->hcpriv = u132;
2061 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
2062 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
2063 } else {
2064 struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
2065 GFP_ATOMIC);
2066 if (urbq == NULL) {
2067 endp->queue_size -= 1;
2068 return -ENOMEM;
2069 } else {
2070 list_add_tail(&urbq->urb_more, &endp->urb_more);
2071 urbq->urb = urb;
2072 }
2073 }
2074 return 0;
2075}
2076
2077static int create_endpoint_and_queue_control(struct u132 *u132,
Alan Sterne9df41c2007-08-08 11:48:02 -04002078 struct urb *urb,
Tony Olechd774efe2006-09-13 11:27:35 +01002079 struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
2080 gfp_t mem_flags)
2081{
2082 struct u132_ring *ring;
Alan Sterne9df41c2007-08-08 11:48:02 -04002083 unsigned long irqs;
2084 int rc;
2085 u8 endp_number;
2086 struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
2087
Tony Olechd774efe2006-09-13 11:27:35 +01002088 if (!endp) {
2089 return -ENOMEM;
2090 }
Alan Sterne9df41c2007-08-08 11:48:02 -04002091
2092 spin_lock_init(&endp->queue_lock.slock);
2093 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
2094 rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
2095 if (rc) {
2096 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2097 kfree(endp);
2098 return rc;
2099 }
2100
2101 endp_number = ++u132->num_endpoints;
2102 urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
David Howellsc4028952006-11-22 14:57:56 +00002103 INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
Tony Olechd774efe2006-09-13 11:27:35 +01002104 INIT_LIST_HEAD(&endp->urb_more);
2105 ring = endp->ring = &u132->ring[0];
2106 if (ring->curr_endp) {
2107 list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
2108 } else {
2109 INIT_LIST_HEAD(&endp->endp_ring);
2110 ring->curr_endp = endp;
2111 }
2112 ring->length += 1;
2113 endp->dequeueing = 0;
2114 endp->edset_flush = 0;
2115 endp->active = 0;
2116 endp->delayed = 0;
2117 endp->endp_number = endp_number;
2118 endp->u132 = u132;
Alan Sterne9df41c2007-08-08 11:48:02 -04002119 endp->hep = urb->ep;
Tony Olechd774efe2006-09-13 11:27:35 +01002120 u132_endp_init_kref(u132, endp);
2121 u132_endp_get_kref(u132, endp);
2122 if (usb_addr == 0) {
Tony Olechd774efe2006-09-13 11:27:35 +01002123 u8 address = u132->addr[usb_addr].address;
2124 struct u132_udev *udev = &u132->udev[address];
2125 endp->udev_number = address;
2126 endp->usb_addr = usb_addr;
2127 endp->usb_endp = usb_endp;
2128 endp->input = 1;
2129 endp->output = 1;
2130 endp->pipetype = usb_pipetype(urb->pipe);
2131 u132_udev_init_kref(u132, udev);
2132 u132_udev_get_kref(u132, udev);
2133 udev->endp_number_in[usb_endp] = endp_number;
2134 udev->endp_number_out[usb_endp] = endp_number;
2135 urb->hcpriv = u132;
Tony Olechd774efe2006-09-13 11:27:35 +01002136 endp->queue_size = 1;
2137 endp->queue_last = 0;
2138 endp->queue_next = 0;
2139 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
2140 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2141 u132_endp_queue_work(u132, endp, 0);
2142 return 0;
2143 } else { /*(usb_addr > 0) */
Tony Olechd774efe2006-09-13 11:27:35 +01002144 u8 address = u132->addr[usb_addr].address;
2145 struct u132_udev *udev = &u132->udev[address];
2146 endp->udev_number = address;
2147 endp->usb_addr = usb_addr;
2148 endp->usb_endp = usb_endp;
2149 endp->input = 1;
2150 endp->output = 1;
2151 endp->pipetype = usb_pipetype(urb->pipe);
2152 u132_udev_get_kref(u132, udev);
2153 udev->enumeration = 2;
2154 udev->endp_number_in[usb_endp] = endp_number;
2155 udev->endp_number_out[usb_endp] = endp_number;
2156 urb->hcpriv = u132;
Tony Olechd774efe2006-09-13 11:27:35 +01002157 endp->queue_size = 1;
2158 endp->queue_last = 0;
2159 endp->queue_next = 0;
2160 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
2161 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2162 u132_endp_queue_work(u132, endp, 0);
2163 return 0;
2164 }
2165}
2166
2167static int queue_control_on_old_endpoint(struct u132 *u132,
Alan Sterne9df41c2007-08-08 11:48:02 -04002168 struct urb *urb,
Tony Olechd774efe2006-09-13 11:27:35 +01002169 struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
2170 u8 usb_endp)
2171{
2172 if (usb_addr == 0) {
2173 if (usb_pipein(urb->pipe)) {
2174 urb->hcpriv = u132;
2175 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
2176 endp->urb_list[ENDP_QUEUE_MASK &
2177 endp->queue_last++] = urb;
2178 } else {
2179 struct u132_urbq *urbq =
2180 kmalloc(sizeof(struct u132_urbq),
2181 GFP_ATOMIC);
2182 if (urbq == NULL) {
2183 endp->queue_size -= 1;
2184 return -ENOMEM;
2185 } else {
2186 list_add_tail(&urbq->urb_more,
2187 &endp->urb_more);
2188 urbq->urb = urb;
2189 }
2190 }
2191 return 0;
2192 } else { /* usb_pipeout(urb->pipe) */
2193 struct u132_addr *addr = &u132->addr[usb_dev->devnum];
2194 int I = MAX_U132_UDEVS;
2195 int i = 0;
2196 while (--I > 0) {
2197 struct u132_udev *udev = &u132->udev[++i];
2198 if (udev->usb_device) {
2199 continue;
2200 } else {
2201 udev->enumeration = 1;
2202 u132->addr[0].address = i;
2203 endp->udev_number = i;
2204 udev->udev_number = i;
2205 udev->usb_addr = usb_dev->devnum;
2206 u132_udev_init_kref(u132, udev);
2207 udev->endp_number_in[usb_endp] =
2208 endp->endp_number;
2209 u132_udev_get_kref(u132, udev);
2210 udev->endp_number_out[usb_endp] =
2211 endp->endp_number;
2212 udev->usb_device = usb_dev;
2213 ((u8 *) (urb->setup_packet))[2] =
2214 addr->address = i;
2215 u132_udev_get_kref(u132, udev);
2216 break;
2217 }
2218 }
2219 if (I == 0) {
2220 dev_err(&u132->platform_dev->dev, "run out of d"
2221 "evice space\n");
2222 return -EINVAL;
2223 }
2224 urb->hcpriv = u132;
2225 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
2226 endp->urb_list[ENDP_QUEUE_MASK &
2227 endp->queue_last++] = urb;
2228 } else {
2229 struct u132_urbq *urbq =
2230 kmalloc(sizeof(struct u132_urbq),
2231 GFP_ATOMIC);
2232 if (urbq == NULL) {
2233 endp->queue_size -= 1;
2234 return -ENOMEM;
2235 } else {
2236 list_add_tail(&urbq->urb_more,
2237 &endp->urb_more);
2238 urbq->urb = urb;
2239 }
2240 }
2241 return 0;
2242 }
2243 } else { /*(usb_addr > 0) */
2244 u8 address = u132->addr[usb_addr].address;
2245 struct u132_udev *udev = &u132->udev[address];
2246 urb->hcpriv = u132;
2247 if (udev->enumeration == 2) {
2248 } else
2249 udev->enumeration = 2;
2250 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
2251 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
2252 urb;
2253 } else {
2254 struct u132_urbq *urbq =
2255 kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
2256 if (urbq == NULL) {
2257 endp->queue_size -= 1;
2258 return -ENOMEM;
2259 } else {
2260 list_add_tail(&urbq->urb_more, &endp->urb_more);
2261 urbq->urb = urb;
2262 }
2263 }
2264 return 0;
2265 }
2266}
2267
Alan Sterne9df41c2007-08-08 11:48:02 -04002268static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
2269 gfp_t mem_flags)
Tony Olechd774efe2006-09-13 11:27:35 +01002270{
2271 struct u132 *u132 = hcd_to_u132(hcd);
2272 if (irqs_disabled()) {
2273 if (__GFP_WAIT & mem_flags) {
2274 printk(KERN_ERR "invalid context for function that migh"
2275 "t sleep\n");
2276 return -EINVAL;
2277 }
2278 }
2279 if (u132->going > 1) {
2280 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2281 , u132->going);
2282 return -ENODEV;
2283 } else if (u132->going > 0) {
2284 dev_err(&u132->platform_dev->dev, "device is being removed urb="
2285 "%p status=%d\n", urb, urb->status);
2286 return -ESHUTDOWN;
2287 } else {
2288 u8 usb_addr = usb_pipedevice(urb->pipe);
2289 u8 usb_endp = usb_pipeendpoint(urb->pipe);
2290 struct usb_device *usb_dev = urb->dev;
2291 if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
2292 u8 address = u132->addr[usb_addr].address;
2293 struct u132_udev *udev = &u132->udev[address];
Alan Sterne9df41c2007-08-08 11:48:02 -04002294 struct u132_endp *endp = urb->ep->hcpriv;
Tony Olechd774efe2006-09-13 11:27:35 +01002295 urb->actual_length = 0;
2296 if (endp) {
2297 unsigned long irqs;
2298 int retval;
2299 spin_lock_irqsave(&endp->queue_lock.slock,
2300 irqs);
Alan Sterne9df41c2007-08-08 11:48:02 -04002301 retval = usb_hcd_link_urb_to_ep(hcd, urb);
2302 if (retval == 0) {
2303 retval = queue_int_on_old_endpoint(
2304 u132, udev, urb,
2305 usb_dev, endp,
2306 usb_addr, usb_endp,
2307 address);
2308 if (retval)
2309 usb_hcd_unlink_urb_from_ep(
2310 hcd, urb);
2311 }
Tony Olechd774efe2006-09-13 11:27:35 +01002312 spin_unlock_irqrestore(&endp->queue_lock.slock,
2313 irqs);
2314 if (retval) {
2315 return retval;
2316 } else {
2317 u132_endp_queue_work(u132, endp,
2318 msecs_to_jiffies(urb->interval))
2319 ;
2320 return 0;
2321 }
2322 } else if (u132->num_endpoints == MAX_U132_ENDPS) {
2323 return -EINVAL;
2324 } else { /*(endp == NULL) */
2325 return create_endpoint_and_queue_int(u132, udev,
Alan Sterne9df41c2007-08-08 11:48:02 -04002326 urb, usb_dev, usb_addr,
2327 usb_endp, address, mem_flags);
Tony Olechd774efe2006-09-13 11:27:35 +01002328 }
2329 } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
2330 dev_err(&u132->platform_dev->dev, "the hardware does no"
2331 "t support PIPE_ISOCHRONOUS\n");
2332 return -EINVAL;
2333 } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
2334 u8 address = u132->addr[usb_addr].address;
2335 struct u132_udev *udev = &u132->udev[address];
Alan Sterne9df41c2007-08-08 11:48:02 -04002336 struct u132_endp *endp = urb->ep->hcpriv;
Tony Olechd774efe2006-09-13 11:27:35 +01002337 urb->actual_length = 0;
2338 if (endp) {
2339 unsigned long irqs;
2340 int retval;
2341 spin_lock_irqsave(&endp->queue_lock.slock,
2342 irqs);
Alan Sterne9df41c2007-08-08 11:48:02 -04002343 retval = usb_hcd_link_urb_to_ep(hcd, urb);
2344 if (retval == 0) {
2345 retval = queue_bulk_on_old_endpoint(
2346 u132, udev, urb,
2347 usb_dev, endp,
2348 usb_addr, usb_endp,
2349 address);
2350 if (retval)
2351 usb_hcd_unlink_urb_from_ep(
2352 hcd, urb);
2353 }
Tony Olechd774efe2006-09-13 11:27:35 +01002354 spin_unlock_irqrestore(&endp->queue_lock.slock,
2355 irqs);
2356 if (retval) {
2357 return retval;
2358 } else {
2359 u132_endp_queue_work(u132, endp, 0);
2360 return 0;
2361 }
2362 } else if (u132->num_endpoints == MAX_U132_ENDPS) {
2363 return -EINVAL;
2364 } else
2365 return create_endpoint_and_queue_bulk(u132,
Alan Sterne9df41c2007-08-08 11:48:02 -04002366 udev, urb, usb_dev, usb_addr,
Tony Olechd774efe2006-09-13 11:27:35 +01002367 usb_endp, address, mem_flags);
2368 } else {
Alan Sterne9df41c2007-08-08 11:48:02 -04002369 struct u132_endp *endp = urb->ep->hcpriv;
Tony Olechd774efe2006-09-13 11:27:35 +01002370 u16 urb_size = 8;
2371 u8 *b = urb->setup_packet;
2372 int i = 0;
2373 char data[30 *3 + 4];
2374 char *d = data;
2375 int m = (sizeof(data) - 1) / 3;
2376 int l = 0;
2377 data[0] = 0;
2378 while (urb_size-- > 0) {
2379 if (i > m) {
2380 } else if (i++ < m) {
2381 int w = sprintf(d, " %02X", *b++);
2382 d += w;
2383 l += w;
2384 } else
2385 d += sprintf(d, " ..");
2386 }
2387 if (endp) {
2388 unsigned long irqs;
2389 int retval;
2390 spin_lock_irqsave(&endp->queue_lock.slock,
2391 irqs);
Alan Sterne9df41c2007-08-08 11:48:02 -04002392 retval = usb_hcd_link_urb_to_ep(hcd, urb);
2393 if (retval == 0) {
2394 retval = queue_control_on_old_endpoint(
2395 u132, urb, usb_dev,
2396 endp, usb_addr,
2397 usb_endp);
2398 if (retval)
2399 usb_hcd_unlink_urb_from_ep(
2400 hcd, urb);
2401 }
Tony Olechd774efe2006-09-13 11:27:35 +01002402 spin_unlock_irqrestore(&endp->queue_lock.slock,
2403 irqs);
2404 if (retval) {
2405 return retval;
2406 } else {
2407 u132_endp_queue_work(u132, endp, 0);
2408 return 0;
2409 }
2410 } else if (u132->num_endpoints == MAX_U132_ENDPS) {
2411 return -EINVAL;
2412 } else
2413 return create_endpoint_and_queue_control(u132,
Alan Sterne9df41c2007-08-08 11:48:02 -04002414 urb, usb_dev, usb_addr, usb_endp,
Tony Olechd774efe2006-09-13 11:27:35 +01002415 mem_flags);
2416 }
2417 }
2418}
2419
2420static int dequeue_from_overflow_chain(struct u132 *u132,
2421 struct u132_endp *endp, struct urb *urb)
2422{
2423 struct list_head *scan;
2424 struct list_head *head = &endp->urb_more;
2425 list_for_each(scan, head) {
2426 struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
2427 urb_more);
2428 if (urbq->urb == urb) {
2429 struct usb_hcd *hcd = u132_to_hcd(u132);
2430 list_del(scan);
2431 endp->queue_size -= 1;
2432 urb->error_count = 0;
2433 urb->hcpriv = NULL;
David Howells7d12e782006-10-05 14:55:46 +01002434 usb_hcd_giveback_urb(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +01002435 return 0;
2436 } else
2437 continue;
2438 }
2439 dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
2440 "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
2441 "\n", urb, endp->endp_number, endp, endp->ring->number,
2442 endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
2443 endp->usb_endp, endp->usb_addr, endp->queue_size,
2444 endp->queue_next, endp->queue_last);
2445 return -EINVAL;
2446}
2447
2448static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
Alan Sterne9df41c2007-08-08 11:48:02 -04002449 struct urb *urb, int status)
Tony Olechd774efe2006-09-13 11:27:35 +01002450{
2451 unsigned long irqs;
Alan Sterne9df41c2007-08-08 11:48:02 -04002452 int rc;
2453
Tony Olechd774efe2006-09-13 11:27:35 +01002454 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
Alan Sterne9df41c2007-08-08 11:48:02 -04002455 rc = usb_hcd_check_unlink_urb(u132_to_hcd(u132), urb, status);
2456 if (rc) {
2457 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2458 return rc;
2459 }
Tony Olechd774efe2006-09-13 11:27:35 +01002460 if (endp->queue_size == 0) {
2461 dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
2462 "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
2463 endp->endp_number, endp, endp->ring->number,
2464 endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
2465 endp->usb_endp, endp->usb_addr);
2466 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2467 return -EINVAL;
2468 }
2469 if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
2470 if (endp->active) {
2471 endp->dequeueing = 1;
2472 endp->edset_flush = 1;
2473 u132_endp_queue_work(u132, endp, 0);
2474 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2475 urb->hcpriv = NULL;
2476 return 0;
2477 } else {
2478 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2479 u132_hcd_abandon_urb(u132, endp, urb, urb->status);
2480 return 0;
2481 }
2482 } else {
2483 u16 queue_list = 0;
2484 u16 queue_size = endp->queue_size;
2485 u16 queue_scan = endp->queue_next;
2486 struct urb **urb_slot = NULL;
2487 while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
2488 if (urb == endp->urb_list[ENDP_QUEUE_MASK &
2489 ++queue_scan]) {
2490 urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
2491 queue_scan];
2492 break;
2493 } else
2494 continue;
2495 }
2496 while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
2497 *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
2498 ++queue_scan];
2499 urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
2500 queue_scan];
2501 }
2502 if (urb_slot) {
2503 struct usb_hcd *hcd = u132_to_hcd(u132);
Alan Sterne9df41c2007-08-08 11:48:02 -04002504
2505 usb_hcd_unlink_urb_from_ep(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +01002506 endp->queue_size -= 1;
2507 if (list_empty(&endp->urb_more)) {
2508 spin_unlock_irqrestore(&endp->queue_lock.slock,
2509 irqs);
2510 } else {
2511 struct list_head *next = endp->urb_more.next;
2512 struct u132_urbq *urbq = list_entry(next,
2513 struct u132_urbq, urb_more);
2514 list_del(next);
2515 *urb_slot = urbq->urb;
2516 spin_unlock_irqrestore(&endp->queue_lock.slock,
2517 irqs);
2518 kfree(urbq);
2519 } urb->error_count = 0;
2520 urb->hcpriv = NULL;
David Howells7d12e782006-10-05 14:55:46 +01002521 usb_hcd_giveback_urb(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +01002522 return 0;
2523 } else if (list_empty(&endp->urb_more)) {
2524 dev_err(&u132->platform_dev->dev, "urb=%p not found in "
2525 "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
2526 "=%d size=%d next=%04X last=%04X\n", urb,
2527 endp->endp_number, endp, endp->ring->number,
2528 endp->input ? 'I' : ' ',
2529 endp->output ? 'O' : ' ', endp->usb_endp,
2530 endp->usb_addr, endp->queue_size,
2531 endp->queue_next, endp->queue_last);
2532 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2533 return -EINVAL;
2534 } else {
Alan Sterne9df41c2007-08-08 11:48:02 -04002535 int retval;
2536
2537 usb_hcd_unlink_urb_from_ep(u132_to_hcd(u132), urb);
2538 retval = dequeue_from_overflow_chain(u132, endp,
Tony Olechd774efe2006-09-13 11:27:35 +01002539 urb);
2540 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2541 return retval;
2542 }
2543 }
2544}
2545
Alan Sterne9df41c2007-08-08 11:48:02 -04002546static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
Tony Olechd774efe2006-09-13 11:27:35 +01002547{
2548 struct u132 *u132 = hcd_to_u132(hcd);
2549 if (u132->going > 2) {
2550 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2551 , u132->going);
2552 return -ENODEV;
2553 } else {
2554 u8 usb_addr = usb_pipedevice(urb->pipe);
2555 u8 usb_endp = usb_pipeendpoint(urb->pipe);
2556 u8 address = u132->addr[usb_addr].address;
2557 struct u132_udev *udev = &u132->udev[address];
2558 if (usb_pipein(urb->pipe)) {
2559 u8 endp_number = udev->endp_number_in[usb_endp];
2560 struct u132_endp *endp = u132->endp[endp_number - 1];
Alan Sterne9df41c2007-08-08 11:48:02 -04002561 return u132_endp_urb_dequeue(u132, endp, urb, status);
Tony Olechd774efe2006-09-13 11:27:35 +01002562 } else {
2563 u8 endp_number = udev->endp_number_out[usb_endp];
2564 struct u132_endp *endp = u132->endp[endp_number - 1];
Alan Sterne9df41c2007-08-08 11:48:02 -04002565 return u132_endp_urb_dequeue(u132, endp, urb, status);
Tony Olechd774efe2006-09-13 11:27:35 +01002566 }
2567 }
2568}
2569
2570static void u132_endpoint_disable(struct usb_hcd *hcd,
2571 struct usb_host_endpoint *hep)
2572{
2573 struct u132 *u132 = hcd_to_u132(hcd);
2574 if (u132->going > 2) {
Tony Olech4b873612006-12-06 13:16:22 +00002575 dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
2576 ") has been removed %d\n", u132, hcd, hep,
2577 u132->going);
Tony Olechd774efe2006-09-13 11:27:35 +01002578 } else {
2579 struct u132_endp *endp = hep->hcpriv;
2580 if (endp)
2581 u132_endp_put_kref(u132, endp);
2582 }
2583}
2584
2585static int u132_get_frame(struct usb_hcd *hcd)
2586{
2587 struct u132 *u132 = hcd_to_u132(hcd);
2588 if (u132->going > 1) {
2589 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2590 , u132->going);
2591 return -ENODEV;
2592 } else if (u132->going > 0) {
2593 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2594 return -ESHUTDOWN;
2595 } else {
2596 int frame = 0;
2597 dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
2598 msleep(100);
2599 return frame;
2600 }
2601}
2602
2603static int u132_roothub_descriptor(struct u132 *u132,
2604 struct usb_hub_descriptor *desc)
2605{
2606 int retval;
2607 u16 temp;
2608 u32 rh_a = -1;
2609 u32 rh_b = -1;
2610 retval = u132_read_pcimem(u132, roothub.a, &rh_a);
2611 if (retval)
2612 return retval;
2613 desc->bDescriptorType = 0x29;
2614 desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
2615 desc->bHubContrCurrent = 0;
2616 desc->bNbrPorts = u132->num_ports;
2617 temp = 1 + (u132->num_ports / 8);
2618 desc->bDescLength = 7 + 2 *temp;
2619 temp = 0;
2620 if (rh_a & RH_A_NPS)
2621 temp |= 0x0002;
2622 if (rh_a & RH_A_PSM)
2623 temp |= 0x0001;
2624 if (rh_a & RH_A_NOCP) {
2625 temp |= 0x0010;
2626 } else if (rh_a & RH_A_OCPM)
2627 temp |= 0x0008;
2628 desc->wHubCharacteristics = cpu_to_le16(temp);
2629 retval = u132_read_pcimem(u132, roothub.b, &rh_b);
2630 if (retval)
2631 return retval;
2632 memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
2633 desc->bitmap[0] = rh_b & RH_B_DR;
2634 if (u132->num_ports > 7) {
2635 desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
2636 desc->bitmap[2] = 0xff;
2637 } else
2638 desc->bitmap[1] = 0xff;
2639 return 0;
2640}
2641
2642static int u132_roothub_status(struct u132 *u132, __le32 *desc)
2643{
2644 u32 rh_status = -1;
2645 int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
2646 *desc = cpu_to_le32(rh_status);
2647 return ret_status;
2648}
2649
2650static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
2651{
2652 if (wIndex == 0 || wIndex > u132->num_ports) {
2653 return -EINVAL;
2654 } else {
2655 int port = wIndex - 1;
2656 u32 rh_portstatus = -1;
2657 int ret_portstatus = u132_read_pcimem(u132,
2658 roothub.portstatus[port], &rh_portstatus);
2659 *desc = cpu_to_le32(rh_portstatus);
2660 if (*(u16 *) (desc + 2)) {
2661 dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
2662 "ge = %08X\n", port, *desc);
2663 }
2664 return ret_portstatus;
2665 }
2666}
2667
2668
2669/* this timer value might be vendor-specific ... */
2670#define PORT_RESET_HW_MSEC 10
2671#define PORT_RESET_MSEC 10
2672/* wrap-aware logic morphed from <linux/jiffies.h> */
2673#define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
2674static int u132_roothub_portreset(struct u132 *u132, int port_index)
2675{
2676 int retval;
2677 u32 fmnumber;
2678 u16 now;
2679 u16 reset_done;
2680 retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
2681 if (retval)
2682 return retval;
2683 now = fmnumber;
2684 reset_done = now + PORT_RESET_MSEC;
2685 do {
2686 u32 portstat;
2687 do {
2688 retval = u132_read_pcimem(u132,
2689 roothub.portstatus[port_index], &portstat);
2690 if (retval)
2691 return retval;
2692 if (RH_PS_PRS & portstat) {
2693 continue;
2694 } else
2695 break;
2696 } while (tick_before(now, reset_done));
2697 if (RH_PS_PRS & portstat)
2698 return -ENODEV;
2699 if (RH_PS_CCS & portstat) {
2700 if (RH_PS_PRSC & portstat) {
2701 retval = u132_write_pcimem(u132,
2702 roothub.portstatus[port_index],
2703 RH_PS_PRSC);
2704 if (retval)
2705 return retval;
2706 }
2707 } else
2708 break; /* start the next reset,
2709 sleep till it's probably done */
2710 retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
2711 RH_PS_PRS);
2712 if (retval)
2713 return retval;
2714 msleep(PORT_RESET_HW_MSEC);
2715 retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
2716 if (retval)
2717 return retval;
2718 now = fmnumber;
2719 } while (tick_before(now, reset_done));
2720 return 0;
2721}
2722
2723static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
2724 u16 wIndex)
2725{
2726 if (wIndex == 0 || wIndex > u132->num_ports) {
2727 return -EINVAL;
2728 } else {
2729 int retval;
2730 int port_index = wIndex - 1;
2731 struct u132_port *port = &u132->port[port_index];
2732 port->Status &= ~(1 << wValue);
2733 switch (wValue) {
2734 case USB_PORT_FEAT_SUSPEND:
2735 retval = u132_write_pcimem(u132,
2736 roothub.portstatus[port_index], RH_PS_PSS);
2737 if (retval)
2738 return retval;
2739 return 0;
2740 case USB_PORT_FEAT_POWER:
2741 retval = u132_write_pcimem(u132,
2742 roothub.portstatus[port_index], RH_PS_PPS);
2743 if (retval)
2744 return retval;
2745 return 0;
2746 case USB_PORT_FEAT_RESET:
2747 retval = u132_roothub_portreset(u132, port_index);
2748 if (retval)
2749 return retval;
2750 return 0;
2751 default:
2752 return -EPIPE;
2753 }
2754 }
2755}
2756
2757static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
2758 u16 wIndex)
2759{
2760 if (wIndex == 0 || wIndex > u132->num_ports) {
2761 return -EINVAL;
2762 } else {
2763 int port_index = wIndex - 1;
2764 u32 temp;
2765 int retval;
2766 struct u132_port *port = &u132->port[port_index];
2767 port->Status &= ~(1 << wValue);
2768 switch (wValue) {
2769 case USB_PORT_FEAT_ENABLE:
2770 temp = RH_PS_CCS;
2771 break;
2772 case USB_PORT_FEAT_C_ENABLE:
2773 temp = RH_PS_PESC;
2774 break;
2775 case USB_PORT_FEAT_SUSPEND:
2776 temp = RH_PS_POCI;
2777 if ((u132->hc_control & OHCI_CTRL_HCFS)
2778 != OHCI_USB_OPER) {
2779 dev_err(&u132->platform_dev->dev, "TODO resume_"
2780 "root_hub\n");
2781 }
2782 break;
2783 case USB_PORT_FEAT_C_SUSPEND:
2784 temp = RH_PS_PSSC;
2785 break;
2786 case USB_PORT_FEAT_POWER:
2787 temp = RH_PS_LSDA;
2788 break;
2789 case USB_PORT_FEAT_C_CONNECTION:
2790 temp = RH_PS_CSC;
2791 break;
2792 case USB_PORT_FEAT_C_OVER_CURRENT:
2793 temp = RH_PS_OCIC;
2794 break;
2795 case USB_PORT_FEAT_C_RESET:
2796 temp = RH_PS_PRSC;
2797 break;
2798 default:
2799 return -EPIPE;
2800 }
2801 retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
2802 temp);
2803 if (retval)
2804 return retval;
2805 return 0;
2806 }
2807}
2808
2809
2810/* the virtual root hub timer IRQ checks for hub status*/
2811static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
2812{
2813 struct u132 *u132 = hcd_to_u132(hcd);
2814 if (u132->going > 1) {
2815 dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
2816 "ed %d\n", hcd, u132->going);
2817 return -ENODEV;
2818 } else if (u132->going > 0) {
2819 dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
2820 "ed\n", hcd);
Tony Olechd774efe2006-09-13 11:27:35 +01002821 return -ESHUTDOWN;
2822 } else {
2823 int i, changed = 0, length = 1;
2824 if (u132->flags & OHCI_QUIRK_AMD756) {
2825 if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
2826 dev_err(&u132->platform_dev->dev, "bogus NDP, r"
2827 "ereads as NDP=%d\n",
2828 u132->hc_roothub_a & RH_A_NDP);
2829 goto done;
2830 }
2831 }
2832 if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) {
2833 buf[0] = changed = 1;
2834 } else
2835 buf[0] = 0;
2836 if (u132->num_ports > 7) {
2837 buf[1] = 0;
2838 length++;
2839 }
2840 for (i = 0; i < u132->num_ports; i++) {
2841 if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
2842 RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
2843 RH_PS_PRSC)) {
2844 changed = 1;
2845 if (i < 7) {
2846 buf[0] |= 1 << (i + 1);
2847 } else
2848 buf[1] |= 1 << (i - 7);
2849 continue;
2850 }
2851 if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) {
2852 continue;
2853 }
2854 if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) {
2855 continue;
2856 }
2857 }
2858 done:return changed ? length : 0;
2859 }
2860}
2861
2862static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
2863 u16 wIndex, char *buf, u16 wLength)
2864{
2865 struct u132 *u132 = hcd_to_u132(hcd);
2866 if (u132->going > 1) {
2867 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2868 , u132->going);
2869 return -ENODEV;
2870 } else if (u132->going > 0) {
2871 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2872 return -ESHUTDOWN;
2873 } else {
2874 int retval = 0;
2875 down(&u132->sw_lock);
2876 switch (typeReq) {
2877 case ClearHubFeature:
2878 switch (wValue) {
2879 case C_HUB_OVER_CURRENT:
2880 case C_HUB_LOCAL_POWER:
2881 break;
2882 default:
2883 goto stall;
2884 }
2885 break;
2886 case SetHubFeature:
2887 switch (wValue) {
2888 case C_HUB_OVER_CURRENT:
2889 case C_HUB_LOCAL_POWER:
2890 break;
2891 default:
2892 goto stall;
2893 }
2894 break;
2895 case ClearPortFeature:{
2896 retval = u132_roothub_clearportfeature(u132,
2897 wValue, wIndex);
2898 if (retval)
2899 goto error;
2900 break;
2901 }
2902 case GetHubDescriptor:{
2903 retval = u132_roothub_descriptor(u132,
2904 (struct usb_hub_descriptor *)buf);
2905 if (retval)
2906 goto error;
2907 break;
2908 }
2909 case GetHubStatus:{
2910 retval = u132_roothub_status(u132,
2911 (__le32 *) buf);
2912 if (retval)
2913 goto error;
2914 break;
2915 }
2916 case GetPortStatus:{
2917 retval = u132_roothub_portstatus(u132,
2918 (__le32 *) buf, wIndex);
2919 if (retval)
2920 goto error;
2921 break;
2922 }
2923 case SetPortFeature:{
2924 retval = u132_roothub_setportfeature(u132,
2925 wValue, wIndex);
2926 if (retval)
2927 goto error;
2928 break;
2929 }
2930 default:
2931 goto stall;
2932 error:u132_disable(u132);
2933 u132->going = 1;
2934 break;
2935 stall:retval = -EPIPE;
2936 break;
2937 }
2938 up(&u132->sw_lock);
2939 return retval;
2940 }
2941}
2942
2943static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
2944{
2945 struct u132 *u132 = hcd_to_u132(hcd);
2946 if (u132->going > 1) {
2947 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2948 , u132->going);
2949 return -ENODEV;
2950 } else if (u132->going > 0) {
2951 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2952 return -ESHUTDOWN;
2953 } else
2954 return 0;
2955}
2956
2957static void u132_hub_irq_enable(struct usb_hcd *hcd)
2958{
2959 struct u132 *u132 = hcd_to_u132(hcd);
2960 if (u132->going > 1) {
2961 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2962 , u132->going);
2963 } else if (u132->going > 0)
2964 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2965}
2966
2967
2968#ifdef CONFIG_PM
2969static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
2970{
2971 struct u132 *u132 = hcd_to_u132(hcd);
2972 if (u132->going > 1) {
2973 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2974 , u132->going);
2975 return -ENODEV;
2976 } else if (u132->going > 0) {
2977 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2978 return -ESHUTDOWN;
2979 } else
2980 return 0;
2981}
2982
2983static int u132_hcd_resume(struct usb_hcd *hcd)
2984{
2985 struct u132 *u132 = hcd_to_u132(hcd);
2986 if (u132->going > 1) {
2987 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2988 , u132->going);
2989 return -ENODEV;
2990 } else if (u132->going > 0) {
2991 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2992 return -ESHUTDOWN;
2993 } else
2994 return 0;
2995}
2996
2997static int u132_bus_suspend(struct usb_hcd *hcd)
2998{
2999 struct u132 *u132 = hcd_to_u132(hcd);
3000 if (u132->going > 1) {
3001 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
3002 , u132->going);
3003 return -ENODEV;
3004 } else if (u132->going > 0) {
3005 dev_err(&u132->platform_dev->dev, "device is being removed\n");
3006 return -ESHUTDOWN;
3007 } else
3008 return 0;
3009}
3010
3011static int u132_bus_resume(struct usb_hcd *hcd)
3012{
3013 struct u132 *u132 = hcd_to_u132(hcd);
3014 if (u132->going > 1) {
3015 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
3016 , u132->going);
3017 return -ENODEV;
3018 } else if (u132->going > 0) {
3019 dev_err(&u132->platform_dev->dev, "device is being removed\n");
3020 return -ESHUTDOWN;
3021 } else
3022 return 0;
3023}
3024
3025#else
3026#define u132_hcd_suspend NULL
3027#define u132_hcd_resume NULL
3028#define u132_bus_suspend NULL
3029#define u132_bus_resume NULL
3030#endif
3031static struct hc_driver u132_hc_driver = {
3032 .description = hcd_name,
3033 .hcd_priv_size = sizeof(struct u132),
3034 .irq = NULL,
3035 .flags = HCD_USB11 | HCD_MEMORY,
3036 .reset = u132_hcd_reset,
3037 .start = u132_hcd_start,
3038 .suspend = u132_hcd_suspend,
3039 .resume = u132_hcd_resume,
3040 .stop = u132_hcd_stop,
3041 .urb_enqueue = u132_urb_enqueue,
3042 .urb_dequeue = u132_urb_dequeue,
3043 .endpoint_disable = u132_endpoint_disable,
3044 .get_frame_number = u132_get_frame,
3045 .hub_status_data = u132_hub_status_data,
3046 .hub_control = u132_hub_control,
3047 .bus_suspend = u132_bus_suspend,
3048 .bus_resume = u132_bus_resume,
3049 .start_port_reset = u132_start_port_reset,
3050 .hub_irq_enable = u132_hub_irq_enable,
3051};
3052
3053/*
3054* This function may be called by the USB core whilst the "usb_all_devices_rwsem"
3055* is held for writing, thus this module must not call usb_remove_hcd()
3056* synchronously - but instead should immediately stop activity to the
Matt LaPlante0779bf22006-11-30 05:24:39 +01003057* device and asynchronously call usb_remove_hcd()
Tony Olechd774efe2006-09-13 11:27:35 +01003058*/
3059static int __devexit u132_remove(struct platform_device *pdev)
3060{
3061 struct usb_hcd *hcd = platform_get_drvdata(pdev);
3062 if (hcd) {
3063 struct u132 *u132 = hcd_to_u132(hcd);
Tony Olechd774efe2006-09-13 11:27:35 +01003064 if (u132->going++ > 1) {
Tony Olech4b873612006-12-06 13:16:22 +00003065 dev_err(&u132->platform_dev->dev, "already being remove"
3066 "d\n");
Tony Olechd774efe2006-09-13 11:27:35 +01003067 return -ENODEV;
3068 } else {
3069 int rings = MAX_U132_RINGS;
3070 int endps = MAX_U132_ENDPS;
Tony Olech4b873612006-12-06 13:16:22 +00003071 dev_err(&u132->platform_dev->dev, "removing device u132"
3072 ".%d\n", u132->sequence_num);
Tony Olechd774efe2006-09-13 11:27:35 +01003073 msleep(100);
3074 down(&u132->sw_lock);
3075 u132_monitor_cancel_work(u132);
3076 while (rings-- > 0) {
3077 struct u132_ring *ring = &u132->ring[rings];
3078 u132_ring_cancel_work(u132, ring);
3079 } while (endps-- > 0) {
3080 struct u132_endp *endp = u132->endp[endps];
3081 if (endp)
3082 u132_endp_cancel_work(u132, endp);
3083 }
3084 u132->going += 1;
3085 printk(KERN_INFO "removing device u132.%d\n",
3086 u132->sequence_num);
3087 up(&u132->sw_lock);
3088 usb_remove_hcd(hcd);
3089 u132_u132_put_kref(u132);
3090 return 0;
3091 }
3092 } else
3093 return 0;
3094}
3095
3096static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
3097{
3098 int rings = MAX_U132_RINGS;
3099 int ports = MAX_U132_PORTS;
3100 int addrs = MAX_U132_ADDRS;
3101 int udevs = MAX_U132_UDEVS;
3102 int endps = MAX_U132_ENDPS;
3103 u132->board = pdev->dev.platform_data;
3104 u132->platform_dev = pdev;
3105 u132->power = 0;
3106 u132->reset = 0;
3107 init_MUTEX(&u132->sw_lock);
3108 init_MUTEX(&u132->scheduler_lock);
3109 while (rings-- > 0) {
3110 struct u132_ring *ring = &u132->ring[rings];
3111 ring->u132 = u132;
3112 ring->number = rings + 1;
3113 ring->length = 0;
3114 ring->curr_endp = NULL;
David Howellsc4028952006-11-22 14:57:56 +00003115 INIT_DELAYED_WORK(&ring->scheduler,
3116 u132_hcd_ring_work_scheduler);
Tony Olechd774efe2006-09-13 11:27:35 +01003117 } down(&u132->sw_lock);
David Howellsc4028952006-11-22 14:57:56 +00003118 INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
Tony Olechd774efe2006-09-13 11:27:35 +01003119 while (ports-- > 0) {
3120 struct u132_port *port = &u132->port[ports];
3121 port->u132 = u132;
3122 port->reset = 0;
3123 port->enable = 0;
3124 port->power = 0;
3125 port->Status = 0;
3126 } while (addrs-- > 0) {
3127 struct u132_addr *addr = &u132->addr[addrs];
3128 addr->address = 0;
3129 } while (udevs-- > 0) {
3130 struct u132_udev *udev = &u132->udev[udevs];
3131 int i = ARRAY_SIZE(udev->endp_number_in);
3132 int o = ARRAY_SIZE(udev->endp_number_out);
3133 udev->usb_device = NULL;
3134 udev->udev_number = 0;
3135 udev->usb_addr = 0;
3136 udev->portnumber = 0;
3137 while (i-- > 0) {
3138 udev->endp_number_in[i] = 0;
3139 }
3140 while (o-- > 0) {
3141 udev->endp_number_out[o] = 0;
3142 }
3143 }
3144 while (endps-- > 0) {
3145 u132->endp[endps] = NULL;
3146 }
3147 up(&u132->sw_lock);
3148 return;
3149}
3150
3151static int __devinit u132_probe(struct platform_device *pdev)
3152{
3153 struct usb_hcd *hcd;
Tony Olech4b873612006-12-06 13:16:22 +00003154 int retval;
3155 u32 control;
3156 u32 rh_a = -1;
3157 u32 num_ports;
Tony Olechd774efe2006-09-13 11:27:35 +01003158 msleep(100);
3159 if (u132_exiting > 0) {
3160 return -ENODEV;
Tony Olech4b873612006-12-06 13:16:22 +00003161 }
3162 retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
3163 if (retval)
3164 return retval;
3165 retval = ftdi_read_pcimem(pdev, control, &control);
3166 if (retval)
3167 return retval;
3168 retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
3169 if (retval)
3170 return retval;
3171 num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */
Tony Olechd774efe2006-09-13 11:27:35 +01003172 if (pdev->dev.dma_mask) {
3173 return -EINVAL;
3174 }
3175 hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
3176 if (!hcd) {
3177 printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
3178 );
3179 ftdi_elan_gone_away(pdev);
3180 return -ENOMEM;
3181 } else {
3182 int retval = 0;
3183 struct u132 *u132 = hcd_to_u132(hcd);
3184 hcd->rsrc_start = 0;
Matthias Kaehlcked2066eb2007-07-13 21:26:59 +02003185 mutex_lock(&u132_module_lock);
Tony Olechd774efe2006-09-13 11:27:35 +01003186 list_add_tail(&u132->u132_list, &u132_static_list);
3187 u132->sequence_num = ++u132_instances;
Matthias Kaehlcked2066eb2007-07-13 21:26:59 +02003188 mutex_unlock(&u132_module_lock);
Tony Olechd774efe2006-09-13 11:27:35 +01003189 u132_u132_init_kref(u132);
3190 u132_initialise(u132, pdev);
3191 hcd->product_desc = "ELAN U132 Host Controller";
3192 retval = usb_add_hcd(hcd, 0, 0);
3193 if (retval != 0) {
3194 dev_err(&u132->platform_dev->dev, "init error %d\n",
3195 retval);
3196 u132_u132_put_kref(u132);
3197 return retval;
3198 } else {
3199 u132_monitor_queue_work(u132, 100);
3200 return 0;
3201 }
3202 }
3203}
3204
3205
3206#ifdef CONFIG_PM
3207/* for this device there's no useful distinction between the controller
3208* and its root hub, except that the root hub only gets direct PM calls
3209* when CONFIG_USB_SUSPEND is enabled.
3210*/
3211static int u132_suspend(struct platform_device *pdev, pm_message_t state)
3212{
3213 struct usb_hcd *hcd = platform_get_drvdata(pdev);
3214 struct u132 *u132 = hcd_to_u132(hcd);
3215 if (u132->going > 1) {
3216 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
3217 , u132->going);
3218 return -ENODEV;
3219 } else if (u132->going > 0) {
3220 dev_err(&u132->platform_dev->dev, "device is being removed\n");
3221 return -ESHUTDOWN;
3222 } else {
3223 int retval = 0;
3224 if (state.event == PM_EVENT_FREEZE) {
3225 retval = u132_bus_suspend(hcd);
3226 } else if (state.event == PM_EVENT_SUSPEND) {
3227 int ports = MAX_U132_PORTS;
3228 while (ports-- > 0) {
3229 port_power(u132, ports, 0);
3230 }
3231 }
3232 if (retval == 0)
3233 pdev->dev.power.power_state = state;
3234 return retval;
3235 }
3236}
3237
3238static int u132_resume(struct platform_device *pdev)
3239{
3240 struct usb_hcd *hcd = platform_get_drvdata(pdev);
3241 struct u132 *u132 = hcd_to_u132(hcd);
3242 if (u132->going > 1) {
3243 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
3244 , u132->going);
3245 return -ENODEV;
3246 } else if (u132->going > 0) {
3247 dev_err(&u132->platform_dev->dev, "device is being removed\n");
3248 return -ESHUTDOWN;
3249 } else {
3250 int retval = 0;
3251 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
3252 int ports = MAX_U132_PORTS;
3253 while (ports-- > 0) {
3254 port_power(u132, ports, 1);
3255 }
3256 retval = 0;
3257 } else {
3258 pdev->dev.power.power_state = PMSG_ON;
3259 retval = u132_bus_resume(hcd);
3260 }
3261 return retval;
3262 }
3263}
3264
3265#else
3266#define u132_suspend NULL
3267#define u132_resume NULL
3268#endif
3269/*
Matt LaPlante0779bf22006-11-30 05:24:39 +01003270* this driver is loaded explicitly by ftdi_u132
Tony Olechd774efe2006-09-13 11:27:35 +01003271*
3272* the platform_driver struct is static because it is per type of module
3273*/
3274static struct platform_driver u132_platform_driver = {
3275 .probe = u132_probe,
3276 .remove = __devexit_p(u132_remove),
3277 .suspend = u132_suspend,
3278 .resume = u132_resume,
3279 .driver = {
3280 .name = (char *)hcd_name,
3281 .owner = THIS_MODULE,
3282 },
3283};
3284static int __init u132_hcd_init(void)
3285{
3286 int retval;
3287 INIT_LIST_HEAD(&u132_static_list);
3288 u132_instances = 0;
3289 u132_exiting = 0;
Matthias Kaehlcked2066eb2007-07-13 21:26:59 +02003290 mutex_init(&u132_module_lock);
Tony Olechd774efe2006-09-13 11:27:35 +01003291 if (usb_disabled())
3292 return -ENODEV;
3293 printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
3294 __DATE__);
3295 workqueue = create_singlethread_workqueue("u132");
3296 retval = platform_driver_register(&u132_platform_driver);
3297 return retval;
3298}
3299
3300
3301module_init(u132_hcd_init);
3302static void __exit u132_hcd_exit(void)
3303{
3304 struct u132 *u132;
3305 struct u132 *temp;
Matthias Kaehlcked2066eb2007-07-13 21:26:59 +02003306 mutex_lock(&u132_module_lock);
Tony Olechd774efe2006-09-13 11:27:35 +01003307 u132_exiting += 1;
Matthias Kaehlcked2066eb2007-07-13 21:26:59 +02003308 mutex_unlock(&u132_module_lock);
Tony Olechd774efe2006-09-13 11:27:35 +01003309 list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
3310 platform_device_unregister(u132->platform_dev);
3311 } platform_driver_unregister(&u132_platform_driver);
3312 printk(KERN_INFO "u132-hcd driver deregistered\n");
3313 wait_event(u132_hcd_wait, u132_instances == 0);
3314 flush_workqueue(workqueue);
3315 destroy_workqueue(workqueue);
3316}
3317
3318
3319module_exit(u132_hcd_exit);
3320MODULE_LICENSE("GPL");