blob: e98df2ee990131643d6e162c67b82145bab018bf [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>
54#include <linux/pci_ids.h>
55#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*/
86static struct semaphore u132_module_lock;
87static 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;
261 down(&u132_module_lock);
262 list_del_init(&u132->u132_list);
263 u132_instances -= 1;
264 up(&u132_module_lock);
265 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);
524 endp->queue_next += 1;
525 if (ENDP_QUEUE_SIZE > --endp->queue_size) {
526 endp->active = 0;
527 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
528 } else {
529 struct list_head *next = endp->urb_more.next;
530 struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
531 urb_more);
532 list_del(next);
533 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
534 urbq->urb;
535 endp->active = 0;
536 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
537 kfree(urbq);
538 } down(&u132->scheduler_lock);
539 ring = endp->ring;
540 ring->in_use = 0;
541 u132_ring_cancel_work(u132, ring);
542 u132_ring_queue_work(u132, ring, 0);
543 up(&u132->scheduler_lock);
544 u132_endp_put_kref(u132, endp);
David Howells7d12e782006-10-05 14:55:46 +0100545 usb_hcd_giveback_urb(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +0100546 return;
547}
548
549static void u132_hcd_forget_urb(struct u132 *u132, struct u132_endp *endp,
550 struct urb *urb, int status)
551{
552 u132_endp_put_kref(u132, endp);
553}
554
555static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
556 struct urb *urb, int status)
557{
558 unsigned long irqs;
559 struct usb_hcd *hcd = u132_to_hcd(u132);
560 urb->error_count = 0;
561 urb->status = status;
562 urb->hcpriv = NULL;
563 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
564 endp->queue_next += 1;
565 if (ENDP_QUEUE_SIZE > --endp->queue_size) {
566 endp->active = 0;
567 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
568 } else {
569 struct list_head *next = endp->urb_more.next;
570 struct u132_urbq *urbq = list_entry(next, struct u132_urbq,
571 urb_more);
572 list_del(next);
573 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
574 urbq->urb;
575 endp->active = 0;
576 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
577 kfree(urbq);
David Howells7d12e782006-10-05 14:55:46 +0100578 } usb_hcd_giveback_urb(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +0100579 return;
580}
581
582static inline int edset_input(struct u132 *u132, struct u132_ring *ring,
583 struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
584 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
585 int toggle_bits, int error_count, int condition_code, int repeat_number,
586 int halted, int skipped, int actual, int non_null))
587{
588 return usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp,
589 urb, address, endp->usb_endp, toggle_bits, callback);
590}
591
592static inline int edset_setup(struct u132 *u132, struct u132_ring *ring,
593 struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
594 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
595 int toggle_bits, int error_count, int condition_code, int repeat_number,
596 int halted, int skipped, int actual, int non_null))
597{
598 return usb_ftdi_elan_edset_setup(u132->platform_dev, ring->number, endp,
599 urb, address, endp->usb_endp, toggle_bits, callback);
600}
601
602static inline int edset_single(struct u132 *u132, struct u132_ring *ring,
603 struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
604 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
605 int toggle_bits, int error_count, int condition_code, int repeat_number,
606 int halted, int skipped, int actual, int non_null))
607{
608 return usb_ftdi_elan_edset_single(u132->platform_dev, ring->number,
609 endp, urb, address, endp->usb_endp, toggle_bits, callback);
610}
611
612static inline int edset_output(struct u132 *u132, struct u132_ring *ring,
613 struct u132_endp *endp, struct urb *urb, u8 address, u8 toggle_bits,
614 void (*callback) (void *endp, struct urb *urb, u8 *buf, int len,
615 int toggle_bits, int error_count, int condition_code, int repeat_number,
616 int halted, int skipped, int actual, int non_null))
617{
618 return usb_ftdi_elan_edset_output(u132->platform_dev, ring->number,
619 endp, urb, address, endp->usb_endp, toggle_bits, callback);
620}
621
622
623/*
624* must not LOCK sw_lock
625*
626*/
627static void u132_hcd_interrupt_recv(void *data, struct urb *urb, u8 *buf,
628 int len, int toggle_bits, int error_count, int condition_code,
629 int repeat_number, int halted, int skipped, int actual, int non_null)
630{
631 struct u132_endp *endp = data;
632 struct u132 *u132 = endp->u132;
633 u8 address = u132->addr[endp->usb_addr].address;
634 struct u132_udev *udev = &u132->udev[address];
635 down(&u132->scheduler_lock);
636 if (u132->going > 1) {
637 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
638 , u132->going);
639 up(&u132->scheduler_lock);
640 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
641 return;
642 } else if (endp->dequeueing) {
643 endp->dequeueing = 0;
644 up(&u132->scheduler_lock);
645 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
646 return;
647 } else if (u132->going > 0) {
648 dev_err(&u132->platform_dev->dev, "device is being removed urb="
649 "%p status=%d\n", urb, urb->status);
650 up(&u132->scheduler_lock);
651 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
652 return;
653 } else if (urb->status == -EINPROGRESS) {
654 struct u132_ring *ring = endp->ring;
655 u8 *u = urb->transfer_buffer + urb->actual_length;
656 u8 *b = buf;
657 int L = len;
658 while (L-- > 0) {
659 *u++ = *b++;
660 }
661 urb->actual_length += len;
662 if ((condition_code == TD_CC_NOERROR) &&
663 (urb->transfer_buffer_length > urb->actual_length)) {
664 endp->toggle_bits = toggle_bits;
665 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
666 1 & toggle_bits);
667 if (urb->actual_length > 0) {
668 int retval;
669 up(&u132->scheduler_lock);
670 retval = edset_single(u132, ring, endp, urb,
671 address, endp->toggle_bits,
672 u132_hcd_interrupt_recv);
673 if (retval == 0) {
674 } else
675 u132_hcd_giveback_urb(u132, endp, urb,
676 retval);
677 } else {
678 ring->in_use = 0;
679 endp->active = 0;
680 endp->jiffies = jiffies +
681 msecs_to_jiffies(urb->interval);
682 u132_ring_cancel_work(u132, ring);
683 u132_ring_queue_work(u132, ring, 0);
684 up(&u132->scheduler_lock);
685 u132_endp_put_kref(u132, endp);
686 }
687 return;
688 } else if ((condition_code == TD_DATAUNDERRUN) &&
689 ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
690 endp->toggle_bits = toggle_bits;
691 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
692 1 & toggle_bits);
693 up(&u132->scheduler_lock);
694 u132_hcd_giveback_urb(u132, endp, urb, 0);
695 return;
696 } else {
697 if (condition_code == TD_CC_NOERROR) {
698 endp->toggle_bits = toggle_bits;
699 usb_settoggle(udev->usb_device, endp->usb_endp,
700 0, 1 & toggle_bits);
701 } else if (condition_code == TD_CC_STALL) {
702 endp->toggle_bits = 0x2;
703 usb_settoggle(udev->usb_device, endp->usb_endp,
704 0, 0);
705 } else {
706 endp->toggle_bits = 0x2;
707 usb_settoggle(udev->usb_device, endp->usb_endp,
708 0, 0);
709 dev_err(&u132->platform_dev->dev, "urb=%p givin"
710 "g back INTERRUPT %s\n", urb,
711 cc_to_text[condition_code]);
712 }
713 up(&u132->scheduler_lock);
714 u132_hcd_giveback_urb(u132, endp, urb,
715 cc_to_error[condition_code]);
716 return;
717 }
718 } else {
719 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
720 "s=%d\n", urb, urb->status);
721 up(&u132->scheduler_lock);
722 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
723 return;
724 }
725}
726
727static void u132_hcd_bulk_output_sent(void *data, struct urb *urb, u8 *buf,
728 int len, int toggle_bits, int error_count, int condition_code,
729 int repeat_number, int halted, int skipped, int actual, int non_null)
730{
731 struct u132_endp *endp = data;
732 struct u132 *u132 = endp->u132;
733 u8 address = u132->addr[endp->usb_addr].address;
734 down(&u132->scheduler_lock);
735 if (u132->going > 1) {
736 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
737 , u132->going);
738 up(&u132->scheduler_lock);
739 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
740 return;
741 } else if (endp->dequeueing) {
742 endp->dequeueing = 0;
743 up(&u132->scheduler_lock);
744 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
745 return;
746 } else if (u132->going > 0) {
747 dev_err(&u132->platform_dev->dev, "device is being removed urb="
748 "%p status=%d\n", urb, urb->status);
749 up(&u132->scheduler_lock);
750 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
751 return;
752 } else if (urb->status == -EINPROGRESS) {
753 struct u132_ring *ring = endp->ring;
754 urb->actual_length += len;
755 endp->toggle_bits = toggle_bits;
756 if (urb->transfer_buffer_length > urb->actual_length) {
757 int retval;
758 up(&u132->scheduler_lock);
759 retval = edset_output(u132, ring, endp, urb, address,
760 endp->toggle_bits, u132_hcd_bulk_output_sent);
761 if (retval == 0) {
762 } else
763 u132_hcd_giveback_urb(u132, endp, urb, retval);
764 return;
765 } else {
766 up(&u132->scheduler_lock);
767 u132_hcd_giveback_urb(u132, endp, urb, 0);
768 return;
769 }
770 } else {
771 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
772 "s=%d\n", urb, urb->status);
773 up(&u132->scheduler_lock);
774 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
775 return;
776 }
777}
778
779static void u132_hcd_bulk_input_recv(void *data, struct urb *urb, u8 *buf,
780 int len, int toggle_bits, int error_count, int condition_code,
781 int repeat_number, int halted, int skipped, int actual, int non_null)
782{
783 struct u132_endp *endp = data;
784 struct u132 *u132 = endp->u132;
785 u8 address = u132->addr[endp->usb_addr].address;
786 struct u132_udev *udev = &u132->udev[address];
787 down(&u132->scheduler_lock);
788 if (u132->going > 1) {
789 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
790 , u132->going);
791 up(&u132->scheduler_lock);
792 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
793 return;
794 } else if (endp->dequeueing) {
795 endp->dequeueing = 0;
796 up(&u132->scheduler_lock);
797 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
798 return;
799 } else if (u132->going > 0) {
800 dev_err(&u132->platform_dev->dev, "device is being removed urb="
801 "%p status=%d\n", urb, urb->status);
802 up(&u132->scheduler_lock);
803 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
804 return;
805 } else if (urb->status == -EINPROGRESS) {
806 struct u132_ring *ring = endp->ring;
807 u8 *u = urb->transfer_buffer + urb->actual_length;
808 u8 *b = buf;
809 int L = len;
810 while (L-- > 0) {
811 *u++ = *b++;
812 }
813 urb->actual_length += len;
814 if ((condition_code == TD_CC_NOERROR) &&
815 (urb->transfer_buffer_length > urb->actual_length)) {
816 int retval;
817 endp->toggle_bits = toggle_bits;
818 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
819 1 & toggle_bits);
820 up(&u132->scheduler_lock);
821 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
822 ring->number, endp, urb, address,
823 endp->usb_endp, endp->toggle_bits,
824 u132_hcd_bulk_input_recv);
825 if (retval == 0) {
826 } else
827 u132_hcd_giveback_urb(u132, endp, urb, retval);
828 return;
829 } else if (condition_code == TD_CC_NOERROR) {
830 endp->toggle_bits = toggle_bits;
831 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
832 1 & toggle_bits);
833 up(&u132->scheduler_lock);
834 u132_hcd_giveback_urb(u132, endp, urb,
835 cc_to_error[condition_code]);
836 return;
837 } else if ((condition_code == TD_DATAUNDERRUN) &&
838 ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0)) {
839 endp->toggle_bits = toggle_bits;
840 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
841 1 & toggle_bits);
842 up(&u132->scheduler_lock);
843 u132_hcd_giveback_urb(u132, endp, urb, 0);
844 return;
845 } else if (condition_code == TD_DATAUNDERRUN) {
846 endp->toggle_bits = toggle_bits;
847 usb_settoggle(udev->usb_device, endp->usb_endp, 0,
848 1 & toggle_bits);
849 dev_warn(&u132->platform_dev->dev, "urb=%p(SHORT NOT OK"
850 ") giving back BULK IN %s\n", urb,
851 cc_to_text[condition_code]);
852 up(&u132->scheduler_lock);
853 u132_hcd_giveback_urb(u132, endp, urb, 0);
854 return;
855 } else if (condition_code == TD_CC_STALL) {
856 endp->toggle_bits = 0x2;
857 usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
858 up(&u132->scheduler_lock);
859 u132_hcd_giveback_urb(u132, endp, urb,
860 cc_to_error[condition_code]);
861 return;
862 } else {
863 endp->toggle_bits = 0x2;
864 usb_settoggle(udev->usb_device, endp->usb_endp, 0, 0);
865 dev_err(&u132->platform_dev->dev, "urb=%p giving back B"
866 "ULK IN code=%d %s\n", urb, condition_code,
867 cc_to_text[condition_code]);
868 up(&u132->scheduler_lock);
869 u132_hcd_giveback_urb(u132, endp, urb,
870 cc_to_error[condition_code]);
871 return;
872 }
873 } else {
874 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
875 "s=%d\n", urb, urb->status);
876 up(&u132->scheduler_lock);
877 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
878 return;
879 }
880}
881
882static void u132_hcd_configure_empty_sent(void *data, struct urb *urb, u8 *buf,
883 int len, int toggle_bits, int error_count, int condition_code,
884 int repeat_number, int halted, int skipped, int actual, int non_null)
885{
886 struct u132_endp *endp = data;
887 struct u132 *u132 = endp->u132;
888 down(&u132->scheduler_lock);
889 if (u132->going > 1) {
890 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
891 , u132->going);
892 up(&u132->scheduler_lock);
893 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
894 return;
895 } else if (endp->dequeueing) {
896 endp->dequeueing = 0;
897 up(&u132->scheduler_lock);
898 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
899 return;
900 } else if (u132->going > 0) {
901 dev_err(&u132->platform_dev->dev, "device is being removed urb="
902 "%p status=%d\n", urb, urb->status);
903 up(&u132->scheduler_lock);
904 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
905 return;
906 } else if (urb->status == -EINPROGRESS) {
907 up(&u132->scheduler_lock);
908 u132_hcd_giveback_urb(u132, endp, urb, 0);
909 return;
910 } else {
911 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
912 "s=%d\n", urb, urb->status);
913 up(&u132->scheduler_lock);
914 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
915 return;
916 }
917}
918
919static void u132_hcd_configure_input_recv(void *data, struct urb *urb, u8 *buf,
920 int len, int toggle_bits, int error_count, int condition_code,
921 int repeat_number, int halted, int skipped, int actual, int non_null)
922{
923 struct u132_endp *endp = data;
924 struct u132 *u132 = endp->u132;
925 u8 address = u132->addr[endp->usb_addr].address;
926 down(&u132->scheduler_lock);
927 if (u132->going > 1) {
928 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
929 , u132->going);
930 up(&u132->scheduler_lock);
931 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
932 return;
933 } else if (endp->dequeueing) {
934 endp->dequeueing = 0;
935 up(&u132->scheduler_lock);
936 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
937 return;
938 } else if (u132->going > 0) {
939 dev_err(&u132->platform_dev->dev, "device is being removed urb="
940 "%p status=%d\n", urb, urb->status);
941 up(&u132->scheduler_lock);
942 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
943 return;
944 } else if (urb->status == -EINPROGRESS) {
945 struct u132_ring *ring = endp->ring;
946 u8 *u = urb->transfer_buffer;
947 u8 *b = buf;
948 int L = len;
949 while (L-- > 0) {
950 *u++ = *b++;
951 }
952 urb->actual_length = len;
953 if ((condition_code == TD_CC_NOERROR) || ((condition_code ==
954 TD_DATAUNDERRUN) && ((urb->transfer_flags &
955 URB_SHORT_NOT_OK) == 0))) {
956 int retval;
957 up(&u132->scheduler_lock);
958 retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
959 ring->number, endp, urb, address,
960 endp->usb_endp, 0x3,
961 u132_hcd_configure_empty_sent);
962 if (retval == 0) {
963 } else
964 u132_hcd_giveback_urb(u132, endp, urb, retval);
965 return;
966 } else if (condition_code == TD_CC_STALL) {
967 up(&u132->scheduler_lock);
968 dev_warn(&u132->platform_dev->dev, "giving back SETUP I"
969 "NPUT STALL urb %p\n", urb);
970 u132_hcd_giveback_urb(u132, endp, urb,
971 cc_to_error[condition_code]);
972 return;
973 } else {
974 up(&u132->scheduler_lock);
975 dev_err(&u132->platform_dev->dev, "giving back SETUP IN"
976 "PUT %s urb %p\n", cc_to_text[condition_code],
977 urb);
978 u132_hcd_giveback_urb(u132, endp, urb,
979 cc_to_error[condition_code]);
980 return;
981 }
982 } else {
983 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
984 "s=%d\n", urb, urb->status);
985 up(&u132->scheduler_lock);
986 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
987 return;
988 }
989}
990
991static void u132_hcd_configure_empty_recv(void *data, struct urb *urb, u8 *buf,
992 int len, int toggle_bits, int error_count, int condition_code,
993 int repeat_number, int halted, int skipped, int actual, int non_null)
994{
995 struct u132_endp *endp = data;
996 struct u132 *u132 = endp->u132;
997 down(&u132->scheduler_lock);
998 if (u132->going > 1) {
999 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1000 , u132->going);
1001 up(&u132->scheduler_lock);
1002 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1003 return;
1004 } else if (endp->dequeueing) {
1005 endp->dequeueing = 0;
1006 up(&u132->scheduler_lock);
1007 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1008 return;
1009 } else if (u132->going > 0) {
1010 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1011 "%p status=%d\n", urb, urb->status);
1012 up(&u132->scheduler_lock);
1013 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1014 return;
1015 } else if (urb->status == -EINPROGRESS) {
1016 up(&u132->scheduler_lock);
1017 u132_hcd_giveback_urb(u132, endp, urb, 0);
1018 return;
1019 } else {
1020 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1021 "s=%d\n", urb, urb->status);
1022 up(&u132->scheduler_lock);
1023 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1024 return;
1025 }
1026}
1027
1028static void u132_hcd_configure_setup_sent(void *data, struct urb *urb, u8 *buf,
1029 int len, int toggle_bits, int error_count, int condition_code,
1030 int repeat_number, int halted, int skipped, int actual, int non_null)
1031{
1032 struct u132_endp *endp = data;
1033 struct u132 *u132 = endp->u132;
1034 u8 address = u132->addr[endp->usb_addr].address;
1035 down(&u132->scheduler_lock);
1036 if (u132->going > 1) {
1037 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1038 , u132->going);
1039 up(&u132->scheduler_lock);
1040 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1041 return;
1042 } else if (endp->dequeueing) {
1043 endp->dequeueing = 0;
1044 up(&u132->scheduler_lock);
1045 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1046 return;
1047 } else if (u132->going > 0) {
1048 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1049 "%p status=%d\n", urb, urb->status);
1050 up(&u132->scheduler_lock);
1051 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1052 return;
1053 } else if (urb->status == -EINPROGRESS) {
1054 if (usb_pipein(urb->pipe)) {
1055 int retval;
1056 struct u132_ring *ring = endp->ring;
1057 up(&u132->scheduler_lock);
1058 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
1059 ring->number, endp, urb, address,
1060 endp->usb_endp, 0,
1061 u132_hcd_configure_input_recv);
1062 if (retval == 0) {
1063 } else
1064 u132_hcd_giveback_urb(u132, endp, urb, retval);
1065 return;
1066 } else {
1067 int retval;
1068 struct u132_ring *ring = endp->ring;
1069 up(&u132->scheduler_lock);
1070 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
1071 ring->number, endp, urb, address,
1072 endp->usb_endp, 0,
1073 u132_hcd_configure_empty_recv);
1074 if (retval == 0) {
1075 } else
1076 u132_hcd_giveback_urb(u132, endp, urb, retval);
1077 return;
1078 }
1079 } else {
1080 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1081 "s=%d\n", urb, urb->status);
1082 up(&u132->scheduler_lock);
1083 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1084 return;
1085 }
1086}
1087
1088static void u132_hcd_enumeration_empty_recv(void *data, struct urb *urb,
1089 u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
1090 int repeat_number, int halted, int skipped, int actual, int non_null)
1091{
1092 struct u132_endp *endp = data;
1093 struct u132 *u132 = endp->u132;
1094 u8 address = u132->addr[endp->usb_addr].address;
1095 struct u132_udev *udev = &u132->udev[address];
1096 down(&u132->scheduler_lock);
1097 if (u132->going > 1) {
1098 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1099 , u132->going);
1100 up(&u132->scheduler_lock);
1101 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1102 return;
1103 } else if (endp->dequeueing) {
1104 endp->dequeueing = 0;
1105 up(&u132->scheduler_lock);
1106 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1107 return;
1108 } else if (u132->going > 0) {
1109 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1110 "%p status=%d\n", urb, urb->status);
1111 up(&u132->scheduler_lock);
1112 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1113 return;
1114 } else if (urb->status == -EINPROGRESS) {
1115 u132->addr[0].address = 0;
1116 endp->usb_addr = udev->usb_addr;
1117 up(&u132->scheduler_lock);
1118 u132_hcd_giveback_urb(u132, endp, urb, 0);
1119 return;
1120 } else {
1121 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1122 "s=%d\n", urb, urb->status);
1123 up(&u132->scheduler_lock);
1124 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1125 return;
1126 }
1127}
1128
1129static void u132_hcd_enumeration_address_sent(void *data, struct urb *urb,
1130 u8 *buf, int len, int toggle_bits, int error_count, int condition_code,
1131 int repeat_number, int halted, int skipped, int actual, int non_null)
1132{
1133 struct u132_endp *endp = data;
1134 struct u132 *u132 = endp->u132;
1135 down(&u132->scheduler_lock);
1136 if (u132->going > 1) {
1137 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1138 , u132->going);
1139 up(&u132->scheduler_lock);
1140 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1141 return;
1142 } else if (endp->dequeueing) {
1143 endp->dequeueing = 0;
1144 up(&u132->scheduler_lock);
1145 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1146 return;
1147 } else if (u132->going > 0) {
1148 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1149 "%p status=%d\n", urb, urb->status);
1150 up(&u132->scheduler_lock);
1151 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1152 return;
1153 } else if (urb->status == -EINPROGRESS) {
1154 int retval;
1155 struct u132_ring *ring = endp->ring;
1156 up(&u132->scheduler_lock);
1157 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
1158 ring->number, endp, urb, 0, endp->usb_endp, 0,
1159 u132_hcd_enumeration_empty_recv);
1160 if (retval == 0) {
1161 } else
1162 u132_hcd_giveback_urb(u132, endp, urb, retval);
1163 return;
1164 } else {
1165 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1166 "s=%d\n", urb, urb->status);
1167 up(&u132->scheduler_lock);
1168 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1169 return;
1170 }
1171}
1172
1173static void u132_hcd_initial_empty_sent(void *data, struct urb *urb, u8 *buf,
1174 int len, int toggle_bits, int error_count, int condition_code,
1175 int repeat_number, int halted, int skipped, int actual, int non_null)
1176{
1177 struct u132_endp *endp = data;
1178 struct u132 *u132 = endp->u132;
1179 down(&u132->scheduler_lock);
1180 if (u132->going > 1) {
1181 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1182 , u132->going);
1183 up(&u132->scheduler_lock);
1184 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1185 return;
1186 } else if (endp->dequeueing) {
1187 endp->dequeueing = 0;
1188 up(&u132->scheduler_lock);
1189 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1190 return;
1191 } else if (u132->going > 0) {
1192 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1193 "%p status=%d\n", urb, urb->status);
1194 up(&u132->scheduler_lock);
1195 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1196 return;
1197 } else if (urb->status == -EINPROGRESS) {
1198 up(&u132->scheduler_lock);
1199 u132_hcd_giveback_urb(u132, endp, urb, 0);
1200 return;
1201 } else {
1202 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1203 "s=%d\n", urb, urb->status);
1204 up(&u132->scheduler_lock);
1205 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1206 return;
1207 }
1208}
1209
1210static void u132_hcd_initial_input_recv(void *data, struct urb *urb, u8 *buf,
1211 int len, int toggle_bits, int error_count, int condition_code,
1212 int repeat_number, int halted, int skipped, int actual, int non_null)
1213{
1214 struct u132_endp *endp = data;
1215 struct u132 *u132 = endp->u132;
1216 u8 address = u132->addr[endp->usb_addr].address;
1217 down(&u132->scheduler_lock);
1218 if (u132->going > 1) {
1219 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1220 , u132->going);
1221 up(&u132->scheduler_lock);
1222 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1223 return;
1224 } else if (endp->dequeueing) {
1225 endp->dequeueing = 0;
1226 up(&u132->scheduler_lock);
1227 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1228 return;
1229 } else if (u132->going > 0) {
1230 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1231 "%p status=%d\n", urb, urb->status);
1232 up(&u132->scheduler_lock);
1233 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1234 return;
1235 } else if (urb->status == -EINPROGRESS) {
1236 int retval;
1237 struct u132_ring *ring = endp->ring;
1238 u8 *u = urb->transfer_buffer;
1239 u8 *b = buf;
1240 int L = len;
1241 while (L-- > 0) {
1242 *u++ = *b++;
1243 }
1244 urb->actual_length = len;
1245 up(&u132->scheduler_lock);
1246 retval = usb_ftdi_elan_edset_empty(u132->platform_dev,
1247 ring->number, endp, urb, address, endp->usb_endp, 0x3,
1248 u132_hcd_initial_empty_sent);
1249 if (retval == 0) {
1250 } else
1251 u132_hcd_giveback_urb(u132, endp, urb, retval);
1252 return;
1253 } else {
1254 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1255 "s=%d\n", urb, urb->status);
1256 up(&u132->scheduler_lock);
1257 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1258 return;
1259 }
1260}
1261
1262static void u132_hcd_initial_setup_sent(void *data, struct urb *urb, u8 *buf,
1263 int len, int toggle_bits, int error_count, int condition_code,
1264 int repeat_number, int halted, int skipped, int actual, int non_null)
1265{
1266 struct u132_endp *endp = data;
1267 struct u132 *u132 = endp->u132;
1268 u8 address = u132->addr[endp->usb_addr].address;
1269 down(&u132->scheduler_lock);
1270 if (u132->going > 1) {
1271 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1272 , u132->going);
1273 up(&u132->scheduler_lock);
1274 u132_hcd_forget_urb(u132, endp, urb, -ENODEV);
1275 return;
1276 } else if (endp->dequeueing) {
1277 endp->dequeueing = 0;
1278 up(&u132->scheduler_lock);
1279 u132_hcd_giveback_urb(u132, endp, urb, -EINTR);
1280 return;
1281 } else if (u132->going > 0) {
1282 dev_err(&u132->platform_dev->dev, "device is being removed urb="
1283 "%p status=%d\n", urb, urb->status);
1284 up(&u132->scheduler_lock);
1285 u132_hcd_giveback_urb(u132, endp, urb, -ENODEV);
1286 return;
1287 } else if (urb->status == -EINPROGRESS) {
1288 int retval;
1289 struct u132_ring *ring = endp->ring;
1290 up(&u132->scheduler_lock);
1291 retval = usb_ftdi_elan_edset_input(u132->platform_dev,
1292 ring->number, endp, urb, address, endp->usb_endp, 0,
1293 u132_hcd_initial_input_recv);
1294 if (retval == 0) {
1295 } else
1296 u132_hcd_giveback_urb(u132, endp, urb, retval);
1297 return;
1298 } else {
1299 dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu"
1300 "s=%d\n", urb, urb->status);
1301 up(&u132->scheduler_lock);
1302 u132_hcd_giveback_urb(u132, endp, urb, urb->status);
1303 return;
1304 }
1305}
1306
Tony Olechd774efe2006-09-13 11:27:35 +01001307/*
1308* this work function is only executed from the work queue
1309*
1310*/
David Howellsc4028952006-11-22 14:57:56 +00001311static void u132_hcd_ring_work_scheduler(struct work_struct *work)
Tony Olechd774efe2006-09-13 11:27:35 +01001312{
David Howellsc4028952006-11-22 14:57:56 +00001313 struct u132_ring *ring =
1314 container_of(work, struct u132_ring, scheduler.work);
Tony Olechd774efe2006-09-13 11:27:35 +01001315 struct u132 *u132 = ring->u132;
1316 down(&u132->scheduler_lock);
1317 if (ring->in_use) {
1318 up(&u132->scheduler_lock);
1319 u132_ring_put_kref(u132, ring);
1320 return;
1321 } else if (ring->curr_endp) {
1322 struct u132_endp *last_endp = ring->curr_endp;
1323 struct list_head *scan;
1324 struct list_head *head = &last_endp->endp_ring;
1325 unsigned long wakeup = 0;
1326 list_for_each(scan, head) {
1327 struct u132_endp *endp = list_entry(scan,
1328 struct u132_endp, endp_ring);
1329 if (endp->queue_next == endp->queue_last) {
1330 } else if ((endp->delayed == 0)
1331 || time_after_eq(jiffies, endp->jiffies)) {
1332 ring->curr_endp = endp;
1333 u132_endp_cancel_work(u132, last_endp);
1334 u132_endp_queue_work(u132, last_endp, 0);
1335 up(&u132->scheduler_lock);
1336 u132_ring_put_kref(u132, ring);
1337 return;
1338 } else {
1339 unsigned long delta = endp->jiffies - jiffies;
1340 if (delta > wakeup)
1341 wakeup = delta;
1342 }
1343 }
1344 if (last_endp->queue_next == last_endp->queue_last) {
1345 } else if ((last_endp->delayed == 0) || time_after_eq(jiffies,
1346 last_endp->jiffies)) {
1347 u132_endp_cancel_work(u132, last_endp);
1348 u132_endp_queue_work(u132, last_endp, 0);
1349 up(&u132->scheduler_lock);
1350 u132_ring_put_kref(u132, ring);
1351 return;
1352 } else {
1353 unsigned long delta = last_endp->jiffies - jiffies;
1354 if (delta > wakeup)
1355 wakeup = delta;
1356 }
1357 if (wakeup > 0) {
1358 u132_ring_requeue_work(u132, ring, wakeup);
1359 up(&u132->scheduler_lock);
1360 return;
1361 } else {
1362 up(&u132->scheduler_lock);
1363 u132_ring_put_kref(u132, ring);
1364 return;
1365 }
1366 } else {
1367 up(&u132->scheduler_lock);
1368 u132_ring_put_kref(u132, ring);
1369 return;
1370 }
1371}
1372
David Howellsc4028952006-11-22 14:57:56 +00001373static void u132_hcd_endp_work_scheduler(struct work_struct *work)
Tony Olechd774efe2006-09-13 11:27:35 +01001374{
1375 struct u132_ring *ring;
David Howellsc4028952006-11-22 14:57:56 +00001376 struct u132_endp *endp =
1377 container_of(work, struct u132_endp, scheduler.work);
Tony Olechd774efe2006-09-13 11:27:35 +01001378 struct u132 *u132 = endp->u132;
1379 down(&u132->scheduler_lock);
1380 ring = endp->ring;
1381 if (endp->edset_flush) {
1382 endp->edset_flush = 0;
1383 if (endp->dequeueing)
1384 usb_ftdi_elan_edset_flush(u132->platform_dev,
1385 ring->number, endp);
1386 up(&u132->scheduler_lock);
1387 u132_endp_put_kref(u132, endp);
1388 return;
1389 } else if (endp->active) {
1390 up(&u132->scheduler_lock);
1391 u132_endp_put_kref(u132, endp);
1392 return;
1393 } else if (ring->in_use) {
1394 up(&u132->scheduler_lock);
1395 u132_endp_put_kref(u132, endp);
1396 return;
1397 } else if (endp->queue_next == endp->queue_last) {
1398 up(&u132->scheduler_lock);
1399 u132_endp_put_kref(u132, endp);
1400 return;
1401 } else if (endp->pipetype == PIPE_INTERRUPT) {
1402 u8 address = u132->addr[endp->usb_addr].address;
1403 if (ring->in_use) {
1404 up(&u132->scheduler_lock);
1405 u132_endp_put_kref(u132, endp);
1406 return;
1407 } else {
1408 int retval;
1409 struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
1410 endp->queue_next];
1411 endp->active = 1;
1412 ring->curr_endp = endp;
1413 ring->in_use = 1;
1414 up(&u132->scheduler_lock);
1415 retval = edset_single(u132, ring, endp, urb, address,
1416 endp->toggle_bits, u132_hcd_interrupt_recv);
1417 if (retval == 0) {
1418 } else
1419 u132_hcd_giveback_urb(u132, endp, urb, retval);
1420 return;
1421 }
1422 } else if (endp->pipetype == PIPE_CONTROL) {
1423 u8 address = u132->addr[endp->usb_addr].address;
1424 if (ring->in_use) {
1425 up(&u132->scheduler_lock);
1426 u132_endp_put_kref(u132, endp);
1427 return;
1428 } else if (address == 0) {
1429 int retval;
1430 struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
1431 endp->queue_next];
1432 endp->active = 1;
1433 ring->curr_endp = endp;
1434 ring->in_use = 1;
1435 up(&u132->scheduler_lock);
1436 retval = edset_setup(u132, ring, endp, urb, address,
1437 0x2, u132_hcd_initial_setup_sent);
1438 if (retval == 0) {
1439 } else
1440 u132_hcd_giveback_urb(u132, endp, urb, retval);
1441 return;
1442 } else if (endp->usb_addr == 0) {
1443 int retval;
1444 struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
1445 endp->queue_next];
1446 endp->active = 1;
1447 ring->curr_endp = endp;
1448 ring->in_use = 1;
1449 up(&u132->scheduler_lock);
1450 retval = edset_setup(u132, ring, endp, urb, 0, 0x2,
1451 u132_hcd_enumeration_address_sent);
1452 if (retval == 0) {
1453 } else
1454 u132_hcd_giveback_urb(u132, endp, urb, retval);
1455 return;
1456 } else {
1457 int retval;
1458 u8 address = u132->addr[endp->usb_addr].address;
1459 struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK &
1460 endp->queue_next];
1461 endp->active = 1;
1462 ring->curr_endp = endp;
1463 ring->in_use = 1;
1464 up(&u132->scheduler_lock);
1465 retval = edset_setup(u132, ring, endp, urb, address,
1466 0x2, u132_hcd_configure_setup_sent);
1467 if (retval == 0) {
1468 } else
1469 u132_hcd_giveback_urb(u132, endp, urb, retval);
1470 return;
1471 }
1472 } else {
1473 if (endp->input) {
1474 u8 address = u132->addr[endp->usb_addr].address;
1475 if (ring->in_use) {
1476 up(&u132->scheduler_lock);
1477 u132_endp_put_kref(u132, endp);
1478 return;
1479 } else {
1480 int retval;
1481 struct urb *urb = endp->urb_list[
1482 ENDP_QUEUE_MASK & endp->queue_next];
1483 endp->active = 1;
1484 ring->curr_endp = endp;
1485 ring->in_use = 1;
1486 up(&u132->scheduler_lock);
1487 retval = edset_input(u132, ring, endp, urb,
1488 address, endp->toggle_bits,
1489 u132_hcd_bulk_input_recv);
1490 if (retval == 0) {
1491 } else
1492 u132_hcd_giveback_urb(u132, endp, urb,
1493 retval);
1494 return;
1495 }
1496 } else { /* output pipe */
1497 u8 address = u132->addr[endp->usb_addr].address;
1498 if (ring->in_use) {
1499 up(&u132->scheduler_lock);
1500 u132_endp_put_kref(u132, endp);
1501 return;
1502 } else {
1503 int retval;
1504 struct urb *urb = endp->urb_list[
1505 ENDP_QUEUE_MASK & endp->queue_next];
1506 endp->active = 1;
1507 ring->curr_endp = endp;
1508 ring->in_use = 1;
1509 up(&u132->scheduler_lock);
1510 retval = edset_output(u132, ring, endp, urb,
1511 address, endp->toggle_bits,
1512 u132_hcd_bulk_output_sent);
1513 if (retval == 0) {
1514 } else
1515 u132_hcd_giveback_urb(u132, endp, urb,
1516 retval);
1517 return;
1518 }
1519 }
1520 }
1521}
1522
1523static void port_power(struct u132 *u132, int pn, int is_on)
1524{
1525 u132->port[pn].power = is_on;
1526}
1527
1528static void u132_power(struct u132 *u132, int is_on)
1529{
1530 struct usb_hcd *hcd = u132_to_hcd(u132)
1531 ; /* hub is inactive unless the port is powered */
1532 if (is_on) {
1533 if (u132->power)
1534 return;
1535 u132->power = 1;
1536 hcd->self.controller->power.power_state = PMSG_ON;
1537 } else {
1538 u132->power = 0;
1539 hcd->state = HC_STATE_HALT;
1540 hcd->self.controller->power.power_state = PMSG_SUSPEND;
1541 }
1542}
1543
1544static int u132_periodic_reinit(struct u132 *u132)
1545{
1546 int retval;
1547 u32 fi = u132->hc_fminterval & 0x03fff;
1548 u32 fit;
1549 u32 fminterval;
1550 retval = u132_read_pcimem(u132, fminterval, &fminterval);
1551 if (retval)
1552 return retval;
1553 fit = fminterval & FIT;
1554 retval = u132_write_pcimem(u132, fminterval,
1555 (fit ^ FIT) | u132->hc_fminterval);
1556 if (retval)
1557 return retval;
1558 retval = u132_write_pcimem(u132, periodicstart,
1559 ((9 *fi) / 10) & 0x3fff);
1560 if (retval)
1561 return retval;
1562 return 0;
1563}
1564
1565static char *hcfs2string(int state)
1566{
1567 switch (state) {
1568 case OHCI_USB_RESET:
1569 return "reset";
1570 case OHCI_USB_RESUME:
1571 return "resume";
1572 case OHCI_USB_OPER:
1573 return "operational";
1574 case OHCI_USB_SUSPEND:
1575 return "suspend";
1576 }
1577 return "?";
1578}
1579
Tony Olechd774efe2006-09-13 11:27:35 +01001580static int u132_init(struct u132 *u132)
1581{
1582 int retval;
1583 u32 control;
1584 u132_disable(u132);
Tony Olech4b873612006-12-06 13:16:22 +00001585 u132->next_statechange = jiffies;
Tony Olechd774efe2006-09-13 11:27:35 +01001586 retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE);
1587 if (retval)
1588 return retval;
1589 retval = u132_read_pcimem(u132, control, &control);
1590 if (retval)
1591 return retval;
1592 if (u132->num_ports == 0) {
1593 u32 rh_a = -1;
1594 retval = u132_read_pcimem(u132, roothub.a, &rh_a);
1595 if (retval)
1596 return retval;
1597 u132->num_ports = rh_a & RH_A_NDP;
1598 retval = read_roothub_info(u132);
1599 if (retval)
1600 return retval;
1601 }
1602 if (u132->num_ports > MAX_U132_PORTS) {
1603 return -EINVAL;
1604 }
1605 return 0;
1606}
1607
1608
1609/* Start an OHCI controller, set the BUS operational
1610* resets USB and controller
1611* enable interrupts
1612*/
1613static int u132_run(struct u132 *u132)
1614{
1615 int retval;
1616 u32 control;
1617 u32 status;
1618 u32 fminterval;
1619 u32 periodicstart;
1620 u32 cmdstatus;
1621 u32 roothub_a;
1622 int mask = OHCI_INTR_INIT;
1623 int first = u132->hc_fminterval == 0;
1624 int sleep_time = 0;
1625 int reset_timeout = 30; /* ... allow extra time */
1626 u132_disable(u132);
1627 if (first) {
1628 u32 temp;
1629 retval = u132_read_pcimem(u132, fminterval, &temp);
1630 if (retval)
1631 return retval;
1632 u132->hc_fminterval = temp & 0x3fff;
1633 if (u132->hc_fminterval != FI) {
1634 }
1635 u132->hc_fminterval |= FSMP(u132->hc_fminterval) << 16;
1636 }
1637 retval = u132_read_pcimem(u132, control, &u132->hc_control);
1638 if (retval)
1639 return retval;
1640 dev_info(&u132->platform_dev->dev, "resetting from state '%s', control "
1641 "= %08X\n", hcfs2string(u132->hc_control & OHCI_CTRL_HCFS),
1642 u132->hc_control);
1643 switch (u132->hc_control & OHCI_CTRL_HCFS) {
1644 case OHCI_USB_OPER:
1645 sleep_time = 0;
1646 break;
1647 case OHCI_USB_SUSPEND:
1648 case OHCI_USB_RESUME:
1649 u132->hc_control &= OHCI_CTRL_RWC;
1650 u132->hc_control |= OHCI_USB_RESUME;
1651 sleep_time = 10;
1652 break;
1653 default:
1654 u132->hc_control &= OHCI_CTRL_RWC;
1655 u132->hc_control |= OHCI_USB_RESET;
1656 sleep_time = 50;
1657 break;
1658 }
1659 retval = u132_write_pcimem(u132, control, u132->hc_control);
1660 if (retval)
1661 return retval;
1662 retval = u132_read_pcimem(u132, control, &control);
1663 if (retval)
1664 return retval;
1665 msleep(sleep_time);
1666 retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
1667 if (retval)
1668 return retval;
1669 if (!(roothub_a & RH_A_NPS)) {
1670 int temp; /* power down each port */
1671 for (temp = 0; temp < u132->num_ports; temp++) {
1672 retval = u132_write_pcimem(u132,
1673 roothub.portstatus[temp], RH_PS_LSDA);
1674 if (retval)
1675 return retval;
1676 }
1677 }
1678 retval = u132_read_pcimem(u132, control, &control);
1679 if (retval)
1680 return retval;
1681 retry:retval = u132_read_pcimem(u132, cmdstatus, &status);
1682 if (retval)
1683 return retval;
Tony Olech4b873612006-12-06 13:16:22 +00001684 retval = u132_write_pcimem(u132, cmdstatus, OHCI_HCR);
Tony Olechd774efe2006-09-13 11:27:35 +01001685 if (retval)
1686 return retval;
1687 extra:{
1688 retval = u132_read_pcimem(u132, cmdstatus, &status);
1689 if (retval)
1690 return retval;
1691 if (0 != (status & OHCI_HCR)) {
1692 if (--reset_timeout == 0) {
1693 dev_err(&u132->platform_dev->dev, "USB HC reset"
1694 " timed out!\n");
1695 return -ENODEV;
1696 } else {
1697 msleep(5);
1698 goto extra;
1699 }
1700 }
1701 }
1702 if (u132->flags & OHCI_QUIRK_INITRESET) {
1703 retval = u132_write_pcimem(u132, control, u132->hc_control);
1704 if (retval)
1705 return retval;
1706 retval = u132_read_pcimem(u132, control, &control);
1707 if (retval)
1708 return retval;
1709 }
1710 retval = u132_write_pcimem(u132, ed_controlhead, 0x00000000);
1711 if (retval)
1712 return retval;
1713 retval = u132_write_pcimem(u132, ed_bulkhead, 0x11000000);
1714 if (retval)
1715 return retval;
1716 retval = u132_write_pcimem(u132, hcca, 0x00000000);
1717 if (retval)
1718 return retval;
1719 retval = u132_periodic_reinit(u132);
1720 if (retval)
1721 return retval;
1722 retval = u132_read_pcimem(u132, fminterval, &fminterval);
1723 if (retval)
1724 return retval;
1725 retval = u132_read_pcimem(u132, periodicstart, &periodicstart);
1726 if (retval)
1727 return retval;
1728 if (0 == (fminterval & 0x3fff0000) || 0 == periodicstart) {
1729 if (!(u132->flags & OHCI_QUIRK_INITRESET)) {
1730 u132->flags |= OHCI_QUIRK_INITRESET;
1731 goto retry;
1732 } else
1733 dev_err(&u132->platform_dev->dev, "init err(%08x %04x)"
1734 "\n", fminterval, periodicstart);
1735 } /* start controller operations */
1736 u132->hc_control &= OHCI_CTRL_RWC;
1737 u132->hc_control |= OHCI_CONTROL_INIT | OHCI_CTRL_BLE | OHCI_USB_OPER;
1738 retval = u132_write_pcimem(u132, control, u132->hc_control);
1739 if (retval)
1740 return retval;
Tony Olech4b873612006-12-06 13:16:22 +00001741 retval = u132_write_pcimem(u132, cmdstatus, OHCI_BLF);
Tony Olechd774efe2006-09-13 11:27:35 +01001742 if (retval)
1743 return retval;
1744 retval = u132_read_pcimem(u132, cmdstatus, &cmdstatus);
1745 if (retval)
1746 return retval;
1747 retval = u132_read_pcimem(u132, control, &control);
1748 if (retval)
1749 return retval;
1750 u132_to_hcd(u132)->state = HC_STATE_RUNNING;
1751 retval = u132_write_pcimem(u132, roothub.status, RH_HS_DRWE);
1752 if (retval)
1753 return retval;
1754 retval = u132_write_pcimem(u132, intrstatus, mask);
1755 if (retval)
1756 return retval;
1757 retval = u132_write_pcimem(u132, intrdisable,
1758 OHCI_INTR_MIE | OHCI_INTR_OC | OHCI_INTR_RHSC | OHCI_INTR_FNO |
1759 OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_SF | OHCI_INTR_WDH |
1760 OHCI_INTR_SO);
1761 if (retval)
1762 return retval; /* handle root hub init quirks ... */
1763 retval = u132_read_pcimem(u132, roothub.a, &roothub_a);
1764 if (retval)
1765 return retval;
1766 roothub_a &= ~(RH_A_PSM | RH_A_OCPM);
1767 if (u132->flags & OHCI_QUIRK_SUPERIO) {
1768 roothub_a |= RH_A_NOCP;
1769 roothub_a &= ~(RH_A_POTPGT | RH_A_NPS);
1770 retval = u132_write_pcimem(u132, roothub.a, roothub_a);
1771 if (retval)
1772 return retval;
1773 } else if ((u132->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
1774 roothub_a |= RH_A_NPS;
1775 retval = u132_write_pcimem(u132, roothub.a, roothub_a);
1776 if (retval)
1777 return retval;
1778 }
1779 retval = u132_write_pcimem(u132, roothub.status, RH_HS_LPSC);
1780 if (retval)
1781 return retval;
1782 retval = u132_write_pcimem(u132, roothub.b,
1783 (roothub_a & RH_A_NPS) ? 0 : RH_B_PPCM);
1784 if (retval)
1785 return retval;
1786 retval = u132_read_pcimem(u132, control, &control);
1787 if (retval)
1788 return retval;
1789 mdelay((roothub_a >> 23) & 0x1fe);
1790 u132_to_hcd(u132)->state = HC_STATE_RUNNING;
1791 return 0;
1792}
1793
1794static void u132_hcd_stop(struct usb_hcd *hcd)
1795{
1796 struct u132 *u132 = hcd_to_u132(hcd);
1797 if (u132->going > 1) {
Tony Olech4b873612006-12-06 13:16:22 +00001798 dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p) has b"
1799 "een removed %d\n", u132, hcd, u132->going);
Tony Olechd774efe2006-09-13 11:27:35 +01001800 } else if (u132->going > 0) {
1801 dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
1802 "ed\n", hcd);
1803 } else {
1804 down(&u132->sw_lock);
1805 msleep(100);
1806 u132_power(u132, 0);
1807 up(&u132->sw_lock);
1808 }
1809}
1810
1811static int u132_hcd_start(struct usb_hcd *hcd)
1812{
1813 struct u132 *u132 = hcd_to_u132(hcd);
1814 if (u132->going > 1) {
1815 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1816 , u132->going);
1817 return -ENODEV;
1818 } else if (u132->going > 0) {
1819 dev_err(&u132->platform_dev->dev, "device is being removed\n");
1820 return -ESHUTDOWN;
1821 } else if (hcd->self.controller) {
1822 int retval;
1823 struct platform_device *pdev =
1824 to_platform_device(hcd->self.controller);
1825 u16 vendor = ((struct u132_platform_data *)
1826 (pdev->dev.platform_data))->vendor;
1827 u16 device = ((struct u132_platform_data *)
1828 (pdev->dev.platform_data))->device;
1829 down(&u132->sw_lock);
1830 msleep(10);
1831 if (vendor == PCI_VENDOR_ID_AMD && device == 0x740c) {
1832 u132->flags = OHCI_QUIRK_AMD756;
1833 } else if (vendor == PCI_VENDOR_ID_OPTI && device == 0xc861) {
1834 dev_err(&u132->platform_dev->dev, "WARNING: OPTi workar"
1835 "ounds unavailable\n");
1836 } else if (vendor == PCI_VENDOR_ID_COMPAQ && device == 0xa0f8)
1837 u132->flags |= OHCI_QUIRK_ZFMICRO;
1838 retval = u132_run(u132);
1839 if (retval) {
1840 u132_disable(u132);
1841 u132->going = 1;
1842 }
1843 msleep(100);
1844 up(&u132->sw_lock);
1845 return retval;
1846 } else {
1847 dev_err(&u132->platform_dev->dev, "platform_device missing\n");
1848 return -ENODEV;
1849 }
1850}
1851
1852static int u132_hcd_reset(struct usb_hcd *hcd)
1853{
1854 struct u132 *u132 = hcd_to_u132(hcd);
1855 if (u132->going > 1) {
1856 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
1857 , u132->going);
1858 return -ENODEV;
1859 } else if (u132->going > 0) {
1860 dev_err(&u132->platform_dev->dev, "device is being removed\n");
1861 return -ESHUTDOWN;
1862 } else {
1863 int retval;
1864 down(&u132->sw_lock);
1865 retval = u132_init(u132);
1866 if (retval) {
1867 u132_disable(u132);
1868 u132->going = 1;
1869 }
1870 up(&u132->sw_lock);
1871 return retval;
1872 }
1873}
1874
1875static int create_endpoint_and_queue_int(struct u132 *u132,
1876 struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
1877 struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
1878 gfp_t mem_flags)
1879{
1880 struct u132_ring *ring;
1881 unsigned long irqs;
1882 u8 endp_number = ++u132->num_endpoints;
1883 struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
1884 kmalloc(sizeof(struct u132_endp), mem_flags);
1885 if (!endp) {
1886 return -ENOMEM;
1887 }
David Howellsc4028952006-11-22 14:57:56 +00001888 INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
Tony Olechd774efe2006-09-13 11:27:35 +01001889 spin_lock_init(&endp->queue_lock.slock);
1890 INIT_LIST_HEAD(&endp->urb_more);
1891 ring = endp->ring = &u132->ring[0];
1892 if (ring->curr_endp) {
1893 list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
1894 } else {
1895 INIT_LIST_HEAD(&endp->endp_ring);
1896 ring->curr_endp = endp;
1897 }
1898 ring->length += 1;
1899 endp->dequeueing = 0;
1900 endp->edset_flush = 0;
1901 endp->active = 0;
1902 endp->delayed = 0;
1903 endp->endp_number = endp_number;
1904 endp->u132 = u132;
1905 endp->hep = hep;
1906 endp->pipetype = usb_pipetype(urb->pipe);
1907 u132_endp_init_kref(u132, endp);
1908 if (usb_pipein(urb->pipe)) {
1909 endp->toggle_bits = 0x2;
1910 usb_settoggle(udev->usb_device, usb_endp, 0, 0);
1911 endp->input = 1;
1912 endp->output = 0;
1913 udev->endp_number_in[usb_endp] = endp_number;
1914 u132_udev_get_kref(u132, udev);
1915 } else {
1916 endp->toggle_bits = 0x2;
1917 usb_settoggle(udev->usb_device, usb_endp, 1, 0);
1918 endp->input = 0;
1919 endp->output = 1;
1920 udev->endp_number_out[usb_endp] = endp_number;
1921 u132_udev_get_kref(u132, udev);
1922 }
1923 urb->hcpriv = u132;
1924 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
1925 endp->delayed = 1;
1926 endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
1927 endp->udev_number = address;
1928 endp->usb_addr = usb_addr;
1929 endp->usb_endp = usb_endp;
1930 endp->queue_size = 1;
1931 endp->queue_last = 0;
1932 endp->queue_next = 0;
1933 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
1934 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
1935 u132_endp_queue_work(u132, endp, msecs_to_jiffies(urb->interval));
1936 return 0;
1937}
1938
1939static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
1940 struct usb_host_endpoint *hep, struct urb *urb,
1941 struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
1942 u8 usb_endp, u8 address)
1943{
1944 urb->hcpriv = u132;
1945 endp->delayed = 1;
1946 endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
1947 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
1948 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
1949 } else {
1950 struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
1951 GFP_ATOMIC);
1952 if (urbq == NULL) {
1953 endp->queue_size -= 1;
1954 return -ENOMEM;
1955 } else {
1956 list_add_tail(&urbq->urb_more, &endp->urb_more);
1957 urbq->urb = urb;
1958 }
1959 }
1960 return 0;
1961}
1962
1963static int create_endpoint_and_queue_bulk(struct u132 *u132,
1964 struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
1965 struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
1966 gfp_t mem_flags)
1967{
1968 int ring_number;
1969 struct u132_ring *ring;
1970 unsigned long irqs;
1971 u8 endp_number = ++u132->num_endpoints;
1972 struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
1973 kmalloc(sizeof(struct u132_endp), mem_flags);
1974 if (!endp) {
1975 return -ENOMEM;
1976 }
David Howellsc4028952006-11-22 14:57:56 +00001977 INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
Tony Olechd774efe2006-09-13 11:27:35 +01001978 spin_lock_init(&endp->queue_lock.slock);
1979 INIT_LIST_HEAD(&endp->urb_more);
1980 endp->dequeueing = 0;
1981 endp->edset_flush = 0;
1982 endp->active = 0;
1983 endp->delayed = 0;
1984 endp->endp_number = endp_number;
1985 endp->u132 = u132;
1986 endp->hep = hep;
1987 endp->pipetype = usb_pipetype(urb->pipe);
1988 u132_endp_init_kref(u132, endp);
1989 if (usb_pipein(urb->pipe)) {
1990 endp->toggle_bits = 0x2;
1991 usb_settoggle(udev->usb_device, usb_endp, 0, 0);
1992 ring_number = 3;
1993 endp->input = 1;
1994 endp->output = 0;
1995 udev->endp_number_in[usb_endp] = endp_number;
1996 u132_udev_get_kref(u132, udev);
1997 } else {
1998 endp->toggle_bits = 0x2;
1999 usb_settoggle(udev->usb_device, usb_endp, 1, 0);
2000 ring_number = 2;
2001 endp->input = 0;
2002 endp->output = 1;
2003 udev->endp_number_out[usb_endp] = endp_number;
2004 u132_udev_get_kref(u132, udev);
2005 }
2006 ring = endp->ring = &u132->ring[ring_number - 1];
2007 if (ring->curr_endp) {
2008 list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
2009 } else {
2010 INIT_LIST_HEAD(&endp->endp_ring);
2011 ring->curr_endp = endp;
2012 }
2013 ring->length += 1;
2014 urb->hcpriv = u132;
2015 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
2016 endp->udev_number = address;
2017 endp->usb_addr = usb_addr;
2018 endp->usb_endp = usb_endp;
2019 endp->queue_size = 1;
2020 endp->queue_last = 0;
2021 endp->queue_next = 0;
2022 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
2023 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2024 u132_endp_queue_work(u132, endp, 0);
2025 return 0;
2026}
2027
2028static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
2029 struct usb_host_endpoint *hep, struct urb *urb,
2030 struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
2031 u8 usb_endp, u8 address)
2032{
2033 urb->hcpriv = u132;
2034 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
2035 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
2036 } else {
2037 struct u132_urbq *urbq = kmalloc(sizeof(struct u132_urbq),
2038 GFP_ATOMIC);
2039 if (urbq == NULL) {
2040 endp->queue_size -= 1;
2041 return -ENOMEM;
2042 } else {
2043 list_add_tail(&urbq->urb_more, &endp->urb_more);
2044 urbq->urb = urb;
2045 }
2046 }
2047 return 0;
2048}
2049
2050static int create_endpoint_and_queue_control(struct u132 *u132,
2051 struct usb_host_endpoint *hep, struct urb *urb,
2052 struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
2053 gfp_t mem_flags)
2054{
2055 struct u132_ring *ring;
2056 u8 endp_number = ++u132->num_endpoints;
2057 struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
2058 kmalloc(sizeof(struct u132_endp), mem_flags);
2059 if (!endp) {
2060 return -ENOMEM;
2061 }
David Howellsc4028952006-11-22 14:57:56 +00002062 INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
Tony Olechd774efe2006-09-13 11:27:35 +01002063 spin_lock_init(&endp->queue_lock.slock);
2064 INIT_LIST_HEAD(&endp->urb_more);
2065 ring = endp->ring = &u132->ring[0];
2066 if (ring->curr_endp) {
2067 list_add_tail(&endp->endp_ring, &ring->curr_endp->endp_ring);
2068 } else {
2069 INIT_LIST_HEAD(&endp->endp_ring);
2070 ring->curr_endp = endp;
2071 }
2072 ring->length += 1;
2073 endp->dequeueing = 0;
2074 endp->edset_flush = 0;
2075 endp->active = 0;
2076 endp->delayed = 0;
2077 endp->endp_number = endp_number;
2078 endp->u132 = u132;
2079 endp->hep = hep;
2080 u132_endp_init_kref(u132, endp);
2081 u132_endp_get_kref(u132, endp);
2082 if (usb_addr == 0) {
2083 unsigned long irqs;
2084 u8 address = u132->addr[usb_addr].address;
2085 struct u132_udev *udev = &u132->udev[address];
2086 endp->udev_number = address;
2087 endp->usb_addr = usb_addr;
2088 endp->usb_endp = usb_endp;
2089 endp->input = 1;
2090 endp->output = 1;
2091 endp->pipetype = usb_pipetype(urb->pipe);
2092 u132_udev_init_kref(u132, udev);
2093 u132_udev_get_kref(u132, udev);
2094 udev->endp_number_in[usb_endp] = endp_number;
2095 udev->endp_number_out[usb_endp] = endp_number;
2096 urb->hcpriv = u132;
2097 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
2098 endp->queue_size = 1;
2099 endp->queue_last = 0;
2100 endp->queue_next = 0;
2101 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
2102 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2103 u132_endp_queue_work(u132, endp, 0);
2104 return 0;
2105 } else { /*(usb_addr > 0) */
2106 unsigned long irqs;
2107 u8 address = u132->addr[usb_addr].address;
2108 struct u132_udev *udev = &u132->udev[address];
2109 endp->udev_number = address;
2110 endp->usb_addr = usb_addr;
2111 endp->usb_endp = usb_endp;
2112 endp->input = 1;
2113 endp->output = 1;
2114 endp->pipetype = usb_pipetype(urb->pipe);
2115 u132_udev_get_kref(u132, udev);
2116 udev->enumeration = 2;
2117 udev->endp_number_in[usb_endp] = endp_number;
2118 udev->endp_number_out[usb_endp] = endp_number;
2119 urb->hcpriv = u132;
2120 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
2121 endp->queue_size = 1;
2122 endp->queue_last = 0;
2123 endp->queue_next = 0;
2124 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] = urb;
2125 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2126 u132_endp_queue_work(u132, endp, 0);
2127 return 0;
2128 }
2129}
2130
2131static int queue_control_on_old_endpoint(struct u132 *u132,
2132 struct usb_host_endpoint *hep, struct urb *urb,
2133 struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
2134 u8 usb_endp)
2135{
2136 if (usb_addr == 0) {
2137 if (usb_pipein(urb->pipe)) {
2138 urb->hcpriv = u132;
2139 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
2140 endp->urb_list[ENDP_QUEUE_MASK &
2141 endp->queue_last++] = urb;
2142 } else {
2143 struct u132_urbq *urbq =
2144 kmalloc(sizeof(struct u132_urbq),
2145 GFP_ATOMIC);
2146 if (urbq == NULL) {
2147 endp->queue_size -= 1;
2148 return -ENOMEM;
2149 } else {
2150 list_add_tail(&urbq->urb_more,
2151 &endp->urb_more);
2152 urbq->urb = urb;
2153 }
2154 }
2155 return 0;
2156 } else { /* usb_pipeout(urb->pipe) */
2157 struct u132_addr *addr = &u132->addr[usb_dev->devnum];
2158 int I = MAX_U132_UDEVS;
2159 int i = 0;
2160 while (--I > 0) {
2161 struct u132_udev *udev = &u132->udev[++i];
2162 if (udev->usb_device) {
2163 continue;
2164 } else {
2165 udev->enumeration = 1;
2166 u132->addr[0].address = i;
2167 endp->udev_number = i;
2168 udev->udev_number = i;
2169 udev->usb_addr = usb_dev->devnum;
2170 u132_udev_init_kref(u132, udev);
2171 udev->endp_number_in[usb_endp] =
2172 endp->endp_number;
2173 u132_udev_get_kref(u132, udev);
2174 udev->endp_number_out[usb_endp] =
2175 endp->endp_number;
2176 udev->usb_device = usb_dev;
2177 ((u8 *) (urb->setup_packet))[2] =
2178 addr->address = i;
2179 u132_udev_get_kref(u132, udev);
2180 break;
2181 }
2182 }
2183 if (I == 0) {
2184 dev_err(&u132->platform_dev->dev, "run out of d"
2185 "evice space\n");
2186 return -EINVAL;
2187 }
2188 urb->hcpriv = u132;
2189 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
2190 endp->urb_list[ENDP_QUEUE_MASK &
2191 endp->queue_last++] = urb;
2192 } else {
2193 struct u132_urbq *urbq =
2194 kmalloc(sizeof(struct u132_urbq),
2195 GFP_ATOMIC);
2196 if (urbq == NULL) {
2197 endp->queue_size -= 1;
2198 return -ENOMEM;
2199 } else {
2200 list_add_tail(&urbq->urb_more,
2201 &endp->urb_more);
2202 urbq->urb = urb;
2203 }
2204 }
2205 return 0;
2206 }
2207 } else { /*(usb_addr > 0) */
2208 u8 address = u132->addr[usb_addr].address;
2209 struct u132_udev *udev = &u132->udev[address];
2210 urb->hcpriv = u132;
2211 if (udev->enumeration == 2) {
2212 } else
2213 udev->enumeration = 2;
2214 if (endp->queue_size++ < ENDP_QUEUE_SIZE) {
2215 endp->urb_list[ENDP_QUEUE_MASK & endp->queue_last++] =
2216 urb;
2217 } else {
2218 struct u132_urbq *urbq =
2219 kmalloc(sizeof(struct u132_urbq), GFP_ATOMIC);
2220 if (urbq == NULL) {
2221 endp->queue_size -= 1;
2222 return -ENOMEM;
2223 } else {
2224 list_add_tail(&urbq->urb_more, &endp->urb_more);
2225 urbq->urb = urb;
2226 }
2227 }
2228 return 0;
2229 }
2230}
2231
2232static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
2233 struct urb *urb, gfp_t mem_flags)
2234{
2235 struct u132 *u132 = hcd_to_u132(hcd);
2236 if (irqs_disabled()) {
2237 if (__GFP_WAIT & mem_flags) {
2238 printk(KERN_ERR "invalid context for function that migh"
2239 "t sleep\n");
2240 return -EINVAL;
2241 }
2242 }
2243 if (u132->going > 1) {
2244 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2245 , u132->going);
2246 return -ENODEV;
2247 } else if (u132->going > 0) {
2248 dev_err(&u132->platform_dev->dev, "device is being removed urb="
2249 "%p status=%d\n", urb, urb->status);
2250 return -ESHUTDOWN;
2251 } else {
2252 u8 usb_addr = usb_pipedevice(urb->pipe);
2253 u8 usb_endp = usb_pipeendpoint(urb->pipe);
2254 struct usb_device *usb_dev = urb->dev;
2255 if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
2256 u8 address = u132->addr[usb_addr].address;
2257 struct u132_udev *udev = &u132->udev[address];
2258 struct u132_endp *endp = hep->hcpriv;
2259 urb->actual_length = 0;
2260 if (endp) {
2261 unsigned long irqs;
2262 int retval;
2263 spin_lock_irqsave(&endp->queue_lock.slock,
2264 irqs);
2265 retval = queue_int_on_old_endpoint(u132, udev,
2266 hep, urb, usb_dev, endp, usb_addr,
2267 usb_endp, address);
2268 spin_unlock_irqrestore(&endp->queue_lock.slock,
2269 irqs);
2270 if (retval) {
2271 return retval;
2272 } else {
2273 u132_endp_queue_work(u132, endp,
2274 msecs_to_jiffies(urb->interval))
2275 ;
2276 return 0;
2277 }
2278 } else if (u132->num_endpoints == MAX_U132_ENDPS) {
2279 return -EINVAL;
2280 } else { /*(endp == NULL) */
2281 return create_endpoint_and_queue_int(u132, udev,
2282 hep, urb, usb_dev, usb_addr, usb_endp,
2283 address, mem_flags);
2284 }
2285 } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
2286 dev_err(&u132->platform_dev->dev, "the hardware does no"
2287 "t support PIPE_ISOCHRONOUS\n");
2288 return -EINVAL;
2289 } else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
2290 u8 address = u132->addr[usb_addr].address;
2291 struct u132_udev *udev = &u132->udev[address];
2292 struct u132_endp *endp = hep->hcpriv;
2293 urb->actual_length = 0;
2294 if (endp) {
2295 unsigned long irqs;
2296 int retval;
2297 spin_lock_irqsave(&endp->queue_lock.slock,
2298 irqs);
2299 retval = queue_bulk_on_old_endpoint(u132, udev,
2300 hep, urb, usb_dev, endp, usb_addr,
2301 usb_endp, address);
2302 spin_unlock_irqrestore(&endp->queue_lock.slock,
2303 irqs);
2304 if (retval) {
2305 return retval;
2306 } else {
2307 u132_endp_queue_work(u132, endp, 0);
2308 return 0;
2309 }
2310 } else if (u132->num_endpoints == MAX_U132_ENDPS) {
2311 return -EINVAL;
2312 } else
2313 return create_endpoint_and_queue_bulk(u132,
2314 udev, hep, urb, usb_dev, usb_addr,
2315 usb_endp, address, mem_flags);
2316 } else {
2317 struct u132_endp *endp = hep->hcpriv;
2318 u16 urb_size = 8;
2319 u8 *b = urb->setup_packet;
2320 int i = 0;
2321 char data[30 *3 + 4];
2322 char *d = data;
2323 int m = (sizeof(data) - 1) / 3;
2324 int l = 0;
2325 data[0] = 0;
2326 while (urb_size-- > 0) {
2327 if (i > m) {
2328 } else if (i++ < m) {
2329 int w = sprintf(d, " %02X", *b++);
2330 d += w;
2331 l += w;
2332 } else
2333 d += sprintf(d, " ..");
2334 }
2335 if (endp) {
2336 unsigned long irqs;
2337 int retval;
2338 spin_lock_irqsave(&endp->queue_lock.slock,
2339 irqs);
2340 retval = queue_control_on_old_endpoint(u132,
2341 hep, urb, usb_dev, endp, usb_addr,
2342 usb_endp);
2343 spin_unlock_irqrestore(&endp->queue_lock.slock,
2344 irqs);
2345 if (retval) {
2346 return retval;
2347 } else {
2348 u132_endp_queue_work(u132, endp, 0);
2349 return 0;
2350 }
2351 } else if (u132->num_endpoints == MAX_U132_ENDPS) {
2352 return -EINVAL;
2353 } else
2354 return create_endpoint_and_queue_control(u132,
2355 hep, urb, usb_dev, usb_addr, usb_endp,
2356 mem_flags);
2357 }
2358 }
2359}
2360
2361static int dequeue_from_overflow_chain(struct u132 *u132,
2362 struct u132_endp *endp, struct urb *urb)
2363{
2364 struct list_head *scan;
2365 struct list_head *head = &endp->urb_more;
2366 list_for_each(scan, head) {
2367 struct u132_urbq *urbq = list_entry(scan, struct u132_urbq,
2368 urb_more);
2369 if (urbq->urb == urb) {
2370 struct usb_hcd *hcd = u132_to_hcd(u132);
2371 list_del(scan);
2372 endp->queue_size -= 1;
2373 urb->error_count = 0;
2374 urb->hcpriv = NULL;
David Howells7d12e782006-10-05 14:55:46 +01002375 usb_hcd_giveback_urb(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +01002376 return 0;
2377 } else
2378 continue;
2379 }
2380 dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]=%p ring"
2381 "[%d] %c%c usb_endp=%d usb_addr=%d size=%d next=%04X last=%04X"
2382 "\n", urb, endp->endp_number, endp, endp->ring->number,
2383 endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
2384 endp->usb_endp, endp->usb_addr, endp->queue_size,
2385 endp->queue_next, endp->queue_last);
2386 return -EINVAL;
2387}
2388
2389static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
2390 struct urb *urb)
2391{
2392 unsigned long irqs;
2393 spin_lock_irqsave(&endp->queue_lock.slock, irqs);
2394 if (endp->queue_size == 0) {
2395 dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
2396 "=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
2397 endp->endp_number, endp, endp->ring->number,
2398 endp->input ? 'I' : ' ', endp->output ? 'O' : ' ',
2399 endp->usb_endp, endp->usb_addr);
2400 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2401 return -EINVAL;
2402 }
2403 if (urb == endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]) {
2404 if (endp->active) {
2405 endp->dequeueing = 1;
2406 endp->edset_flush = 1;
2407 u132_endp_queue_work(u132, endp, 0);
2408 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2409 urb->hcpriv = NULL;
2410 return 0;
2411 } else {
2412 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2413 u132_hcd_abandon_urb(u132, endp, urb, urb->status);
2414 return 0;
2415 }
2416 } else {
2417 u16 queue_list = 0;
2418 u16 queue_size = endp->queue_size;
2419 u16 queue_scan = endp->queue_next;
2420 struct urb **urb_slot = NULL;
2421 while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
2422 if (urb == endp->urb_list[ENDP_QUEUE_MASK &
2423 ++queue_scan]) {
2424 urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
2425 queue_scan];
2426 break;
2427 } else
2428 continue;
2429 }
2430 while (++queue_list < ENDP_QUEUE_SIZE && --queue_size > 0) {
2431 *urb_slot = endp->urb_list[ENDP_QUEUE_MASK &
2432 ++queue_scan];
2433 urb_slot = &endp->urb_list[ENDP_QUEUE_MASK &
2434 queue_scan];
2435 }
2436 if (urb_slot) {
2437 struct usb_hcd *hcd = u132_to_hcd(u132);
2438 endp->queue_size -= 1;
2439 if (list_empty(&endp->urb_more)) {
2440 spin_unlock_irqrestore(&endp->queue_lock.slock,
2441 irqs);
2442 } else {
2443 struct list_head *next = endp->urb_more.next;
2444 struct u132_urbq *urbq = list_entry(next,
2445 struct u132_urbq, urb_more);
2446 list_del(next);
2447 *urb_slot = urbq->urb;
2448 spin_unlock_irqrestore(&endp->queue_lock.slock,
2449 irqs);
2450 kfree(urbq);
2451 } urb->error_count = 0;
2452 urb->hcpriv = NULL;
David Howells7d12e782006-10-05 14:55:46 +01002453 usb_hcd_giveback_urb(hcd, urb);
Tony Olechd774efe2006-09-13 11:27:35 +01002454 return 0;
2455 } else if (list_empty(&endp->urb_more)) {
2456 dev_err(&u132->platform_dev->dev, "urb=%p not found in "
2457 "endp[%d]=%p ring[%d] %c%c usb_endp=%d usb_addr"
2458 "=%d size=%d next=%04X last=%04X\n", urb,
2459 endp->endp_number, endp, endp->ring->number,
2460 endp->input ? 'I' : ' ',
2461 endp->output ? 'O' : ' ', endp->usb_endp,
2462 endp->usb_addr, endp->queue_size,
2463 endp->queue_next, endp->queue_last);
2464 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2465 return -EINVAL;
2466 } else {
2467 int retval = dequeue_from_overflow_chain(u132, endp,
2468 urb);
2469 spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
2470 return retval;
2471 }
2472 }
2473}
2474
2475static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
2476{
2477 struct u132 *u132 = hcd_to_u132(hcd);
2478 if (u132->going > 2) {
2479 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2480 , u132->going);
2481 return -ENODEV;
2482 } else {
2483 u8 usb_addr = usb_pipedevice(urb->pipe);
2484 u8 usb_endp = usb_pipeendpoint(urb->pipe);
2485 u8 address = u132->addr[usb_addr].address;
2486 struct u132_udev *udev = &u132->udev[address];
2487 if (usb_pipein(urb->pipe)) {
2488 u8 endp_number = udev->endp_number_in[usb_endp];
2489 struct u132_endp *endp = u132->endp[endp_number - 1];
2490 return u132_endp_urb_dequeue(u132, endp, urb);
2491 } else {
2492 u8 endp_number = udev->endp_number_out[usb_endp];
2493 struct u132_endp *endp = u132->endp[endp_number - 1];
2494 return u132_endp_urb_dequeue(u132, endp, urb);
2495 }
2496 }
2497}
2498
2499static void u132_endpoint_disable(struct usb_hcd *hcd,
2500 struct usb_host_endpoint *hep)
2501{
2502 struct u132 *u132 = hcd_to_u132(hcd);
2503 if (u132->going > 2) {
Tony Olech4b873612006-12-06 13:16:22 +00002504 dev_err(&u132->platform_dev->dev, "u132 device %p(hcd=%p hep=%p"
2505 ") has been removed %d\n", u132, hcd, hep,
2506 u132->going);
Tony Olechd774efe2006-09-13 11:27:35 +01002507 } else {
2508 struct u132_endp *endp = hep->hcpriv;
2509 if (endp)
2510 u132_endp_put_kref(u132, endp);
2511 }
2512}
2513
2514static int u132_get_frame(struct usb_hcd *hcd)
2515{
2516 struct u132 *u132 = hcd_to_u132(hcd);
2517 if (u132->going > 1) {
2518 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2519 , u132->going);
2520 return -ENODEV;
2521 } else if (u132->going > 0) {
2522 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2523 return -ESHUTDOWN;
2524 } else {
2525 int frame = 0;
2526 dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
2527 msleep(100);
2528 return frame;
2529 }
2530}
2531
2532static int u132_roothub_descriptor(struct u132 *u132,
2533 struct usb_hub_descriptor *desc)
2534{
2535 int retval;
2536 u16 temp;
2537 u32 rh_a = -1;
2538 u32 rh_b = -1;
2539 retval = u132_read_pcimem(u132, roothub.a, &rh_a);
2540 if (retval)
2541 return retval;
2542 desc->bDescriptorType = 0x29;
2543 desc->bPwrOn2PwrGood = (rh_a & RH_A_POTPGT) >> 24;
2544 desc->bHubContrCurrent = 0;
2545 desc->bNbrPorts = u132->num_ports;
2546 temp = 1 + (u132->num_ports / 8);
2547 desc->bDescLength = 7 + 2 *temp;
2548 temp = 0;
2549 if (rh_a & RH_A_NPS)
2550 temp |= 0x0002;
2551 if (rh_a & RH_A_PSM)
2552 temp |= 0x0001;
2553 if (rh_a & RH_A_NOCP) {
2554 temp |= 0x0010;
2555 } else if (rh_a & RH_A_OCPM)
2556 temp |= 0x0008;
2557 desc->wHubCharacteristics = cpu_to_le16(temp);
2558 retval = u132_read_pcimem(u132, roothub.b, &rh_b);
2559 if (retval)
2560 return retval;
2561 memset(desc->bitmap, 0xff, sizeof(desc->bitmap));
2562 desc->bitmap[0] = rh_b & RH_B_DR;
2563 if (u132->num_ports > 7) {
2564 desc->bitmap[1] = (rh_b & RH_B_DR) >> 8;
2565 desc->bitmap[2] = 0xff;
2566 } else
2567 desc->bitmap[1] = 0xff;
2568 return 0;
2569}
2570
2571static int u132_roothub_status(struct u132 *u132, __le32 *desc)
2572{
2573 u32 rh_status = -1;
2574 int ret_status = u132_read_pcimem(u132, roothub.status, &rh_status);
2575 *desc = cpu_to_le32(rh_status);
2576 return ret_status;
2577}
2578
2579static int u132_roothub_portstatus(struct u132 *u132, __le32 *desc, u16 wIndex)
2580{
2581 if (wIndex == 0 || wIndex > u132->num_ports) {
2582 return -EINVAL;
2583 } else {
2584 int port = wIndex - 1;
2585 u32 rh_portstatus = -1;
2586 int ret_portstatus = u132_read_pcimem(u132,
2587 roothub.portstatus[port], &rh_portstatus);
2588 *desc = cpu_to_le32(rh_portstatus);
2589 if (*(u16 *) (desc + 2)) {
2590 dev_info(&u132->platform_dev->dev, "Port %d Status Chan"
2591 "ge = %08X\n", port, *desc);
2592 }
2593 return ret_portstatus;
2594 }
2595}
2596
2597
2598/* this timer value might be vendor-specific ... */
2599#define PORT_RESET_HW_MSEC 10
2600#define PORT_RESET_MSEC 10
2601/* wrap-aware logic morphed from <linux/jiffies.h> */
2602#define tick_before(t1, t2) ((s16)(((s16)(t1))-((s16)(t2))) < 0)
2603static int u132_roothub_portreset(struct u132 *u132, int port_index)
2604{
2605 int retval;
2606 u32 fmnumber;
2607 u16 now;
2608 u16 reset_done;
2609 retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
2610 if (retval)
2611 return retval;
2612 now = fmnumber;
2613 reset_done = now + PORT_RESET_MSEC;
2614 do {
2615 u32 portstat;
2616 do {
2617 retval = u132_read_pcimem(u132,
2618 roothub.portstatus[port_index], &portstat);
2619 if (retval)
2620 return retval;
2621 if (RH_PS_PRS & portstat) {
2622 continue;
2623 } else
2624 break;
2625 } while (tick_before(now, reset_done));
2626 if (RH_PS_PRS & portstat)
2627 return -ENODEV;
2628 if (RH_PS_CCS & portstat) {
2629 if (RH_PS_PRSC & portstat) {
2630 retval = u132_write_pcimem(u132,
2631 roothub.portstatus[port_index],
2632 RH_PS_PRSC);
2633 if (retval)
2634 return retval;
2635 }
2636 } else
2637 break; /* start the next reset,
2638 sleep till it's probably done */
2639 retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
2640 RH_PS_PRS);
2641 if (retval)
2642 return retval;
2643 msleep(PORT_RESET_HW_MSEC);
2644 retval = u132_read_pcimem(u132, fmnumber, &fmnumber);
2645 if (retval)
2646 return retval;
2647 now = fmnumber;
2648 } while (tick_before(now, reset_done));
2649 return 0;
2650}
2651
2652static int u132_roothub_setportfeature(struct u132 *u132, u16 wValue,
2653 u16 wIndex)
2654{
2655 if (wIndex == 0 || wIndex > u132->num_ports) {
2656 return -EINVAL;
2657 } else {
2658 int retval;
2659 int port_index = wIndex - 1;
2660 struct u132_port *port = &u132->port[port_index];
2661 port->Status &= ~(1 << wValue);
2662 switch (wValue) {
2663 case USB_PORT_FEAT_SUSPEND:
2664 retval = u132_write_pcimem(u132,
2665 roothub.portstatus[port_index], RH_PS_PSS);
2666 if (retval)
2667 return retval;
2668 return 0;
2669 case USB_PORT_FEAT_POWER:
2670 retval = u132_write_pcimem(u132,
2671 roothub.portstatus[port_index], RH_PS_PPS);
2672 if (retval)
2673 return retval;
2674 return 0;
2675 case USB_PORT_FEAT_RESET:
2676 retval = u132_roothub_portreset(u132, port_index);
2677 if (retval)
2678 return retval;
2679 return 0;
2680 default:
2681 return -EPIPE;
2682 }
2683 }
2684}
2685
2686static int u132_roothub_clearportfeature(struct u132 *u132, u16 wValue,
2687 u16 wIndex)
2688{
2689 if (wIndex == 0 || wIndex > u132->num_ports) {
2690 return -EINVAL;
2691 } else {
2692 int port_index = wIndex - 1;
2693 u32 temp;
2694 int retval;
2695 struct u132_port *port = &u132->port[port_index];
2696 port->Status &= ~(1 << wValue);
2697 switch (wValue) {
2698 case USB_PORT_FEAT_ENABLE:
2699 temp = RH_PS_CCS;
2700 break;
2701 case USB_PORT_FEAT_C_ENABLE:
2702 temp = RH_PS_PESC;
2703 break;
2704 case USB_PORT_FEAT_SUSPEND:
2705 temp = RH_PS_POCI;
2706 if ((u132->hc_control & OHCI_CTRL_HCFS)
2707 != OHCI_USB_OPER) {
2708 dev_err(&u132->platform_dev->dev, "TODO resume_"
2709 "root_hub\n");
2710 }
2711 break;
2712 case USB_PORT_FEAT_C_SUSPEND:
2713 temp = RH_PS_PSSC;
2714 break;
2715 case USB_PORT_FEAT_POWER:
2716 temp = RH_PS_LSDA;
2717 break;
2718 case USB_PORT_FEAT_C_CONNECTION:
2719 temp = RH_PS_CSC;
2720 break;
2721 case USB_PORT_FEAT_C_OVER_CURRENT:
2722 temp = RH_PS_OCIC;
2723 break;
2724 case USB_PORT_FEAT_C_RESET:
2725 temp = RH_PS_PRSC;
2726 break;
2727 default:
2728 return -EPIPE;
2729 }
2730 retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
2731 temp);
2732 if (retval)
2733 return retval;
2734 return 0;
2735 }
2736}
2737
2738
2739/* the virtual root hub timer IRQ checks for hub status*/
2740static int u132_hub_status_data(struct usb_hcd *hcd, char *buf)
2741{
2742 struct u132 *u132 = hcd_to_u132(hcd);
2743 if (u132->going > 1) {
2744 dev_err(&u132->platform_dev->dev, "device hcd=%p has been remov"
2745 "ed %d\n", hcd, u132->going);
2746 return -ENODEV;
2747 } else if (u132->going > 0) {
2748 dev_err(&u132->platform_dev->dev, "device hcd=%p is being remov"
2749 "ed\n", hcd);
Tony Olechd774efe2006-09-13 11:27:35 +01002750 return -ESHUTDOWN;
2751 } else {
2752 int i, changed = 0, length = 1;
2753 if (u132->flags & OHCI_QUIRK_AMD756) {
2754 if ((u132->hc_roothub_a & RH_A_NDP) > MAX_ROOT_PORTS) {
2755 dev_err(&u132->platform_dev->dev, "bogus NDP, r"
2756 "ereads as NDP=%d\n",
2757 u132->hc_roothub_a & RH_A_NDP);
2758 goto done;
2759 }
2760 }
2761 if (u132->hc_roothub_status & (RH_HS_LPSC | RH_HS_OCIC)) {
2762 buf[0] = changed = 1;
2763 } else
2764 buf[0] = 0;
2765 if (u132->num_ports > 7) {
2766 buf[1] = 0;
2767 length++;
2768 }
2769 for (i = 0; i < u132->num_ports; i++) {
2770 if (u132->hc_roothub_portstatus[i] & (RH_PS_CSC |
2771 RH_PS_PESC | RH_PS_PSSC | RH_PS_OCIC |
2772 RH_PS_PRSC)) {
2773 changed = 1;
2774 if (i < 7) {
2775 buf[0] |= 1 << (i + 1);
2776 } else
2777 buf[1] |= 1 << (i - 7);
2778 continue;
2779 }
2780 if (!(u132->hc_roothub_portstatus[i] & RH_PS_CCS)) {
2781 continue;
2782 }
2783 if ((u132->hc_roothub_portstatus[i] & RH_PS_PSS)) {
2784 continue;
2785 }
2786 }
2787 done:return changed ? length : 0;
2788 }
2789}
2790
2791static int u132_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
2792 u16 wIndex, char *buf, u16 wLength)
2793{
2794 struct u132 *u132 = hcd_to_u132(hcd);
2795 if (u132->going > 1) {
2796 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2797 , u132->going);
2798 return -ENODEV;
2799 } else if (u132->going > 0) {
2800 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2801 return -ESHUTDOWN;
2802 } else {
2803 int retval = 0;
2804 down(&u132->sw_lock);
2805 switch (typeReq) {
2806 case ClearHubFeature:
2807 switch (wValue) {
2808 case C_HUB_OVER_CURRENT:
2809 case C_HUB_LOCAL_POWER:
2810 break;
2811 default:
2812 goto stall;
2813 }
2814 break;
2815 case SetHubFeature:
2816 switch (wValue) {
2817 case C_HUB_OVER_CURRENT:
2818 case C_HUB_LOCAL_POWER:
2819 break;
2820 default:
2821 goto stall;
2822 }
2823 break;
2824 case ClearPortFeature:{
2825 retval = u132_roothub_clearportfeature(u132,
2826 wValue, wIndex);
2827 if (retval)
2828 goto error;
2829 break;
2830 }
2831 case GetHubDescriptor:{
2832 retval = u132_roothub_descriptor(u132,
2833 (struct usb_hub_descriptor *)buf);
2834 if (retval)
2835 goto error;
2836 break;
2837 }
2838 case GetHubStatus:{
2839 retval = u132_roothub_status(u132,
2840 (__le32 *) buf);
2841 if (retval)
2842 goto error;
2843 break;
2844 }
2845 case GetPortStatus:{
2846 retval = u132_roothub_portstatus(u132,
2847 (__le32 *) buf, wIndex);
2848 if (retval)
2849 goto error;
2850 break;
2851 }
2852 case SetPortFeature:{
2853 retval = u132_roothub_setportfeature(u132,
2854 wValue, wIndex);
2855 if (retval)
2856 goto error;
2857 break;
2858 }
2859 default:
2860 goto stall;
2861 error:u132_disable(u132);
2862 u132->going = 1;
2863 break;
2864 stall:retval = -EPIPE;
2865 break;
2866 }
2867 up(&u132->sw_lock);
2868 return retval;
2869 }
2870}
2871
2872static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num)
2873{
2874 struct u132 *u132 = hcd_to_u132(hcd);
2875 if (u132->going > 1) {
2876 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2877 , u132->going);
2878 return -ENODEV;
2879 } else if (u132->going > 0) {
2880 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2881 return -ESHUTDOWN;
2882 } else
2883 return 0;
2884}
2885
2886static void u132_hub_irq_enable(struct usb_hcd *hcd)
2887{
2888 struct u132 *u132 = hcd_to_u132(hcd);
2889 if (u132->going > 1) {
2890 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2891 , u132->going);
2892 } else if (u132->going > 0)
2893 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2894}
2895
2896
2897#ifdef CONFIG_PM
2898static int u132_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
2899{
2900 struct u132 *u132 = hcd_to_u132(hcd);
2901 if (u132->going > 1) {
2902 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2903 , u132->going);
2904 return -ENODEV;
2905 } else if (u132->going > 0) {
2906 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2907 return -ESHUTDOWN;
2908 } else
2909 return 0;
2910}
2911
2912static int u132_hcd_resume(struct usb_hcd *hcd)
2913{
2914 struct u132 *u132 = hcd_to_u132(hcd);
2915 if (u132->going > 1) {
2916 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2917 , u132->going);
2918 return -ENODEV;
2919 } else if (u132->going > 0) {
2920 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2921 return -ESHUTDOWN;
2922 } else
2923 return 0;
2924}
2925
2926static int u132_bus_suspend(struct usb_hcd *hcd)
2927{
2928 struct u132 *u132 = hcd_to_u132(hcd);
2929 if (u132->going > 1) {
2930 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2931 , u132->going);
2932 return -ENODEV;
2933 } else if (u132->going > 0) {
2934 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2935 return -ESHUTDOWN;
2936 } else
2937 return 0;
2938}
2939
2940static int u132_bus_resume(struct usb_hcd *hcd)
2941{
2942 struct u132 *u132 = hcd_to_u132(hcd);
2943 if (u132->going > 1) {
2944 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
2945 , u132->going);
2946 return -ENODEV;
2947 } else if (u132->going > 0) {
2948 dev_err(&u132->platform_dev->dev, "device is being removed\n");
2949 return -ESHUTDOWN;
2950 } else
2951 return 0;
2952}
2953
2954#else
2955#define u132_hcd_suspend NULL
2956#define u132_hcd_resume NULL
2957#define u132_bus_suspend NULL
2958#define u132_bus_resume NULL
2959#endif
2960static struct hc_driver u132_hc_driver = {
2961 .description = hcd_name,
2962 .hcd_priv_size = sizeof(struct u132),
2963 .irq = NULL,
2964 .flags = HCD_USB11 | HCD_MEMORY,
2965 .reset = u132_hcd_reset,
2966 .start = u132_hcd_start,
2967 .suspend = u132_hcd_suspend,
2968 .resume = u132_hcd_resume,
2969 .stop = u132_hcd_stop,
2970 .urb_enqueue = u132_urb_enqueue,
2971 .urb_dequeue = u132_urb_dequeue,
2972 .endpoint_disable = u132_endpoint_disable,
2973 .get_frame_number = u132_get_frame,
2974 .hub_status_data = u132_hub_status_data,
2975 .hub_control = u132_hub_control,
2976 .bus_suspend = u132_bus_suspend,
2977 .bus_resume = u132_bus_resume,
2978 .start_port_reset = u132_start_port_reset,
2979 .hub_irq_enable = u132_hub_irq_enable,
2980};
2981
2982/*
2983* This function may be called by the USB core whilst the "usb_all_devices_rwsem"
2984* is held for writing, thus this module must not call usb_remove_hcd()
2985* synchronously - but instead should immediately stop activity to the
Matt LaPlante0779bf22006-11-30 05:24:39 +01002986* device and asynchronously call usb_remove_hcd()
Tony Olechd774efe2006-09-13 11:27:35 +01002987*/
2988static int __devexit u132_remove(struct platform_device *pdev)
2989{
2990 struct usb_hcd *hcd = platform_get_drvdata(pdev);
2991 if (hcd) {
2992 struct u132 *u132 = hcd_to_u132(hcd);
Tony Olechd774efe2006-09-13 11:27:35 +01002993 if (u132->going++ > 1) {
Tony Olech4b873612006-12-06 13:16:22 +00002994 dev_err(&u132->platform_dev->dev, "already being remove"
2995 "d\n");
Tony Olechd774efe2006-09-13 11:27:35 +01002996 return -ENODEV;
2997 } else {
2998 int rings = MAX_U132_RINGS;
2999 int endps = MAX_U132_ENDPS;
Tony Olech4b873612006-12-06 13:16:22 +00003000 dev_err(&u132->platform_dev->dev, "removing device u132"
3001 ".%d\n", u132->sequence_num);
Tony Olechd774efe2006-09-13 11:27:35 +01003002 msleep(100);
3003 down(&u132->sw_lock);
3004 u132_monitor_cancel_work(u132);
3005 while (rings-- > 0) {
3006 struct u132_ring *ring = &u132->ring[rings];
3007 u132_ring_cancel_work(u132, ring);
3008 } while (endps-- > 0) {
3009 struct u132_endp *endp = u132->endp[endps];
3010 if (endp)
3011 u132_endp_cancel_work(u132, endp);
3012 }
3013 u132->going += 1;
3014 printk(KERN_INFO "removing device u132.%d\n",
3015 u132->sequence_num);
3016 up(&u132->sw_lock);
3017 usb_remove_hcd(hcd);
3018 u132_u132_put_kref(u132);
3019 return 0;
3020 }
3021 } else
3022 return 0;
3023}
3024
3025static void u132_initialise(struct u132 *u132, struct platform_device *pdev)
3026{
3027 int rings = MAX_U132_RINGS;
3028 int ports = MAX_U132_PORTS;
3029 int addrs = MAX_U132_ADDRS;
3030 int udevs = MAX_U132_UDEVS;
3031 int endps = MAX_U132_ENDPS;
3032 u132->board = pdev->dev.platform_data;
3033 u132->platform_dev = pdev;
3034 u132->power = 0;
3035 u132->reset = 0;
3036 init_MUTEX(&u132->sw_lock);
3037 init_MUTEX(&u132->scheduler_lock);
3038 while (rings-- > 0) {
3039 struct u132_ring *ring = &u132->ring[rings];
3040 ring->u132 = u132;
3041 ring->number = rings + 1;
3042 ring->length = 0;
3043 ring->curr_endp = NULL;
David Howellsc4028952006-11-22 14:57:56 +00003044 INIT_DELAYED_WORK(&ring->scheduler,
3045 u132_hcd_ring_work_scheduler);
Tony Olechd774efe2006-09-13 11:27:35 +01003046 } down(&u132->sw_lock);
David Howellsc4028952006-11-22 14:57:56 +00003047 INIT_DELAYED_WORK(&u132->monitor, u132_hcd_monitor_work);
Tony Olechd774efe2006-09-13 11:27:35 +01003048 while (ports-- > 0) {
3049 struct u132_port *port = &u132->port[ports];
3050 port->u132 = u132;
3051 port->reset = 0;
3052 port->enable = 0;
3053 port->power = 0;
3054 port->Status = 0;
3055 } while (addrs-- > 0) {
3056 struct u132_addr *addr = &u132->addr[addrs];
3057 addr->address = 0;
3058 } while (udevs-- > 0) {
3059 struct u132_udev *udev = &u132->udev[udevs];
3060 int i = ARRAY_SIZE(udev->endp_number_in);
3061 int o = ARRAY_SIZE(udev->endp_number_out);
3062 udev->usb_device = NULL;
3063 udev->udev_number = 0;
3064 udev->usb_addr = 0;
3065 udev->portnumber = 0;
3066 while (i-- > 0) {
3067 udev->endp_number_in[i] = 0;
3068 }
3069 while (o-- > 0) {
3070 udev->endp_number_out[o] = 0;
3071 }
3072 }
3073 while (endps-- > 0) {
3074 u132->endp[endps] = NULL;
3075 }
3076 up(&u132->sw_lock);
3077 return;
3078}
3079
3080static int __devinit u132_probe(struct platform_device *pdev)
3081{
3082 struct usb_hcd *hcd;
Tony Olech4b873612006-12-06 13:16:22 +00003083 int retval;
3084 u32 control;
3085 u32 rh_a = -1;
3086 u32 num_ports;
Tony Olechd774efe2006-09-13 11:27:35 +01003087 msleep(100);
3088 if (u132_exiting > 0) {
3089 return -ENODEV;
Tony Olech4b873612006-12-06 13:16:22 +00003090 }
3091 retval = ftdi_write_pcimem(pdev, intrdisable, OHCI_INTR_MIE);
3092 if (retval)
3093 return retval;
3094 retval = ftdi_read_pcimem(pdev, control, &control);
3095 if (retval)
3096 return retval;
3097 retval = ftdi_read_pcimem(pdev, roothub.a, &rh_a);
3098 if (retval)
3099 return retval;
3100 num_ports = rh_a & RH_A_NDP; /* refuse to confuse usbcore */
Tony Olechd774efe2006-09-13 11:27:35 +01003101 if (pdev->dev.dma_mask) {
3102 return -EINVAL;
3103 }
3104 hcd = usb_create_hcd(&u132_hc_driver, &pdev->dev, pdev->dev.bus_id);
3105 if (!hcd) {
3106 printk(KERN_ERR "failed to create the usb hcd struct for U132\n"
3107 );
3108 ftdi_elan_gone_away(pdev);
3109 return -ENOMEM;
3110 } else {
3111 int retval = 0;
3112 struct u132 *u132 = hcd_to_u132(hcd);
3113 hcd->rsrc_start = 0;
3114 down(&u132_module_lock);
3115 list_add_tail(&u132->u132_list, &u132_static_list);
3116 u132->sequence_num = ++u132_instances;
3117 up(&u132_module_lock);
3118 u132_u132_init_kref(u132);
3119 u132_initialise(u132, pdev);
3120 hcd->product_desc = "ELAN U132 Host Controller";
3121 retval = usb_add_hcd(hcd, 0, 0);
3122 if (retval != 0) {
3123 dev_err(&u132->platform_dev->dev, "init error %d\n",
3124 retval);
3125 u132_u132_put_kref(u132);
3126 return retval;
3127 } else {
3128 u132_monitor_queue_work(u132, 100);
3129 return 0;
3130 }
3131 }
3132}
3133
3134
3135#ifdef CONFIG_PM
3136/* for this device there's no useful distinction between the controller
3137* and its root hub, except that the root hub only gets direct PM calls
3138* when CONFIG_USB_SUSPEND is enabled.
3139*/
3140static int u132_suspend(struct platform_device *pdev, pm_message_t state)
3141{
3142 struct usb_hcd *hcd = platform_get_drvdata(pdev);
3143 struct u132 *u132 = hcd_to_u132(hcd);
3144 if (u132->going > 1) {
3145 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
3146 , u132->going);
3147 return -ENODEV;
3148 } else if (u132->going > 0) {
3149 dev_err(&u132->platform_dev->dev, "device is being removed\n");
3150 return -ESHUTDOWN;
3151 } else {
3152 int retval = 0;
3153 if (state.event == PM_EVENT_FREEZE) {
3154 retval = u132_bus_suspend(hcd);
3155 } else if (state.event == PM_EVENT_SUSPEND) {
3156 int ports = MAX_U132_PORTS;
3157 while (ports-- > 0) {
3158 port_power(u132, ports, 0);
3159 }
3160 }
3161 if (retval == 0)
3162 pdev->dev.power.power_state = state;
3163 return retval;
3164 }
3165}
3166
3167static int u132_resume(struct platform_device *pdev)
3168{
3169 struct usb_hcd *hcd = platform_get_drvdata(pdev);
3170 struct u132 *u132 = hcd_to_u132(hcd);
3171 if (u132->going > 1) {
3172 dev_err(&u132->platform_dev->dev, "device has been removed %d\n"
3173 , u132->going);
3174 return -ENODEV;
3175 } else if (u132->going > 0) {
3176 dev_err(&u132->platform_dev->dev, "device is being removed\n");
3177 return -ESHUTDOWN;
3178 } else {
3179 int retval = 0;
3180 if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
3181 int ports = MAX_U132_PORTS;
3182 while (ports-- > 0) {
3183 port_power(u132, ports, 1);
3184 }
3185 retval = 0;
3186 } else {
3187 pdev->dev.power.power_state = PMSG_ON;
3188 retval = u132_bus_resume(hcd);
3189 }
3190 return retval;
3191 }
3192}
3193
3194#else
3195#define u132_suspend NULL
3196#define u132_resume NULL
3197#endif
3198/*
Matt LaPlante0779bf22006-11-30 05:24:39 +01003199* this driver is loaded explicitly by ftdi_u132
Tony Olechd774efe2006-09-13 11:27:35 +01003200*
3201* the platform_driver struct is static because it is per type of module
3202*/
3203static struct platform_driver u132_platform_driver = {
3204 .probe = u132_probe,
3205 .remove = __devexit_p(u132_remove),
3206 .suspend = u132_suspend,
3207 .resume = u132_resume,
3208 .driver = {
3209 .name = (char *)hcd_name,
3210 .owner = THIS_MODULE,
3211 },
3212};
3213static int __init u132_hcd_init(void)
3214{
3215 int retval;
3216 INIT_LIST_HEAD(&u132_static_list);
3217 u132_instances = 0;
3218 u132_exiting = 0;
3219 init_MUTEX(&u132_module_lock);
3220 if (usb_disabled())
3221 return -ENODEV;
3222 printk(KERN_INFO "driver %s built at %s on %s\n", hcd_name, __TIME__,
3223 __DATE__);
3224 workqueue = create_singlethread_workqueue("u132");
3225 retval = platform_driver_register(&u132_platform_driver);
3226 return retval;
3227}
3228
3229
3230module_init(u132_hcd_init);
3231static void __exit u132_hcd_exit(void)
3232{
3233 struct u132 *u132;
3234 struct u132 *temp;
3235 down(&u132_module_lock);
3236 u132_exiting += 1;
3237 up(&u132_module_lock);
3238 list_for_each_entry_safe(u132, temp, &u132_static_list, u132_list) {
3239 platform_device_unregister(u132->platform_dev);
3240 } platform_driver_unregister(&u132_platform_driver);
3241 printk(KERN_INFO "u132-hcd driver deregistered\n");
3242 wait_event(u132_hcd_wait, u132_instances == 0);
3243 flush_workqueue(workqueue);
3244 destroy_workqueue(workqueue);
3245}
3246
3247
3248module_exit(u132_hcd_exit);
3249MODULE_LICENSE("GPL");