1/**
2 * \brief This file contains code to initalize the EHCI controller and to
3 *        handle the interrupts
4 */
5
6/*
7 * Copyright (c) 2007-2013 ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <stdlib.h>
16#include <stdio.h>
17#include <string.h>
18#include <barrelfish/barrelfish.h>
19
20#include <usb/usb.h>
21
22#include <usb_controller.h>
23#include <usb_device.h>
24
25#include "usb_ehci.h"
26#include "usb_ehci_memory.h"
27#include "usb_ehci_bus.h"
28#include "usb_ehci_root_hub.h"
29#include "usb_ehci_xfer.h"
30
31/**
32 * \brief   performs a soft reset on the EHCI host controller
33 *
34 * \param   hc the ehci controller to reset
35 */
36usb_error_t usb_ehci_hc_reset(usb_ehci_hc_t *hc)
37{
38    /* write the reset bit */
39    ehci_usbcmd_hcr_wrf(&hc->ehci_base, 1);
40
41    /* wait some time to let rest complete */
42    lib_usb_wait(200);
43
44    for (uint8_t i = 0; i < 10; i++) {
45        if (ehci_usbcmd_hcr_rdf(&hc->ehci_base)) {
46            /*
47             * the host controller sets this bit to 0 if the rest is complete
48             * therefore we have to wait some more time
49             */
50            lib_usb_wait(200);
51            continue;
52        }
53    }
54
55    /* last check if reset was completed */
56    if (ehci_usbcmd_hcr_rdf(&hc->ehci_base)) {
57        return (USB_ERR_TIMEOUT);
58    }
59
60    usb_error_t err = USB_ERR_OK;
61
62    /*
63     * The EHCI specification says that certain registers must have a
64     * defined value after reset while others are undefined.
65     *
66     * The following code checks if the reset was successful.
67     */
68    if ((ehci_usbcmd_rawrd(&hc->ehci_base) & 0xFFFFF0FF) != 0x00080000) {
69        debug_printf("WARNING: USBCMD has wrong value.\n");
70        err = USB_ERR_IOERROR;
71    }
72    if (ehci_usbsts_rawrd(&hc->ehci_base) != 0x00001000) {
73        debug_printf("WARNING: USBST has wrong value.\n");
74        err = USB_ERR_IOERROR;
75    }
76    if (ehci_usbintr_rawrd(&hc->ehci_base) != 0x00000000) {
77        debug_printf("WARNING: USBINTR has wrong value.\n");
78        err = USB_ERR_IOERROR;
79    }
80    if (ehci_frindex_rawrd(&hc->ehci_base) != 0x00000000) {
81        debug_printf("WARNING:FRINDEX has wrong value.\n");
82        err = USB_ERR_IOERROR;
83    }
84    if (ehci_ctrldssegment_rawrd(&hc->ehci_base) != 0x00000000) {
85        debug_printf("WARNING: Reset is succeeded: CTRLDS has wrong value.\n");
86        err = USB_ERR_IOERROR;
87    }
88    if (ehci_configflag_rawrd(&hc->ehci_base) != 0x00000000) {
89        debug_printf("WARNING: CONFIGFLG has wrong value.\n");
90        err = USB_ERR_IOERROR;
91    }
92    if ((ehci_portsc_rawrd(&hc->ehci_base, 0) | 0x00001000) != 0x00003000) {
93        debug_printf("WARNING: PORTSC has wrong value.\n");
94        err = USB_ERR_IOERROR;
95    }
96
97    return (err);
98}
99
100/**
101 * \brief halts the EHCI controller. Running transactions are finished first
102 *
103 * \param hc the host controller to halt
104 */
105static usb_error_t usb_ehci_hc_halt(usb_ehci_hc_t *hc)
106{
107    /* write the reset bit */
108    ehci_usbcmd_wr(&hc->ehci_base, 0x0);
109
110    /*
111     * Wait some time before start checking
112     */
113    lib_usb_wait(200);
114
115    /* wait until the reset is done */
116    for (uint8_t i = 0; i < 10; i++) {
117        if (ehci_usbsts_hch_rdf(&hc->ehci_base)) {
118            /* all activity halted, return */
119            return (USB_ERR_OK);
120        }
121        lib_usb_wait(200);
122    }
123
124    /* check if halted */
125    if (ehci_usbsts_hch_rdf(&hc->ehci_base)) {
126        /* all activity halted, return */
127        return (USB_ERR_OK);
128    }
129
130    return (USB_ERR_TIMEOUT);
131}
132
133usb_error_t usb_ehci_initialize_controller(usb_ehci_hc_t *hc)
134{
135    /*
136     * XXX: 64 bit data structures are not supported at the moment
137     */
138    if (ehci_hccparams_bit64ac_rdf(&hc->ehci_base)) {
139        debug_printf("NYI: Host controller uses 64-bit memory addresses!\n");
140        return (USB_ERR_BAD_CONTEXT);
141
142        ehci_ctrldssegment_wr(&hc->ehci_base, 0);
143    }
144
145    /*
146     * STEP 1: Setting the start addresses of the periodic and asynchronous
147     *         transfer lists
148     */
149    ehci_periodiclistbase_wr(&hc->ehci_base, hc->pframes_phys);
150    ehci_asynclistaddr_wr(&hc->ehci_base, hc->qh_async_last->qh_self);
151
152    /*
153     * STEP 2: Setting the USBCMD register
154     */
155    ehci_usbcmd_t cmd = 0;
156    // interrupt threshold to 1 micro frame
157    cmd = ehci_usbcmd_itc_insert(cmd, 1);
158    // enable the async schedule
159    cmd = ehci_usbcmd_ase_insert(cmd, 1);
160    // enable the periodic schedule
161    cmd = ehci_usbcmd_pse_insert(cmd, 1);
162    // keep the frame list size
163    cmd = ehci_usbcmd_fls_insert(cmd, ehci_usbcmd_fls_rdf(&hc->ehci_base));
164    // start the host controller
165    cmd = ehci_usbcmd_rs_insert(cmd, 1);
166
167    // write the cmd value to the register
168    ehci_usbcmd_wr(&hc->ehci_base, cmd);
169
170    /*
171     * STEP 3: Take over the port ownership
172     */
173    ehci_configflag_cf_wrf(&hc->ehci_base, 1);
174
175    /* wait till the HC is up and running */
176    lib_usb_wait(200);
177    for (uint32_t i = 0; i < 10; i++) {
178        if (!ehci_usbsts_hch_rdf(&hc->ehci_base)) {
179            break;
180        }
181        lib_usb_wait(200);
182    }
183
184
185    if (ehci_usbsts_hch_rdf(&hc->ehci_base)) {
186        /* the host controller is still not started. */
187        return (USB_ERR_TIMEOUT);
188    }
189
190    /*
191     * STEP 4: Enable the interrupts
192     */
193    ehci_usbintr_wr(&hc->ehci_base, hc->enabled_interrupts);
194
195    /*
196     * STEP 5: Check if everything is fine i.e. controller running.
197     */
198    if (ehci_usbsts_hch_rdf(&hc->ehci_base)) {
199        /*
200         * the HC does not want to do what we want
201         */
202        debug_printf("ERROR: Host controller does not start...\n");
203
204        return (USB_ERR_IOERROR);
205    }
206
207    /*
208     * STEP 4: Enable power on the ports.
209     *
210     * R/W���Host controller has port power control switches. This bit
211     * represents the current setting of the switch (0 = off, 1 = on). When
212     * power is not available on a port (i.e. PP equals a 0), the port is non-
213     * functional and will not report attaches, detaches, etc.
214     */
215    if (ehci_hcsparams_ppc_rdf(&hc->ehci_base)) {
216        for (uint8_t i = 0; i < hc->rh_num_ports; i++) {
217            ehci_portsc_pp_wrf(&hc->ehci_base, i, 1);
218        }
219    }
220
221    debug_printf("EHCI controller up and running.\n");
222
223    return (USB_ERR_OK);
224}
225
226
227/**
228 * \brief   Interrupt handler for the EHCI controller hardware
229 *
230 * \param   hc  host controller
231 */
232void usb_ehci_interrupt(usb_host_controller_t *host)
233{
234    USB_DEBUG_TR_ENTER;
235
236    usb_ehci_hc_t *hc = (usb_ehci_hc_t *) host->hc_control;
237
238    /*
239     * read the status register and mask out the interrupts [5..0]
240     */
241    ehci_usbsts_t intr = ehci_usbsts_rawrd(&hc->ehci_base) & 0x3F;
242
243    if (!(intr)) {
244        /* there was no interrupt for this controller */
245        return;
246    }
247
248    if (!(intr & hc->enabled_interrupts)) {
249        /* there was an interrupt we dont have enabled */
250        USB_DEBUG("Unenabled interrupt happened.\n");
251        return;
252    }
253
254    /* acknowledge the interrupts */
255    ehci_usbsts_wr(&hc->ehci_base, intr);
256
257    intr &= hc->enabled_interrupts;
258
259    if (ehci_usbsts_hse_extract(intr)) {
260        /*
261         * host system error -> unrecoverable error
262         * serious error occurs during a host system access involving the host
263         * controller module.
264         */
265        USB_DEBUG("EHCI controller encountered an unrecoverable error\n");
266        USER_PANIC("NYI: handling of unrecoverable errors! \n");
267
268    }
269
270    uint8_t pcd_disabled = 0;
271
272    if (ehci_usbsts_pcd_extract(intr)) {
273        /*
274         * port change detected
275         * there is something going on on the port e.g. a new device is attached
276         *
277         * This interrupt stays enabled until the port is reset, so to avoid
278         * multiple interrupts, disable the port change interrupts for now.
279         */
280        ehci_usbsts_pcd_insert(hc->enabled_interrupts, 0);
281
282        /* disable the PCD interrupt for now */
283        ehci_usbintr_pcie_wrf(&hc->ehci_base, 0);
284
285        pcd_disabled = 1;
286
287        /* handle port status change */
288        usb_ehci_roothub_interrupt(hc);
289    }
290
291    intr = ehci_usbsts_pcd_insert(intr, 0);
292    intr = ehci_usbsts_iaa_insert(intr, 0);
293    intr = ehci_usbsts_usbei_insert(intr, 0);
294    intr = ehci_usbsts_usbi_insert(intr, 0);
295
296    if (intr != 0) {
297        USB_DEBUG("NOTICE: Blocking interrupt %"PRIx32"\n", intr);
298        /*
299         * there is still an interrupt left, so block on this type
300         */
301        hc->enabled_interrupts &= ~intr;
302        ehci_usbintr_wr(&hc->ehci_base, hc->enabled_interrupts);
303    }
304
305    /* poll the USB transfers */
306    usb_ehci_poll(hc);
307
308    if (pcd_disabled) {
309        /* enable the port status change interrupt again */
310        ehci_usbintr_pcie_insert(hc->enabled_interrupts, 1);
311        ehci_usbintr_pcie_wrf(&hc->ehci_base, 1);
312    }
313
314    USB_DEBUG_TR_RETURN;
315}
316
317/**
318 * \brief initializes the ehci host controller and creates the queues
319 *
320 * \param hc the ehci controller to initialize
321 * \param base the base address of the ehci controller
322 */
323usb_error_t usb_ehci_init(usb_ehci_hc_t *hc, uintptr_t base)
324{
325    /*
326     * STEP 1: Mackerel init
327     * Initialization of the ehci_t struct has to be done in two steps
328     * since the ehci has capability registers and operational registers
329     * which offsets has to be read out of the caplength register first.
330     */
331    ehci_initialize(&hc->ehci_base, (mackerel_addr_t) base, NULL);
332
333    /* getting the operational register offset */
334    uint8_t cap_offset = ehci_caplength_rd(&hc->ehci_base);
335
336    if (cap_offset == 0) {
337        debug_printf("ERROR: EHCI capability register length is zero.\n");
338        return (USB_ERR_INVAL);
339    }
340
341    ehci_initialize(&hc->ehci_base, (mackerel_addr_t) base,
342            (mackerel_addr_t) (base + cap_offset));
343
344    /*
345     * STEP 2: getting the number of ports and the revision
346     */
347    hc->ehci_revision = ehci_hciversion_rd(&hc->ehci_base);
348    hc->rh_num_ports = ehci_hcsparams_n_ports_rdf(&hc->ehci_base);
349
350    debug_printf("Device found: EHCI controller rev: %x.%x with %u ports\n",
351            hc->ehci_revision >> 8, hc->ehci_revision & 0xFF, hc->rh_num_ports);
352
353    /*
354     * STEP 3: perform halt
355     * This stops the execution of (potentially) existing transfers
356     */
357    usb_error_t err;
358    err = usb_ehci_hc_halt(hc);
359    if (err != USB_ERR_OK) {
360        debug_printf("WARNING: Host controller has not halted properly.\n");
361    }
362
363    /*
364     * STEP 4: perform host controller reset
365     * Performing a reset also checks the register fields for the correct values
366     */
367    err = usb_ehci_hc_reset(hc);
368    if (err != USB_ERR_OK) {
369        debug_printf("ERROR: Host controller not reset properly. \n");
370    }
371
372    /* after reset this field should have been initialized to a valid value */
373    if (ehci_usbcmd_fls_rdf(&hc->ehci_base) == ehci_frame_rsvd) {
374        /*
375         * this field should be initialized to a correct values
376         * having FLS=0x3 is invalid!
377         */
378        debug_printf("ERROR: Wrong frame length size\n");
379        return (USB_ERR_IOERROR);
380    }
381
382    /*
383     * STEP 5: init the generic host controller
384     * This fills out the missing fields of the generic host controller
385     */
386    hc->controller->hcdi_bus_fn = usb_ehci_get_bus_fn();
387    hc->controller->usb_revision = USB_REV_2_0;
388    hc->controller->devices = hc->devices;
389    hc->controller->devices_max = USB_EHCI_MAX_DEVICES;
390
391    /*
392     * STEP 6: Setting up the enabled interrupts
393     * this does not activate them, just prepare it for later.
394     */
395    ehci_usbintr_t en_intrs = 0;
396    en_intrs = ehci_usbintr_iaae_insert(en_intrs, 0);
397    en_intrs = ehci_usbintr_hsee_insert(en_intrs, 1);
398    en_intrs = ehci_usbintr_pcie_insert(en_intrs, 1);
399    en_intrs = ehci_usbintr_usbie_insert(en_intrs, 1);
400    en_intrs = ehci_usbintr_usbeie_insert(en_intrs, 1);
401    hc->enabled_interrupts = en_intrs;
402
403    /*
404     * STEP 7: Setting up the initial transfer queues
405     */
406    usb_ehci_qh_t *qh;
407
408    /* setup the terminate qheue head */
409    qh = usb_ehci_qh_alloc();
410    qh->qh_next_qtd = USB_EHCI_LINK_TERMINATE;
411    qh->qh_alt_next_qtd = USB_EHCI_LINK_TERMINATE;
412    qh->qh_status.status = USB_EHCI_QTD_STATUS_HALTED;
413    hc->qh_terminate = qh;
414
415    /*
416     * STEP 7.1a: Initialize the interrupt transfer queues
417     */
418    for (uint32_t i = 0; i < USB_EHCI_VFRAMELIST_COUNT; i++) {
419        qh = usb_ehci_qh_alloc();
420
421        hc->qh_intr_last[i] = qh;
422        qh->qh_ep.ep_speed = USB_EHCI_QH_SPEED_HIGH;
423        qh->qh_ep.mult = 1;
424        qh->qh_curr_qtd = 0;
425        qh->qh_next_qtd = USB_EHCI_LINK_TERMINATE;
426        qh->qh_alt_next_qtd = USB_EHCI_LINK_TERMINATE;
427        qh->qh_status.status = USB_EHCI_QTD_STATUS_HALTED;
428        qh->qh_self |= USB_EHCI_LINKTYPE_QH;
429    }
430
431    /*
432     * STEP 7.1b: Link the queue heads together that they form the 2ms
433     *            polling interval
434     */
435    uint16_t bit = USB_EHCI_VFRAMELIST_COUNT / 2;
436    uint32_t curr, next;
437
438    while (bit) {
439        curr = bit;
440        while (curr & bit) {
441            usb_ehci_qh_t *qh_curr;
442            usb_ehci_qh_t *qh_next;
443
444            next = (curr ^ bit) | (bit / 2);
445
446            qh_curr = hc->qh_intr_last[curr];
447            qh_next = hc->qh_intr_last[next];
448
449            qh_curr->qh_link = qh_next->qh_self;
450
451            curr++;
452        }
453        bit >>= 1;
454    }
455
456    qh = hc->qh_intr_last[0];
457    qh->qh_link = USB_EHCI_LINK_TERMINATE;
458
459    /*
460     * STEP 7.2: Initialize the isochronus split transaction queues together
461     *           with the isochronus transaction queues
462     */
463
464    usb_ehci_sitd_t *sitd;
465    usb_ehci_itd_t *itd;
466
467    for (uint32_t i = 0; i < USB_EHCI_VFRAMELIST_COUNT; i++) {
468
469        sitd = usb_ehci_sitd_alloc();
470        hc->qh_sitd_fs_last[i] = sitd;
471
472        sitd->sitd_self |= USB_EHCI_LINKTYPE_SITD;
473
474        sitd->sitd_back_link = USB_EHCI_LINK_TERMINATE;
475
476        next = i | (USB_EHCI_VFRAMELIST_COUNT / 2);
477        sitd->sitd_next = hc->qh_intr_last[next]->qh_self;
478
479        itd = usb_ehci_itd_alloc();
480        hc->qh_itd_hs_last[i] = itd;
481
482        itd->itd_self |= USB_EHCI_LINKTYPE_ITD;
483
484        itd->itd_next = sitd->sitd_self;
485    }
486
487    /*
488     * STEP 8: Initialize the physical frames for the periodic transfers
489     *         and store the periodic frame list iTDs addresses
490     */
491    if (hc->pframes == NULL) {
492        usb_ehci_pframes_alloc(hc);
493    }
494
495    assert(hc->pframes);
496
497    usb_paddr_t *pframes = (hc->pframes);
498
499    for (uint32_t i = 0; i < USB_EHCI_FRAMELIST_COUNT; i++) {
500        next = i & (USB_EHCI_VFRAMELIST_COUNT - 1);
501        (pframes[i]) = hc->qh_itd_hs_last[next]->itd_self;
502    }
503
504    /*
505     * STEP 9: Initialize the asynchronous transfer queue
506     */
507    qh = usb_ehci_qh_alloc();
508
509    hc->qh_async_last = qh;
510    hc->qh_async_first = qh;
511
512    qh->qh_ep.ep_speed = USB_EHCI_QH_SPEED_HIGH;
513    qh->qh_ep.head_reclamation = 1;
514    qh->qh_ep.mult = 1;
515    qh->qh_link = qh->qh_self | USB_EHCI_LINKTYPE_QH | USB_EHCI_LINK_TERMINATE;
516    qh->qh_alt_next_qtd = USB_EHCI_LINK_TERMINATE;
517    qh->qh_next_qtd = USB_EHCI_LINK_TERMINATE;
518    qh->qh_status.status = USB_EHCI_QTD_STATUS_HALTED;
519
520    /*
521     * STEP 10: Allocate the root hub device
522     */
523    struct usb_device *root_hub = usb_device_alloc(hc->controller, NULL, 0, 0,
524            1, USB_SPEED_HIGH, USB_MODE_HOST);
525
526    if (root_hub) {
527        usb_hub_init(root_hub);
528        hc->rh_device = root_hub;
529        hc->controller->root_hub = root_hub;
530    } else {
531        USER_PANIC("ERROR: No root hub present!");
532    }
533
534    hc->devices[USB_ROOTHUB_ADDRESS] = root_hub;
535
536    /*
537     * STEP 11: Call the register initialization function
538     */
539    err = usb_ehci_initialize_controller(hc);
540
541    /*
542     * STEP 12: do an initial poll, since the interrupts may be risen before
543     *          we started the interrupt handler
544     */
545    if (err == USB_ERR_OK) {
546        usb_ehci_poll(hc);
547    }
548
549    return (err);
550}
551