1/*
2 * Copyright (c) 2007-2013 ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
8 */
9
10#include <stdlib.h>
11#include <stdio.h>
12#include <string.h>
13#include <barrelfish/barrelfish.h>
14
15#include <usb/usb.h>
16
17
18#include <usb_device.h>
19#include <usb_controller.h>
20#include <usb_xfer.h>
21#include "usb_ohci.h"
22#include "usb_ohci_xfer.h"
23#include "usb_ohci_memory.h"
24#include "usb_ohci_queue.h"
25
26
27
28
29static void usb_ohci_xfer_short_frames(struct usb_xfer *xfer)
30{
31    usb_ohci_td_t *td;
32    usb_ohci_ed_t *ed;
33
34    usb_ohci_td_ctrl_t *td_ctrl;
35    uint16_t cc;
36    usb_paddr_t td_next;
37    usb_paddr_t current_buffer;
38
39    td = xfer->hcd_td_cache;
40
41    /*
42     * loop over the frame, a frame may contain more than one short
43     * packets, we have to make sure that we reached the last one
44     */
45    while (1) {
46
47        current_buffer = td->td_current_buffer;
48        td_ctrl = &td->td_control;
49        td_next = td->td_nextTD;
50
51        /*
52         * check if we have reached the last transfer descriptor
53         * if so we are done
54         */
55
56        if (((void *) td) == xfer->hcd_td_last) {
57            td = NULL;
58            break;
59        }
60
61        /*
62         * check the condition codes, if it is USB_OHCI_STATUS_OK then
63         * the transfer is finished
64         */
65        cc = td_ctrl->condition_code;
66        if (cc) {
67            td = NULL;
68            break;
69        }
70
71        /*
72         * check if we have reached the last packet i.e. the td_nextTD is
73         * NULL, but hwe have to mask out the last four bits, since these may
74         * be used otherwise.
75         * If we have a current buffer then there is something else in the
76         * frame we follow the alternative and stop processing.
77         */
78        if (((td_next & (~0xF)) == 0) || current_buffer) {
79            td = td->alt_next;
80            break;
81        }
82
83        // go to next transfer descriptor
84        td = td->obj_next;
85    }
86
87    // update of the cache
88    xfer->hcd_td_cache = td;
89
90    /*
91     * we have found a non completed short transfer for this endpoint
92     * this means we have to update the head pointer of the endpoint
93     * descriptor to this one
94     */
95    if (td) {
96        // get the associated endpoint
97        ed = xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set];
98
99        ed->ed_headP = td->td_self;
100
101        // TODO: invalideate cache?
102
103        /*
104         * we need to make sure that the OHCI takes up this remaining
105         * transfer descriptor for processing.
106         */
107        if (xfer->type == USB_TYPE_BULK) {
108            /* TODO: write register BLF
109             * OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
110             */
111        }
112
113        if (xfer->type == USB_TYPE_CTRL) {
114            /* TODO: write register CLF
115             * OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
116             */
117        }
118    }
119}
120
121/**
122 * \brief   this function checks if a USB transfer is already finished or not
123 *
124 * \param   xfer    the usb transfer to check for completition
125 *
126 * \return  0       if the usb transfer is not finished
127 *          else    if the usb transfer is finished
128 */
129uint8_t usb_ohci_xfer_is_finished(struct usb_xfer *xfer)
130{
131    usb_ohci_ed_t *ed;
132    usb_paddr_t ed_headP;
133    usb_paddr_t ed_tailP;
134
135    // getting the endpoint from the queue head list
136    ed = xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set];
137
138    /* TODO: invalidate cache ? */
139
140    // get the transfer descriptor pointers
141    ed_headP = ed->ed_headP;
142    ed_tailP = ed->ed_tailP;
143
144    /*
145     *  if the endpoint is halted or there are no transfer descriptors
146     *  then there is no activitiy
147     */
148    if (USB_OHCI_EP_HALTED(ed) || !USB_OHCI_EP_HAS_TD(ed_headP, ed_tailP)) {
149        if (xfer->type == USB_TYPE_ISOC) {
150            // isochronus endponts have to be treated differently;
151            usb_ohci_xfer_done_isoc(xfer);
152
153            // transfer completed
154            return 1;
155        }
156
157        if (xfer->flags_internal.short_frames_ok) {
158            usb_ohci_xfer_short_frames(xfer);
159
160            if (xfer->hcd_td_cache) {
161                return 0;
162            }
163        }
164
165        // handle the data toggle flag
166        if (USB_OHCI_EP_CARRY(ed)) {
167            xfer->endpoint->data_toggle = 1;
168        } else {
169            xfer->endpoint->data_toggle = 0;
170        }
171
172        // handle the completition of the xfer
173        usb_ohci_xfer_done(xfer);
174
175        // transfers completed
176        return 1;
177    }
178
179    // transfer is not completed yet
180    return 0;
181}
182
183/**
184 * \brief This function updates the frame_lengths of the usb transfer
185 *
186 * \param xfer  the current USB transfer
187 *
188 * \return USB_ERR_OK on success
189 *         USB_ERR_IO
190 *         USB_ERR_STALLED
191 */
192static usb_error_t usb_ohci_xfer_update_frame_lengths(struct usb_xfer *xfer)
193{
194    usb_ohci_td_t *td;
195    usb_ohci_td_t *td_alt_next;
196    uint32_t temp;
197    usb_paddr_t phy_start;
198    usb_paddr_t phy_end;
199    usb_ohci_td_ctrl_t td_flags;
200
201    uint16_t cc;
202
203    td = xfer->hcd_td_cache;
204    td_alt_next = td->alt_next;
205
206    usb_ohci_td_ctrl_t td_flags_zero = {0,0,0,0,0,0,0};
207
208    td_flags = td_flags_zero;
209
210    if (xfer->actual_frames != xfer->num_frames) {
211        if (xfer->actual_frames < xfer->max_frame_count) {
212            xfer->frame_lengths[xfer->actual_frames] = 0;
213        } else {
214            // TODO: error handling if actual frame is bigger than max frames
215            assert(!"Frame overflow");
216        }
217    }
218
219    while (1) {
220        phy_start = td->td_current_buffer;
221        td_flags = td->td_control;
222        cc = td_flags.condition_code;
223
224        if (phy_start) {
225            /*
226             * the current buffer pointer is non zero, this means we
227             * have some data in the buffer, but buffer is not full.
228             * i.e. we have to deal with short transfers
229             */
230            phy_end = td->td_buffer_end;
231
232            /*
233             * calculate the remaining bytes in the buffer.
234             * Basically end-start + 1
235             */
236            temp = (USB_OHCI_PAGE(phy_start ^ phy_end) ?
237                    (USB_OHCI_PAGE_SIZE + 1) : 0x0001);
238            temp += USB_OHCI_PAGE_OFFSET(phy_end);
239            temp -= USB_OHCI_PAGE_OFFSET(phy_start);
240
241            /*
242             * we may have more data in the buffer left as the transfer
243             * size indicates. That case we stall the transfer.
244             */
245            if (temp > td->len) {
246                cc = USB_OHCI_STATUS_STALL;
247            } else if (xfer->actual_frames != xfer->num_frames) {
248                /*
249                 * set the frame_length of the actual frame
250                 */
251                xfer->frame_lengths[xfer->actual_frames] += td->len - temp;
252            }
253        } else {
254            /*
255             * the transfer was complete one frame before, so we
256             * set the frame length of the actual frame to be the
257             * total transfer length
258             */
259            if (xfer->actual_frames != xfer->num_frames) {
260                xfer->frame_lengths[xfer->actual_frames] += td->len;
261            }
262        }
263
264        /*
265         * if this TD was the last of USB the transfer, we are done and
266         * can go out of the loop (tranfer finished).
267         */
268        if (((void *) td) == xfer->hcd_td_last) {
269            td = NULL;
270            break;
271        }
272
273        /*
274         * if we have a condition flag other than USB_OHCI_STATUS_OK then
275         * we treat this as completed and go out of the loop.
276         * (transfer finished).
277         */
278        if (cc) {
279            td = NULL;
280            break;
281        }
282
283        /*
284         * we encountered a short transfer, we have to check now if
285         * short transfers are acceptable or not by checking the
286         * short_frames_ok flag. If this is the case, we follow the
287         * alternative next pointer to the TD filling up the remainder of
288         * this frame. If short frames are not acceptable this means
289         * we have reached the end of the transfer
290         */
291        if (phy_start) {
292            if (xfer->flags_internal.short_frames_ok) {
293                td = td->alt_next;
294            } else {
295                td = NULL;
296            }
297            break;
298        }
299
300        // take the next TD in the list
301        td = td->obj_next;
302
303        /*
304         * we have a new alternative next pointer this belongs
305         * to another transfer thus this transfer is complete
306         */
307        if (td->alt_next != td_alt_next) {
308            break;
309        }
310    }
311
312    /* update transfer cache */
313
314    xfer->hcd_td_cache = td;
315
316    return ((cc == USB_OHCI_STATUS_OK) ? USB_ERR_OK :
317            (cc == USB_OHCI_STATUS_STALL) ? USB_ERR_STALLED : USB_ERR_IOERROR);
318}
319
320/**
321 * \brief   this function handles the completion of a transfer
322 *
323 * \param   xfer    the usb transfer to handle completion
324 */
325void usb_ohci_xfer_done(struct usb_xfer *xfer)
326{
327    usb_error_t err = USB_ERR_OK;
328
329    /*
330     * go over the td list and handle the competition
331     */
332    xfer->hcd_td_cache = xfer->hcd_td_first;
333
334    /*
335     * check if it is a control transfer. If this is the case
336     * we may need to do some extra work, because control headers
337     * could be requested
338     */
339    if (xfer->flags_internal.ctrl_xfer) {
340        if (xfer->flags_internal.ctrl_header) {
341            err = usb_ohci_xfer_update_frame_lengths(xfer);
342        }
343        xfer->actual_frames = 1;
344
345        if (xfer->hcd_td_cache == NULL) {
346            usb_ohci_xfer_remove(xfer, err);
347            return;
348        }
349    }
350
351    /*
352     * process the remaining frames till all is complete
353     */
354    while (xfer->actual_frames < xfer->num_frames) {
355        err = usb_ohci_xfer_update_frame_lengths(xfer);
356        xfer->actual_frames++;
357
358        if (xfer->hcd_td_cache == NULL) {
359            usb_ohci_xfer_remove(xfer, err);
360            return;
361        }
362    }
363
364    /*
365     * check if there is a control transfer active at the moment
366     */
367    if (xfer->flags_internal.ctrl_xfer && !xfer->flags_internal.ctrl_active) {
368        err = usb_ohci_xfer_update_frame_lengths(xfer);
369    }
370
371    usb_ohci_xfer_remove(xfer, err);
372
373}
374
375/**
376 * \brief
377 *
378 * \param   xfer    the usb transfer to check for completion
379 *
380 * \return  0       if the usb transfer is not finished
381 *          else    if the usb transfer is finished
382 */
383void usb_ohci_xfer_done_isoc(struct usb_xfer *xfer)
384{
385    assert(!"NYI: need to check isochronus transfer competition");
386}
387
388/**
389 * \brief This function is called by the specific pipe functions when a
390 *        usb transfer is finished. The transfer descriptors are removed
391 *        from the endpoint lists.
392 *
393 * \param xfer  the usb transfer request that is finished
394 * \param error status code of the finished transfer request
395 */
396void usb_ohci_xfer_remove(struct usb_xfer *xfer, usb_error_t error)
397{
398    usb_ohci_ed_t *ed;
399
400    // get the host controller
401    usb_ohci_hc_t *hc = (usb_ohci_hc_t *) xfer->host_controller->hc_control;
402
403    // get the endpoint associated with the usb transfer
404    ed = xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set];
405
406    // TODO: invalidate page cache of endpoint
407
408    switch (xfer->type) {
409        case USB_TYPE_ISOC:
410            usb_ohci_remove_qh(ed, hc->qh_isoc_last);
411            break;
412        case USB_TYPE_INTR:
413            usb_ohci_remove_qh(ed, hc->qh_intr_last[xfer->intr_qh_pos]);
414            break;
415        case USB_TYPE_CTRL:
416            usb_ohci_remove_qh(ed, hc->qh_ctrl_last);
417            break;
418        case USB_TYPE_BULK:
419            usb_ohci_remove_qh(ed, hc->qh_bulk_last);
420            break;
421        default:
422            assert(!"Invalid Transfer Type");
423            break;
424    }
425
426    // set the transfer descriptor pointers to null
427    xfer->hcd_td_first = NULL;
428    xfer->hcd_td_last = NULL;
429
430    /*
431     * remove from interrupt queue and enqueue to done queue
432     */
433    usb_xfer_done(xfer, error);
434}
435
436/*
437 * \brief enqueues the transfer on the controller's interrupt queue to
438 *        handle the completed transfers
439 *
440 * \param xfer  the transfer to enqueue
441 */
442void usb_ohci_xfer_enqueue(struct usb_xfer *xfer)
443{
444    /* check for early completion */
445    if (usb_ohci_xfer_is_finished(xfer)) {
446        return;
447    }
448    /* put transfer on interrupt queue */
449    usb_xfer_enqueue(&xfer->host_controller->intr_queue, xfer);
450
451    /* start timeout, if any */
452    /* TODO: handle time out
453     if (xfer->timeout != 0) {
454     usbd_transfer_timeout_ms(xfer, &ohci_timeout, xfer->timeout);
455     }*/
456}
457
458struct usb_ohci_setup_td {
459    usb_ohci_td_t *td;
460    usb_ohci_td_t *td_next;
461    uint32_t average;
462    usb_ohci_td_ctrl_t td_flags;
463    uint32_t len;
464    uint16_t max_frame_size;
465    uint8_t shortpkt;
466    uint8_t setup_alt_next;
467    uint8_t last_frame;
468};
469
470/**
471 * \brief   this function is used to setup the transfer descriptors
472 *          and allocating buffers for the transfers
473 *
474 * \param temp  setup information for the transfer descriptors
475 */
476static void usb_ohci_xfer_setup_td(struct usb_ohci_setup_td *temp)
477{
478    usb_ohci_td_t *td;
479    usb_ohci_td_t *td_next;
480    usb_ohci_td_t *td_alt_next = NULL;
481
482    uint32_t average = 0;
483    uint8_t old_shortpkt = temp->shortpkt;
484    uint32_t old_len = temp->len;
485
486    /*
487     * this is used to precompute the length of the transfer
488     */
489    uint8_t precompute = 1;
490    uint8_t restart = 1;
491
492    /*
493     * we are using software to detect short packets thus we allow
494     * buffer rounding i.e. the buffer does not have to be filled
495     * completely
496     */
497    if (temp->td_flags.direction_pid == USB_OHCI_PID_IN) {
498        temp->td_flags.rounding = 1;
499    } else {
500        temp->td_flags.rounding = 0;
501    }
502
503    td = temp->td;
504    td_next = temp->td_next;
505
506    while (restart) {
507
508        while (1) {
509            if (temp->len == 0) {
510                /*
511                 * handling of zero length packets. these packets are sent last
512                 * thus we stop processing if we see the short packet flag
513                 */
514                if (temp->shortpkt) {
515                    break;
516                }
517
518                temp->shortpkt = 1;
519                average = 0;
520
521            } else {
522                average = temp->average;
523
524                /*
525                 * check if the length of the transfer is smaller than the
526                 * average i.e. if we have a short packet not using the whole
527                 * USB frame
528                 */
529                if (temp->len < average) {
530                    if (temp->len % temp->max_frame_size) {
531                        temp->shortpkt = 1;
532                    }
533                    average = temp->len;
534                }
535            }
536
537            if (td_next == NULL) {
538                /*
539                 * TODO: PANIC: not enough transport descriptors
540                 */
541                assert(!"ran out of transfer descriptors!");
542            }
543
544            /*
545             * get the next td to process
546             */
547            td = td_next;
548            td_next = td->obj_next;
549
550            /*
551             * check if we are pre-computing the lengths.
552             * update the remaining length and continue with the loop
553             */
554            if (precompute) {
555                temp->len -= average;
556
557                continue;
558            }
559
560            /* fill in the current TD with the data */
561            td->td_control = temp->td_flags;
562
563            /* the next td uses the toggle carry */
564            temp->td_flags.data_toggle = 1;
565
566            /*
567             * setup the fields in the transfer descriptor depending on the
568             * packet size, zero length packets do not need a buffer
569             * buffer but other wise we need
570             */
571            if (average == 0) {
572                td->td_current_buffer = 0;
573                td->td_buffer_end = 0;
574                td->len = 0;
575            } else {
576                // buffer size is bigger than the td internal buffer
577                if (average > USB_OHCI_TD_BUFFER_SIZE) {
578                    /*
579                     * TODO: allocate a bigger buffer here
580                     */
581                    assert(!"NYI: handling of biger buffers ");
582                } else {
583                    td->td_current_buffer = td->td_self
584                            + USB_OHCI_TD_BUFFER_OFFSET;
585                    td->td_buffer_end = td->td_current_buffer + average;
586                }
587
588                /* set the length of this transfer descriptor */
589                td->len = average;
590
591                /* update the remaining length of the transfer */
592                temp->len -= average;
593            }
594
595            if ((td_next == td_alt_next) && temp->setup_alt_next) {
596                /*
597                 * we have to setup the alternative transfer descriptors
598                 * because we need to receive these frames one by one
599                 *
600                 * - delay interrupts must be 1
601                 * - last td in the list
602                 */
603                td->td_control.delay_interrupt = 1;
604                td->td_nextTD = 0;
605
606            } else {
607                /*
608                 * do the linking of the transfer descriptors using
609                 * their physical addresses if there is another
610                 * td in the list
611                 */
612                if (td_next) {
613                    td->td_nextTD = td_next->td_self;
614                }
615            }
616
617            td->alt_next = td_alt_next;
618        }
619
620        if (precompute) {
621            precompute = 0;
622
623            /* the last frame does not have an alternative next td */
624            if (temp->last_frame) {
625                td_alt_next = NULL;
626            } else {
627                td_alt_next = td_next;
628            }
629
630            /*
631             * we were precomputing so we need to restore the values
632             */
633            temp->shortpkt = old_shortpkt;
634            temp->len = old_len;
635        } else {
636            restart = 0;
637        }
638
639    }
640
641    temp->td = td;
642    temp->td_next = td_next;
643}
644
645/**
646 * \brief   this function sets up the standard chains for the  transfer
647 *          descriptors for an USB transfer.
648 *
649 * \param xfer      the usb transfer to setup the transfer descriptors
650 * \param ed_last   the last endpoint descriptor
651 */
652void usb_ohci_xfer_start(struct usb_xfer *xfer, usb_ohci_ed_t **ed_last)
653{
654    struct usb_ohci_setup_td temp;
655    struct usb_hcdi_pipe_fn *pipe_fn;
656
657    usb_ohci_ed_t *ed;
658    usb_ohci_td_t *td;
659    usb_ohci_ed_ctrl_t ed_flags;
660    uint32_t x;
661
662    /*
663     * getting the size information out of the xfer
664     */
665    temp.average = xfer->max_hc_frame_size;
666    temp.max_frame_size = xfer->max_frame_size;
667
668    /* toggle the next DMA set bit and get the next set */
669    xfer->flags_internal.curr_dma_set ^= 1;
670    td = xfer->hcd_td_start[xfer->flags_internal.curr_dma_set];
671
672    /* update the beginning of the td list */
673    xfer->hcd_td_first = td;
674    xfer->hcd_td_cache = td;
675
676    temp.td = NULL;
677    temp.td_next = td;
678    temp.last_frame = 0;
679    temp.setup_alt_next = xfer->flags_internal.short_frames_ok;
680
681    pipe_fn = xfer->endpoint->pipe_fn;
682
683    /*
684     * check if we have to prepend a setup message, this is the case
685     * if we are handling with control transfers and a header is requested
686     */
687    if (xfer->flags_internal.ctrl_xfer) {
688        if (xfer->flags_internal.ctrl_header) {
689            temp.td_flags.data_toggle = 0;
690            temp.td_flags.condition_code = 0;
691            temp.td_flags.direction_pid = USB_OHCI_PID_SETUP;
692            temp.td_flags.delay_interrupt = USB_OHCI_TD_DISABLE_IRQ;
693
694            temp.len = xfer->frame_lengths[0];
695            temp.shortpkt = temp.len ? 1 : 0;
696
697            /* check if this is the last frame, i.e. there is no data stage */
698            if (xfer->num_frames == 1) {
699                if (xfer->flags_internal.ctrl_active) {
700                    temp.last_frame = 1;
701                    temp.setup_alt_next = 0;
702                }
703            }
704            usb_ohci_xfer_setup_td(&temp);
705
706            xfer->endpoint->data_toggle = 1;
707        }
708        x = 1;
709    } else {
710        x = 0;
711    }
712
713    temp.td_flags.condition_code = 0;
714    temp.td_flags.delay_interrupt = USB_OHCI_TD_DISABLE_IRQ;
715
716    if (xfer->endpoint->data_toggle) {
717        temp.td_flags.data_toggle = 1;
718    } else {
719        temp.td_flags.data_toggle = 0;
720    }
721
722    if (xfer->ed_direction == USB_OHCI_ED_DIRECTION_IN) {
723        temp.td_flags.direction_pid = USB_OHCI_PID_IN;
724    } else {
725        temp.td_flags.direction_pid = USB_OHCI_PID_OUT;
726    }
727
728    while (x != xfer->num_frames) {
729
730        /*
731         * Handling DATA0 and DATA1 packets
732         */
733        temp.len = xfer->frame_lengths[x++];
734
735        if (x == xfer->num_frames) {
736            if (xfer->flags_internal.ctrl_xfer) {
737                if (xfer->flags_internal.ctrl_active) {
738                    /* no STATUS stage, just DATA */
739                    temp.last_frame = 1;
740                    temp.setup_alt_next = 0;
741                }
742            } else {
743                temp.last_frame = 1;
744                temp.setup_alt_next = 0;
745            }
746
747        }
748
749        if (temp.len == 0) {
750            /* this is a short packet  but we want to send an USB packet */
751            temp.shortpkt = 0;
752        } else {
753            temp.shortpkt = (xfer->flags.short_xfer_forced) ? 0 : 1;
754        }
755
756        usb_ohci_xfer_setup_td(&temp);
757    }
758
759    /*
760     * control transfer have a status stage, check if we have to append
761     * such a status stage
762     */
763    if (xfer->flags_internal.ctrl_xfer && !xfer->flags_internal.ctrl_active) {
764        memset(&temp.td_flags, 0, sizeof(usb_ohci_td_ctrl_t));
765        temp.td_flags.condition_code = 0;
766        temp.td_flags.data_toggle = 1;
767        temp.td_flags.delay_interrupt = 1;
768        if (xfer->ed_direction == USB_OHCI_ED_DIRECTION_IN) {
769            temp.td_flags.direction_pid = USB_OHCI_ED_DIRECTION_OUT;
770        } else {
771            temp.td_flags.direction_pid = USB_OHCI_ED_DIRECTION_OUT;
772        }
773
774        temp.len = 0;
775        temp.shortpkt = 0;
776        temp.last_frame = 1;
777        temp.setup_alt_next = 0;
778
779        usb_ohci_xfer_setup_td(&temp);
780    }
781
782    td = temp.td;
783
784    /* ensure that the last TD is terminating */
785    td->td_nextTD = 0;
786    td->td_control.delay_interrupt = 1;
787
788    xfer->hcd_td_last = td;
789
790    ed = xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set];
791
792    ed_flags.function_address = xfer->device_address;
793    ed_flags.endpoint_number = xfer->endpoint_number;
794    ed_flags.max_packet_size = xfer->max_frame_size;
795    ed_flags.td_format = USB_OHCI_ED_FORMAT_GENERAL;
796    ed_flags.direction = USB_OHCI_ED_DIRECTION_FROM_TD;
797
798    if (xfer->device->speed == USB_SPEED_LOW) {
799        ed_flags.speed = USB_OHCI_ED_LOWSPEED;
800    }
801
802    ed->ed_control = ed_flags;
803
804    td = xfer->hcd_td_first;
805
806    ed->ed_headP = td->td_self;
807
808    /* TODO: self suspended */
809    if (xfer->device->flags.self_suspended == 0) {
810
811    }
812}
813
814/**
815 * \brief   this function sets up a new usb transfer on the host controller
816 *
817 * \param   param the parameters to setup the usb transfer
818 *
819 */
820void usb_ohci_xfer_setup(struct usb_xfer_setup_params *param)
821{
822    struct usb_xfer *xfer = param->curr_xfer;
823    void *last_obj;
824    /*
825     * variables to track how many descriptors we have to allocate
826     */
827    uint32_t num_td = 0;
828    uint32_t num_itd = 0;
829    uint32_t num_qh = 0;
830    uint32_t n = 0;
831
832    /*
833     * set the OHCI specific values
834     */
835    param->hc_max_packet_count = 1;
836    param->hc_max_packet_size = 0x500;
837    param->hc_max_frame_size = USB_OHCI_PAGE_SIZE;
838
839    /* TODO: set BDMA enabled?  */
840    usb_xfer_setup_struct(param);
841
842    switch (param->type) {
843        case USB_TYPE_ISOC:
844            num_itd = ((xfer->max_data_length / USB_OHCI_PAGE_SIZE)
845                    + ((xfer->num_frames + USB_OHCI_ISOCHRONUS_TD_OFFSETS - 1)
846                            / USB_OHCI_ISOCHRONUS_TD_OFFSETS) + 1);
847            break;
848        case USB_TYPE_INTR:
849            num_td = ((2 * xfer->num_frames)
850                    + xfer->max_data_length / xfer->max_hc_frame_size);
851            num_qh = 1;
852            break;
853        case USB_TYPE_CTRL:
854            num_td = ((2 * xfer->num_frames) + 1 /* STATUS stage*/
855            + (xfer->max_data_length / xfer->max_hc_frame_size));
856            num_qh = 1;
857            break;
858        case USB_TYPE_BULK:
859            num_qh = 1;
860            num_td = ((2 * xfer->num_frames)
861                    + (xfer->max_data_length / xfer->max_hc_frame_size));
862            break;
863    }
864    uint8_t alloc_dma_set;
865    do {
866        alloc_dma_set = xfer->flags_internal.curr_dma_set;
867
868        /*
869         * check if setting up the usb transfer succeeded
870         */
871        if (param->err) {
872            return;
873        }
874
875        last_obj = NULL;
876
877        /*
878         * allocate memory for the transfer descriptors
879         */
880        usb_ohci_td_t *td;
881        for (n = 0; n < num_td; n++) {
882            td = usb_ohci_td_alloc();
883            if (td == NULL) {
884                param->err = USB_ERR_NOMEM;
885                // free the allocated td's
886                for (td = last_obj; td != NULL; td = td->obj_next) {
887                    usb_ohci_td_free(td);
888                }
889                return;
890            }
891
892            td->obj_next = last_obj;
893            last_obj = td;
894        }
895
896        /*
897         * allocate memory for the isochronus transfer descriptors
898         */
899        usb_ohci_itd_t *itd;
900        for (n = 0; n < num_itd; n++) {
901            itd = usb_ohci_itd_alloc();
902            if (itd == NULL) {
903                param->err = USB_ERR_NOMEM;
904                // free the allocated iTDs
905                for (uint32_t i = 0; i < n; i++) {
906                    itd = last_obj;
907                    last_obj = itd->obj_next;
908                    usb_ohci_itd_free(itd);
909                }
910
911                // free the allocated TDs
912                for (n = 0; n < num_td; n++) {
913                    td = last_obj;
914                    last_obj = td->obj_next;
915                    usb_ohci_td_free(td);
916                }
917                return;
918            }
919
920            itd->obj_next = last_obj;
921            last_obj = itd;
922        }
923        xfer->hcd_td_start[xfer->flags_internal.curr_dma_set] = last_obj;
924
925        /*
926         * allocate memory for the queue heads
927         */
928        usb_ohci_ed_t *ed;
929        last_obj = NULL;
930        for (n = 0; n < num_qh; n++) {
931            ed = usb_ohci_ed_alloc();
932            if (ed == NULL) {
933                for (ed = last_obj; ed != NULL; ed = ed->obj_next) {
934                    usb_ohci_ed_free(ed);
935                }
936                last_obj =
937                        xfer->hcd_td_start[xfer->flags_internal.curr_dma_set];
938                for (n = 0; n < num_itd; n++) {
939                    itd = last_obj;
940                    last_obj = itd->obj_next;
941                    usb_ohci_itd_free(itd);
942                }
943                for (n = 0; n < num_td; n++) {
944                    td = last_obj;
945                    last_obj = td->obj_next;
946                    usb_ohci_td_free(td);
947                }
948            }
949            last_obj = ed;
950        }
951        xfer->hcd_qh_start[xfer->flags_internal.curr_dma_set] = last_obj;
952
953        if (!xfer->flags_internal.curr_dma_set) {
954            xfer->flags_internal.curr_dma_set = 1;
955        }
956    } while (!alloc_dma_set);
957}
958
959/**
960 * \brief   this function is a stub to unsetup a usb transfer
961 *
962 */
963void usb_ohci_xfer_unsetup(struct usb_xfer *xfer)
964{
965    return;
966}
967
968