2 * Freescale QUICC Engine USB Host Controller Driver
4 * Copyright (c) Freescale Semicondutor, Inc. 2006, 2011.
5 * Shlomi Gridish <gridish@freescale.com>
6 * Jerry Huang <Chang-Ming.Huang@freescale.com>
7 * Copyright (c) Logic Product Development, Inc. 2007
8 * Peter Barada <peterb@logicpd.com>
9 * Copyright (c) MontaVista Software, Inc. 2008.
10 * Anton Vorontsov <avorontsov@ru.mvista.com>
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
18 #include <linux/kernel.h>
19 #include <linux/types.h>
20 #include <linux/spinlock.h>
21 #include <linux/delay.h>
22 #include <linux/errno.h>
23 #include <linux/list.h>
24 #include <linux/interrupt.h>
26 #include <linux/usb.h>
27 #include <linux/usb/hcd.h>
29 #include <asm/fsl_gtm.h>
32 static void recycle_frame(struct fhci_usb
*usb
, struct packet
*pkt
)
36 pkt
->status
= USB_TD_OK
;
38 pkt
->priv_data
= NULL
;
40 cq_put(&usb
->ep0
->empty_frame_Q
, pkt
);
43 /* confirm submitted packet */
44 void fhci_transaction_confirm(struct fhci_usb
*usb
, struct packet
*pkt
)
47 struct packet
*td_pkt
;
52 td
= fhci_remove_td_from_frame(usb
->actual_frame
);
55 td
->status
= pkt
->status
;
56 if (td
->type
== FHCI_TA_IN
&& td_pkt
->info
& PKT_DUMMY_PACKET
) {
57 if ((td
->data
+ td
->actual_len
) && trans_len
)
58 memcpy(td
->data
+ td
->actual_len
, pkt
->data
,
60 cq_put(&usb
->ep0
->dummy_packets_Q
, pkt
->data
);
63 recycle_frame(usb
, pkt
);
66 if (ed
->mode
== FHCI_TF_ISO
) {
67 if (ed
->td_list
.next
->next
!= &ed
->td_list
) {
69 list_entry(ed
->td_list
.next
->next
, struct td
,
72 td_next
->start_frame
= usb
->actual_frame
->frame_num
;
74 td
->actual_len
= trans_len
;
76 } else if ((td
->status
& USB_TD_ERROR
) &&
77 !(td
->status
& USB_TD_TX_ER_NAK
)) {
79 * There was an error on the transaction (but not NAK).
80 * If it is fatal error (data underrun, stall, bad pid or 3
81 * errors exceeded), mark this TD as done.
83 if ((td
->status
& USB_TD_RX_DATA_UNDERUN
) ||
84 (td
->status
& USB_TD_TX_ER_STALL
) ||
85 (td
->status
& USB_TD_RX_ER_PID
) ||
86 (++td
->error_cnt
>= 3)) {
87 ed
->state
= FHCI_ED_HALTED
;
90 if (td
->status
& USB_TD_RX_DATA_UNDERUN
) {
91 fhci_dbg(usb
->fhci
, "td err fu\n");
92 td
->toggle
= !td
->toggle
;
93 td
->actual_len
+= trans_len
;
95 fhci_dbg(usb
->fhci
, "td err f!u\n");
98 fhci_dbg(usb
->fhci
, "td err !f\n");
99 /* it is not a fatal error -retry this transaction */
102 td
->status
= USB_TD_OK
;
104 } else if (td
->status
& USB_TD_TX_ER_NAK
) {
105 /* there was a NAK response */
106 fhci_vdbg(usb
->fhci
, "td nack\n");
109 td
->status
= USB_TD_OK
;
111 /* there was no error on transaction */
114 td
->toggle
= !td
->toggle
;
115 td
->actual_len
+= trans_len
;
117 if (td
->len
== td
->actual_len
)
122 fhci_move_td_from_ed_to_done_list(usb
, ed
);
126 * Flush all transmitted packets from BDs
127 * This routine is called when disabling the USB port to flush all
128 * transmissions that are already scheduled in the BDs
130 void fhci_flush_all_transmissions(struct fhci_usb
*usb
)
135 mode
= in_8(&usb
->fhci
->regs
->usb_usmod
);
136 clrbits8(&usb
->fhci
->regs
->usb_usmod
, USB_MODE_EN
);
140 while ((td
= fhci_peek_td_from_frame(usb
->actual_frame
)) != NULL
) {
141 struct packet
*pkt
= td
->pkt
;
143 pkt
->status
= USB_TD_TX_ER_TIMEOUT
;
144 fhci_transaction_confirm(usb
, pkt
);
147 usb
->actual_frame
->frame_status
= FRAME_END_TRANSMISSION
;
149 /* reset the event register */
150 out_be16(&usb
->fhci
->regs
->usb_usber
, 0xffff);
151 /* enable the USB controller */
152 out_8(&usb
->fhci
->regs
->usb_usmod
, mode
| USB_MODE_EN
);
156 * This function forms the packet and transmit the packet. This function
157 * will handle all endpoint type:ISO,interrupt,control and bulk
159 static int add_packet(struct fhci_usb
*usb
, struct ed
*ed
, struct td
*td
)
161 u32 fw_transaction_time
, len
= 0;
165 /* calcalate data address,len and toggle and then add the transaction */
166 if (td
->toggle
== USB_TD_TOGGLE_CARRY
)
167 td
->toggle
= ed
->toggle_carry
;
172 if (td
->type
!= FHCI_TA_IN
)
177 len
= min(td
->len
- td
->actual_len
, ed
->max_pkt_size
);
178 if (!((td
->type
== FHCI_TA_IN
) &&
179 ((len
+ td
->actual_len
) == td
->len
)))
180 data
= td
->data
+ td
->actual_len
;
183 len
= min(td
->len
, ed
->max_pkt_size
);
184 if (!((td
->type
== FHCI_TA_IN
) &&
185 ((td
->len
+ CRC_SIZE
) >= ed
->max_pkt_size
)))
192 if (usb
->port_status
== FHCI_PORT_FULL
)
193 fw_transaction_time
= (((len
+ PROTOCOL_OVERHEAD
) * 11) >> 4);
195 fw_transaction_time
= ((len
+ PROTOCOL_OVERHEAD
) * 6);
197 /* check if there's enough space in this frame to submit this TD */
198 if (usb
->actual_frame
->total_bytes
+ len
+ PROTOCOL_OVERHEAD
>=
199 usb
->max_bytes_per_frame
) {
200 fhci_vdbg(usb
->fhci
, "not enough space in this frame: "
201 "%d %d %d\n", usb
->actual_frame
->total_bytes
, len
,
202 usb
->max_bytes_per_frame
);
206 /* check if there's enough time in this frame to submit this TD */
207 if (usb
->actual_frame
->frame_status
!= FRAME_IS_PREPARED
&&
208 (usb
->actual_frame
->frame_status
& FRAME_END_TRANSMISSION
||
209 (fw_transaction_time
+ usb
->sw_transaction_time
>=
210 1000 - fhci_get_sof_timer_count(usb
)))) {
211 fhci_dbg(usb
->fhci
, "not enough time in this frame\n");
215 /* update frame object fields before transmitting */
216 pkt
= cq_get(&usb
->ep0
->empty_frame_Q
);
218 fhci_dbg(usb
->fhci
, "there is no empty frame\n");
225 data
= cq_get(&usb
->ep0
->dummy_packets_Q
);
227 pkt
->info
= PKT_DUMMY_PACKET
;
231 pkt
->status
= USB_TD_OK
;
232 /* update TD status field before transmitting */
233 td
->status
= USB_TD_INPROGRESS
;
234 /* update actual frame time object with the actual transmission */
235 usb
->actual_frame
->total_bytes
+= (len
+ PROTOCOL_OVERHEAD
);
236 fhci_add_td_to_frame(usb
->actual_frame
, td
);
238 if (usb
->port_status
!= FHCI_PORT_FULL
&&
239 usb
->port_status
!= FHCI_PORT_LOW
) {
240 pkt
->status
= USB_TD_TX_ER_TIMEOUT
;
242 fhci_transaction_confirm(usb
, pkt
);
243 } else if (fhci_host_transaction(usb
, pkt
, td
->type
, ed
->dev_addr
,
244 ed
->ep_addr
, ed
->mode
, ed
->speed
, td
->toggle
)) {
245 /* remove TD from actual frame */
246 list_del_init(&td
->frame_lh
);
247 td
->status
= USB_TD_OK
;
248 if (pkt
->info
& PKT_DUMMY_PACKET
)
249 cq_put(&usb
->ep0
->dummy_packets_Q
, pkt
->data
);
250 recycle_frame(usb
, pkt
);
251 usb
->actual_frame
->total_bytes
-= (len
+ PROTOCOL_OVERHEAD
);
252 fhci_err(usb
->fhci
, "host transaction failed\n");
259 static void move_head_to_tail(struct list_head
*list
)
261 struct list_head
*node
= list
->next
;
263 if (!list_empty(list
)) {
264 list_move_tail(node
, list
);
269 * This function goes through the endpoint list and schedules the
270 * transactions within this list
272 static int scan_ed_list(struct fhci_usb
*usb
,
273 struct list_head
*list
, enum fhci_tf_mode list_type
)
275 static const int frame_part
[4] = {
276 [FHCI_TF_CTRL
] = MAX_BYTES_PER_FRAME
,
277 [FHCI_TF_ISO
] = (MAX_BYTES_PER_FRAME
*
278 MAX_PERIODIC_FRAME_USAGE
) / 100,
279 [FHCI_TF_BULK
] = MAX_BYTES_PER_FRAME
,
280 [FHCI_TF_INTR
] = (MAX_BYTES_PER_FRAME
*
281 MAX_PERIODIC_FRAME_USAGE
) / 100
286 u32 save_transaction_time
= usb
->sw_transaction_time
;
288 list_for_each_entry(ed
, list
, node
) {
291 if (!td
|| (td
&& td
->status
== USB_TD_INPROGRESS
))
294 if (ed
->state
!= FHCI_ED_OPER
) {
295 if (ed
->state
== FHCI_ED_URB_DEL
) {
296 td
->status
= USB_TD_OK
;
297 fhci_move_td_from_ed_to_done_list(usb
, ed
);
298 ed
->state
= FHCI_ED_SKIP
;
304 * if it isn't interrupt pipe or it is not iso pipe and the
305 * interval time passed
307 if ((list_type
== FHCI_TF_INTR
|| list_type
== FHCI_TF_ISO
) &&
308 (((usb
->actual_frame
->frame_num
-
309 td
->start_frame
) & 0x7ff) < td
->interval
))
312 if (add_packet(usb
, ed
, td
) < 0)
315 /* update time stamps in the TD */
316 td
->start_frame
= usb
->actual_frame
->frame_num
;
317 usb
->sw_transaction_time
+= save_transaction_time
;
319 if (usb
->actual_frame
->total_bytes
>=
320 usb
->max_bytes_per_frame
) {
321 usb
->actual_frame
->frame_status
=
322 FRAME_DATA_END_TRANSMISSION
;
323 fhci_push_dummy_bd(usb
->ep0
);
328 if (usb
->actual_frame
->total_bytes
>= frame_part
[list_type
])
332 /* be fair to each ED(move list head around) */
333 move_head_to_tail(list
);
334 usb
->sw_transaction_time
= save_transaction_time
;
339 static u32
rotate_frames(struct fhci_usb
*usb
)
341 struct fhci_hcd
*fhci
= usb
->fhci
;
343 if (!list_empty(&usb
->actual_frame
->tds_list
)) {
344 if ((((in_be16(&fhci
->pram
->frame_num
) & 0x07ff) -
345 usb
->actual_frame
->frame_num
) & 0x7ff) > 5)
346 fhci_flush_actual_frame(usb
);
351 usb
->actual_frame
->frame_status
= FRAME_IS_PREPARED
;
352 usb
->actual_frame
->frame_num
= in_be16(&fhci
->pram
->frame_num
) & 0x7ff;
353 usb
->actual_frame
->total_bytes
= 0;
359 * This function schedule the USB transaction and will process the
360 * endpoint in the following order: iso, interrupt, control and bulk.
362 void fhci_schedule_transactions(struct fhci_usb
*usb
)
366 if (usb
->actual_frame
->frame_status
& FRAME_END_TRANSMISSION
)
367 if (rotate_frames(usb
) != 0)
370 if (usb
->actual_frame
->frame_status
& FRAME_END_TRANSMISSION
)
373 if (usb
->actual_frame
->total_bytes
== 0) {
375 * schedule the next available ISO transfer
376 *or next stage of the ISO transfer
378 scan_ed_list(usb
, &usb
->hc_list
->iso_list
, FHCI_TF_ISO
);
381 * schedule the next available interrupt transfer or
382 * the next stage of the interrupt transfer
384 scan_ed_list(usb
, &usb
->hc_list
->intr_list
, FHCI_TF_INTR
);
387 * schedule the next available control transfer
388 * or the next stage of the control transfer
390 left
= scan_ed_list(usb
, &usb
->hc_list
->ctrl_list
,
395 * schedule the next available bulk transfer or the next stage of the
399 scan_ed_list(usb
, &usb
->hc_list
->bulk_list
, FHCI_TF_BULK
);
402 /* Handles SOF interrupt */
403 static void sof_interrupt(struct fhci_hcd
*fhci
)
405 struct fhci_usb
*usb
= fhci
->usb_lld
;
407 if ((usb
->port_status
== FHCI_PORT_DISABLED
) &&
408 (usb
->vroot_hub
->port
.wPortStatus
& USB_PORT_STAT_CONNECTION
) &&
409 !(usb
->vroot_hub
->port
.wPortChange
& USB_PORT_STAT_C_CONNECTION
)) {
410 if (usb
->vroot_hub
->port
.wPortStatus
& USB_PORT_STAT_LOW_SPEED
)
411 usb
->port_status
= FHCI_PORT_LOW
;
413 usb
->port_status
= FHCI_PORT_FULL
;
415 usb
->saved_msk
&= ~USB_E_IDLE_MASK
;
416 out_be16(&usb
->fhci
->regs
->usb_usbmr
, usb
->saved_msk
);
419 gtm_set_exact_timer16(fhci
->timer
, usb
->max_frame_usage
, false);
421 fhci_host_transmit_actual_frame(usb
);
422 usb
->actual_frame
->frame_status
= FRAME_IS_TRANSMITTED
;
424 fhci_schedule_transactions(usb
);
427 /* Handles device disconnected interrupt on port */
428 void fhci_device_disconnected_interrupt(struct fhci_hcd
*fhci
)
430 struct fhci_usb
*usb
= fhci
->usb_lld
;
432 fhci_dbg(fhci
, "-> %s\n", __func__
);
434 fhci_usb_disable_interrupt(usb
);
435 clrbits8(&usb
->fhci
->regs
->usb_usmod
, USB_MODE_LSS
);
436 usb
->port_status
= FHCI_PORT_DISABLED
;
438 fhci_stop_sof_timer(fhci
);
440 /* Enable IDLE since we want to know if something comes along */
441 usb
->saved_msk
|= USB_E_IDLE_MASK
;
442 out_be16(&usb
->fhci
->regs
->usb_usbmr
, usb
->saved_msk
);
444 usb
->vroot_hub
->port
.wPortStatus
&= ~USB_PORT_STAT_CONNECTION
;
445 usb
->vroot_hub
->port
.wPortChange
|= USB_PORT_STAT_C_CONNECTION
;
446 usb
->max_bytes_per_frame
= 0;
447 fhci_usb_enable_interrupt(usb
);
449 fhci_dbg(fhci
, "<- %s\n", __func__
);
452 /* detect a new device connected on the USB port */
453 void fhci_device_connected_interrupt(struct fhci_hcd
*fhci
)
456 struct fhci_usb
*usb
= fhci
->usb_lld
;
460 fhci_dbg(fhci
, "-> %s\n", __func__
);
462 fhci_usb_disable_interrupt(usb
);
463 state
= fhci_ioports_check_bus_state(fhci
);
465 /* low-speed device was connected to the USB port */
467 ret
= qe_usb_clock_set(fhci
->lowspeed_clk
, USB_CLOCK
>> 3);
469 fhci_warn(fhci
, "Low-Speed device is not supported, "
474 usb
->port_status
= FHCI_PORT_LOW
;
475 setbits8(&usb
->fhci
->regs
->usb_usmod
, USB_MODE_LSS
);
476 usb
->vroot_hub
->port
.wPortStatus
|=
477 (USB_PORT_STAT_LOW_SPEED
|
478 USB_PORT_STAT_CONNECTION
);
479 usb
->vroot_hub
->port
.wPortChange
|=
480 USB_PORT_STAT_C_CONNECTION
;
481 usb
->max_bytes_per_frame
=
482 (MAX_BYTES_PER_FRAME
>> 3) - 7;
483 fhci_port_enable(usb
);
484 } else if (state
== 2) {
485 ret
= qe_usb_clock_set(fhci
->fullspeed_clk
, USB_CLOCK
);
487 fhci_warn(fhci
, "Full-Speed device is not supported, "
492 usb
->port_status
= FHCI_PORT_FULL
;
493 clrbits8(&usb
->fhci
->regs
->usb_usmod
, USB_MODE_LSS
);
494 usb
->vroot_hub
->port
.wPortStatus
&=
495 ~USB_PORT_STAT_LOW_SPEED
;
496 usb
->vroot_hub
->port
.wPortStatus
|=
497 USB_PORT_STAT_CONNECTION
;
498 usb
->vroot_hub
->port
.wPortChange
|=
499 USB_PORT_STAT_C_CONNECTION
;
500 usb
->max_bytes_per_frame
= (MAX_BYTES_PER_FRAME
- 15);
501 fhci_port_enable(usb
);
504 fhci_usb_enable_interrupt(usb
);
505 fhci_dbg(fhci
, "<- %s\n", __func__
);
508 irqreturn_t
fhci_frame_limit_timer_irq(int irq
, void *_hcd
)
510 struct usb_hcd
*hcd
= _hcd
;
511 struct fhci_hcd
*fhci
= hcd_to_fhci(hcd
);
512 struct fhci_usb
*usb
= fhci
->usb_lld
;
514 spin_lock(&fhci
->lock
);
516 gtm_set_exact_timer16(fhci
->timer
, 1000, false);
518 if (usb
->actual_frame
->frame_status
== FRAME_IS_TRANSMITTED
) {
519 usb
->actual_frame
->frame_status
= FRAME_TIMER_END_TRANSMISSION
;
520 fhci_push_dummy_bd(usb
->ep0
);
523 fhci_schedule_transactions(usb
);
525 spin_unlock(&fhci
->lock
);
530 /* Cancel transmission on the USB endpoint */
531 static void abort_transmission(struct fhci_usb
*usb
)
533 fhci_dbg(usb
->fhci
, "-> %s\n", __func__
);
534 /* issue stop Tx command */
535 qe_issue_cmd(QE_USB_STOP_TX
, QE_CR_SUBBLOCK_USB
, EP_ZERO
, 0);
537 out_8(&usb
->fhci
->regs
->usb_uscom
, USB_CMD_FLUSH_FIFO
| EP_ZERO
);
541 /* issue restart Tx command */
542 qe_issue_cmd(QE_USB_RESTART_TX
, QE_CR_SUBBLOCK_USB
, EP_ZERO
, 0);
543 fhci_dbg(usb
->fhci
, "<- %s\n", __func__
);
546 irqreturn_t
fhci_irq(struct usb_hcd
*hcd
)
548 struct fhci_hcd
*fhci
= hcd_to_fhci(hcd
);
549 struct fhci_usb
*usb
;
553 spin_lock_irqsave(&fhci
->lock
, flags
);
557 usb_er
|= in_be16(&usb
->fhci
->regs
->usb_usber
) &
558 in_be16(&usb
->fhci
->regs
->usb_usbmr
);
560 /* clear event bits for next time */
561 out_be16(&usb
->fhci
->regs
->usb_usber
, usb_er
);
563 fhci_dbg_isr(fhci
, usb_er
);
565 if (usb_er
& USB_E_RESET_MASK
) {
566 if ((usb
->port_status
== FHCI_PORT_FULL
) ||
567 (usb
->port_status
== FHCI_PORT_LOW
)) {
568 fhci_device_disconnected_interrupt(fhci
);
569 usb_er
&= ~USB_E_IDLE_MASK
;
570 } else if (usb
->port_status
== FHCI_PORT_WAITING
) {
571 usb
->port_status
= FHCI_PORT_DISCONNECTING
;
573 /* Turn on IDLE since we want to disconnect */
574 usb
->saved_msk
|= USB_E_IDLE_MASK
;
575 out_be16(&usb
->fhci
->regs
->usb_usber
,
577 } else if (usb
->port_status
== FHCI_PORT_DISABLED
) {
578 if (fhci_ioports_check_bus_state(fhci
) == 1)
579 fhci_device_connected_interrupt(fhci
);
581 usb_er
&= ~USB_E_RESET_MASK
;
584 if (usb_er
& USB_E_MSF_MASK
) {
585 abort_transmission(fhci
->usb_lld
);
586 usb_er
&= ~USB_E_MSF_MASK
;
589 if (usb_er
& (USB_E_SOF_MASK
| USB_E_SFT_MASK
)) {
591 usb_er
&= ~(USB_E_SOF_MASK
| USB_E_SFT_MASK
);
594 if (usb_er
& USB_E_TXB_MASK
) {
595 fhci_tx_conf_interrupt(fhci
->usb_lld
);
596 usb_er
&= ~USB_E_TXB_MASK
;
599 if (usb_er
& USB_E_TXE1_MASK
) {
600 fhci_tx_conf_interrupt(fhci
->usb_lld
);
601 usb_er
&= ~USB_E_TXE1_MASK
;
604 if (usb_er
& USB_E_IDLE_MASK
) {
605 if (usb
->port_status
== FHCI_PORT_DISABLED
) {
606 usb_er
&= ~USB_E_RESET_MASK
;
607 fhci_device_connected_interrupt(fhci
);
608 } else if (usb
->port_status
==
609 FHCI_PORT_DISCONNECTING
) {
610 /* XXX usb->port_status = FHCI_PORT_WAITING; */
612 usb
->saved_msk
&= ~USB_E_IDLE_MASK
;
613 out_be16(&usb
->fhci
->regs
->usb_usbmr
,
616 fhci_dbg_isr(fhci
, -1);
619 usb_er
&= ~USB_E_IDLE_MASK
;
622 spin_unlock_irqrestore(&fhci
->lock
, flags
);
629 * Process normal completions(error or success) and clean the schedule.
631 * This is the main path for handing urbs back to drivers. The only other patth
632 * is process_del_list(),which unlinks URBs by scanning EDs,instead of scanning
633 * the (re-reversed) done list as this does.
635 static void process_done_list(unsigned long data
)
640 struct urb_priv
*urb_priv
;
641 struct fhci_hcd
*fhci
= (struct fhci_hcd
*)data
;
643 disable_irq(fhci
->timer
->irq
);
644 disable_irq(fhci_to_hcd(fhci
)->irq
);
645 spin_lock(&fhci
->lock
);
647 td
= fhci_remove_td_from_done_list(fhci
->hc_list
);
650 urb_priv
= urb
->hcpriv
;
653 /* update URB's length and status from TD */
654 fhci_done_td(urb
, td
);
658 * if all this urb's TDs are done, call complete()
659 * Interrupt transfers are the onley special case:
660 * they are reissued,until "deleted" by usb_unlink_urb
661 * (real work done in a SOF intr, by process_del_list)
663 if (urb_priv
->tds_cnt
== urb_priv
->num_of_tds
) {
664 fhci_urb_complete_free(fhci
, urb
);
665 } else if (urb_priv
->state
== URB_DEL
&&
666 ed
->state
== FHCI_ED_SKIP
) {
667 fhci_del_ed_list(fhci
, ed
);
668 ed
->state
= FHCI_ED_OPER
;
669 } else if (ed
->state
== FHCI_ED_HALTED
) {
670 urb_priv
->state
= URB_DEL
;
671 ed
->state
= FHCI_ED_URB_DEL
;
672 fhci_del_ed_list(fhci
, ed
);
673 ed
->state
= FHCI_ED_OPER
;
676 td
= fhci_remove_td_from_done_list(fhci
->hc_list
);
679 spin_unlock(&fhci
->lock
);
680 enable_irq(fhci
->timer
->irq
);
681 enable_irq(fhci_to_hcd(fhci
)->irq
);
684 DECLARE_TASKLET(fhci_tasklet
, process_done_list
, 0);
686 /* transfer complted callback */
687 u32
fhci_transfer_confirm_callback(struct fhci_hcd
*fhci
)
689 if (!fhci
->process_done_task
->state
)
690 tasklet_schedule(fhci
->process_done_task
);
695 * adds urb to the endpoint descriptor list
697 * fhci data structure for the Low level host controller
698 * ep USB Host endpoint data structure
699 * urb USB request block data structure
701 void fhci_queue_urb(struct fhci_hcd
*fhci
, struct urb
*urb
)
703 struct ed
*ed
= urb
->ep
->hcpriv
;
704 struct urb_priv
*urb_priv
= urb
->hcpriv
;
705 u32 data_len
= urb
->transfer_buffer_length
;
713 ed
= fhci_get_empty_ed(fhci
);
714 ed
->dev_addr
= usb_pipedevice(urb
->pipe
);
715 ed
->ep_addr
= usb_pipeendpoint(urb
->pipe
);
716 switch (usb_pipetype(urb
->pipe
)) {
718 ed
->mode
= FHCI_TF_CTRL
;
721 ed
->mode
= FHCI_TF_BULK
;
724 ed
->mode
= FHCI_TF_INTR
;
726 case PIPE_ISOCHRONOUS
:
727 ed
->mode
= FHCI_TF_ISO
;
732 ed
->speed
= (urb
->dev
->speed
== USB_SPEED_LOW
) ?
733 FHCI_LOW_SPEED
: FHCI_FULL_SPEED
;
734 ed
->max_pkt_size
= usb_maxpacket(urb
->dev
,
735 urb
->pipe
, usb_pipeout(urb
->pipe
));
736 urb
->ep
->hcpriv
= ed
;
737 fhci_dbg(fhci
, "new ep speed=%d max_pkt_size=%d\n",
738 ed
->speed
, ed
->max_pkt_size
);
741 /* for ISO transfer calculate start frame index */
742 if (ed
->mode
== FHCI_TF_ISO
) {
743 /* Ignore the possibility of underruns */
744 urb
->start_frame
= ed
->td_head
? ed
->next_iso
:
746 ed
->next_iso
= (urb
->start_frame
+ urb
->interval
*
747 urb
->number_of_packets
) & 0x07ff;
751 * OHCI handles the DATA toggle itself,we just use the USB
754 if (usb_gettoggle(urb
->dev
, usb_pipeendpoint(urb
->pipe
),
755 usb_pipeout(urb
->pipe
)))
756 toggle
= USB_TD_TOGGLE_CARRY
;
758 toggle
= USB_TD_TOGGLE_DATA0
;
759 usb_settoggle(urb
->dev
, usb_pipeendpoint(urb
->pipe
),
760 usb_pipeout(urb
->pipe
), 1);
763 urb_priv
->tds_cnt
= 0;
766 data
= urb
->transfer_buffer
;
772 if (urb
->transfer_flags
& URB_ZERO_PACKET
&&
773 urb
->transfer_buffer_length
> 0 &&
774 ((urb
->transfer_buffer_length
%
775 usb_maxpacket(urb
->dev
, urb
->pipe
,
776 usb_pipeout(urb
->pipe
))) == 0))
777 urb_state
= US_BULK0
;
778 while (data_len
> 4096) {
779 td
= fhci_td_fill(fhci
, urb
, urb_priv
, ed
, cnt
,
780 usb_pipeout(urb
->pipe
) ? FHCI_TA_OUT
:
782 cnt
? USB_TD_TOGGLE_CARRY
:
784 data
, 4096, 0, 0, true);
790 td
= fhci_td_fill(fhci
, urb
, urb_priv
, ed
, cnt
,
791 usb_pipeout(urb
->pipe
) ? FHCI_TA_OUT
: FHCI_TA_IN
,
792 cnt
? USB_TD_TOGGLE_CARRY
: toggle
,
793 data
, data_len
, 0, 0, true);
796 if (urb
->transfer_flags
& URB_ZERO_PACKET
&&
797 cnt
< urb_priv
->num_of_tds
) {
798 td
= fhci_td_fill(fhci
, urb
, urb_priv
, ed
, cnt
,
799 usb_pipeout(urb
->pipe
) ? FHCI_TA_OUT
:
801 USB_TD_TOGGLE_CARRY
, NULL
, 0, 0, 0, true);
806 urb
->start_frame
= get_frame_num(fhci
) + 1;
807 td
= fhci_td_fill(fhci
, urb
, urb_priv
, ed
, cnt
++,
808 usb_pipeout(urb
->pipe
) ? FHCI_TA_OUT
: FHCI_TA_IN
,
809 USB_TD_TOGGLE_DATA0
, data
, data_len
,
810 urb
->interval
, urb
->start_frame
, true);
813 ed
->dev_addr
= usb_pipedevice(urb
->pipe
);
814 ed
->max_pkt_size
= usb_maxpacket(urb
->dev
, urb
->pipe
,
815 usb_pipeout(urb
->pipe
));
817 td
= fhci_td_fill(fhci
, urb
, urb_priv
, ed
, cnt
++, FHCI_TA_SETUP
,
818 USB_TD_TOGGLE_DATA0
, urb
->setup_packet
, 8, 0, 0, true);
822 td
= fhci_td_fill(fhci
, urb
, urb_priv
, ed
, cnt
++,
823 usb_pipeout(urb
->pipe
) ? FHCI_TA_OUT
:
825 USB_TD_TOGGLE_DATA1
, data
, data_len
, 0, 0,
831 td
= fhci_td_fill(fhci
, urb
, urb_priv
, ed
, cnt
++,
832 (usb_pipeout(urb
->pipe
) ? FHCI_TA_IN
:
834 USB_TD_TOGGLE_DATA1
, data
, 0, 0, 0, true);
836 td
= fhci_td_fill(fhci
, urb
, urb_priv
, ed
, cnt
++,
838 USB_TD_TOGGLE_DATA1
, data
, 0, 0, 0, true);
840 urb_state
= US_CTRL_SETUP
;
843 for (cnt
= 0; cnt
< urb
->number_of_packets
; cnt
++) {
844 u16 frame
= urb
->start_frame
;
847 * FIXME scheduling should handle frame counter
848 * roll-around ... exotic case (and OHCI has
849 * a 2^16 iso range, vs other HCs max of 2^10)
851 frame
+= cnt
* urb
->interval
;
853 td
= fhci_td_fill(fhci
, urb
, urb_priv
, ed
, cnt
,
854 usb_pipeout(urb
->pipe
) ? FHCI_TA_OUT
:
857 data
+ urb
->iso_frame_desc
[cnt
].offset
,
858 urb
->iso_frame_desc
[cnt
].length
,
859 urb
->interval
, frame
, true);
867 * set the state of URB
868 * control pipe:3 states -- setup,data,status
869 * interrupt and bulk pipe:1 state -- data
872 urb
->pipe
|= urb_state
& 0x1f;
874 urb_priv
->state
= URB_INPROGRESS
;
877 ed
->state
= FHCI_ED_OPER
;
880 list_add(&ed
->node
, &fhci
->hc_list
->ctrl_list
);
883 list_add(&ed
->node
, &fhci
->hc_list
->bulk_list
);
886 list_add(&ed
->node
, &fhci
->hc_list
->intr_list
);
889 list_add(&ed
->node
, &fhci
->hc_list
->iso_list
);
896 fhci_add_tds_to_ed(ed
, urb_priv
->tds
, urb_priv
->num_of_tds
);