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, Universitaetstrasse 6, 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 "ohci_device.h"
16
17#include <usb/usb.h>
18#include <usb/usb_error.h>
19
20#include <usb_controller.h>
21#include "usb_ohci.h"
22#include "usb_ohci_memory.h"
23#include "usb_ohci_bus.h"
24#include "usb_ohci_root_hub.h"
25
26/*
27 * our mackerel base
28 */
29static struct ohci_t ohci_base;
30
31static struct usb_ohci_ed *usb_ohci_init_ed(struct usb_ohci_ed **list)
32{
33    struct usb_ohci_ed *ed =  usb_ohci_ed_alloc();
34    if (ed == NULL) {
35        return NULL;
36    }
37    ed->ed_control.skip=1;
38
39    if (list != NULL) {
40        *list = ed;
41    }
42    return ed;
43}
44
45/**
46 * \brief   initializes the host controller hardware
47 *
48 * \param   hc      the host controller
49 * \param   suspend flag the host controller should be suspended
50 */
51static usb_error_t usb_ohci_init_controller(usb_ohci_hc_t *hc, uint8_t suspend)
52{
53    USB_DEBUG("usb_ohci_init_controller()\n");
54
55    char status[512];
56    ohci_control_pr(status, 512, hc->ohci_base);
57    puts(status);
58
59    /*
60     * check the ownership of the host controller
61     */
62    if (ohci_control_ir_rdf(hc->ohci_base)) {
63        assert(!"REQEUST OWER CHANGE. ");
64    }
65
66    // reset the device
67    ohci_control_hcfs_wrf(hc->ohci_base, 0);
68
69    /*
70     * TODO: Wait till reset is done
71     */
72    for(uint32_t i = 0; i < 2000000000; i++);
73
74    USB_DEBUG("usb_ohci_init_controller(): Device Reset done.\n");
75
76
77    ohci_fm_interval_t ival = ohci_fm_interval_rd(hc->ohci_base);
78
79    ohci_cmdstatus_hcr_wrf(hc->ohci_base, 1);
80
81    for (uint16_t i = 0; i < 10; i++) {
82        /*
83         * TODO: Wait 10 us
84         */
85        for(uint32_t j = 0; j < 2000000000; j++);
86
87        if (!ohci_cmdstatus_hcr_rdf(hc->ohci_base)) {
88            break;
89        }
90    }
91    if (ohci_cmdstatus_hcr_rdf(hc->ohci_base)) {
92        debug_printf("OHCI host controller reset timeout.");
93        return USB_ERR_IOERROR;
94    }
95
96    if (suspend) {
97        ohci_control_hcfs_wrf(hc->ohci_base, 3);
98        return USB_ERR_OK;
99    }
100
101    /*
102     * Setting up register values
103     */
104    // HCCA pointer
105    ohci_hcca_wr(hc->ohci_base, usb_ohci_hcca_physaddr());
106
107    // Control ED head pointer
108    ohci_ctrl_head_wr(hc->ohci_base, hc->qh_ctrl_first->ed_self);
109
110    // Bulk ED head pointer
111    ohci_bulk_head_wr(hc->ohci_base, hc->qh_bulk_first->ed_self);
112
113    USB_DEBUG("usb_ohci_init() - reset and enable interrupts\n");
114    // reset the interrupts
115    ohci_intdisable_rawwr(hc->ohci_base, 0x0);
116    ohci_interrupt_t enabled_intrs = ohci_intenable_rd(hc->ohci_base);
117    enabled_intrs= ohci_interrupt_mie_insert(enabled_intrs, 1);
118    enabled_intrs= ohci_interrupt_wdh_insert(enabled_intrs, 1);
119    enabled_intrs= ohci_interrupt_rd_insert(enabled_intrs, 1);
120    enabled_intrs= ohci_interrupt_ue_insert(enabled_intrs, 1);
121    enabled_intrs= ohci_interrupt_oc_insert(enabled_intrs, 1);
122    enabled_intrs= ohci_interrupt_rhsc_insert(enabled_intrs, 1);
123    ohci_intenable_wr(hc->ohci_base, enabled_intrs);
124
125    hc->enabled_intrs = enabled_intrs;
126
127    // setting the desired features
128    ohci_control_t ctrl = ohci_control_rd(hc->ohci_base);
129    ctrl = ohci_control_ie_insert(ctrl, 1);
130    ctrl = ohci_control_ir_insert(ctrl,0);
131    ctrl = ohci_control_cle_insert(ctrl, 1);
132    ctrl = ohci_control_ble_insert(ctrl, 1);
133    ctrl = ohci_control_cbsr_insert(ctrl, 3);
134    ctrl = ohci_control_hcfs_insert(ctrl, 2);
135    ctrl = ohci_control_pe_insert(ctrl, 1);
136    ctrl = ohci_control_rwe_insert(ctrl, 1);
137    ctrl = ohci_control_rwc_insert(ctrl, 1);
138    ohci_control_wr(hc->ohci_base, ctrl);
139
140    /*
141     * the controller is now OPERATIONAL and running.
142     */
143    debug_printf("OHCI host controller operational now!\n");
144    // setting some remaining registers
145    ival = ohci_fm_interval_fit_insert(ival, 0);
146    ival = ohci_fm_interval_fsmps_insert(ival, (ival-210)*6/7);
147    ohci_fm_interval_wr(hc->ohci_base, ival);
148    ohci_period_start_wr(hc->ohci_base, (ival)*9/10);
149
150    // setting some root hub fields
151    ohci_rh_descra_nocp_wrf(hc->ohci_base, 1);
152    ohci_rh_status_lpsc_wrf(hc->ohci_base, 1);
153
154    /*
155     * getting the port numbers
156     */
157    hc->root_hub_num_ports = 0;
158    for (uint8_t i = 0; (i < 10) && (hc->root_hub_num_ports == 0); i++) {
159        /*
160         * TODO: delay
161         */
162        for(uint32_t j = 0; j < 100000000; j++);
163        hc->root_hub_num_ports = ohci_rh_descra_ndp_rdf(hc->ohci_base);
164    }
165    debug_printf("OHCI CONTROLLER INTIALIZED. Having %"PRIu8" ports\n",
166            hc->root_hub_num_ports );
167
168    //char buf[8001];
169    // ohci_rh_descra_pr(buf, 15999, hc->ohci_base);
170    //    printf(buf);
171    //ohci_pr(buf, 5000, hc->ohci_base);
172    //printf(buf);
173
174    //ohci_cmdstatus_ocr_wrf(hc->ohci_base, 0x1);
175    usb_ohci_root_hub_interrupt(hc);
176
177    return USB_ERR_OK;
178}
179
180/*
181 * ------------------------------------------------------------------------
182 * Exported Functions
183 * ------------------------------------------------------------------------
184 */
185
186
187
188/**
189 * \brief   initializes the OHCI controller hardware
190 */
191usb_error_t usb_ohci_init(usb_ohci_hc_t *hc, uintptr_t base)
192{
193    /*
194     * initialize the mackerel framework
195     */
196// TODO: Why does 32-bit expect mackerel_io_t?
197#ifdef __x86__
198    ohci_initialize(&ohci_base, (mackerel_io_t)base);
199#else
200    ohci_initialize(&ohci_base, (mackerel_addr_t)base);
201#endif
202    hc->ohci_base = &ohci_base;
203
204    /*
205     * setup the endpoint descriptors
206     */
207    hc->qh_bulk_last = usb_ohci_init_ed(&hc->qh_bulk_first);
208    hc->qh_ctrl_last = usb_ohci_init_ed(&hc->qh_ctrl_first);
209    hc->qh_isoc_last = usb_ohci_init_ed(NULL);
210
211    for (uint16_t i = 0; i<USB_OHCI_NO_EP_DESCRIPTORS; i++) {
212        hc->qh_intr_last[i] = usb_ohci_init_ed(NULL);
213    }
214
215    /**
216     * setup the interrupt transfer type tree
217     */
218    uint16_t bit = USB_OHCI_NO_EP_DESCRIPTORS / 2;
219    uint16_t current;
220    uint16_t next;
221    while (bit) {
222        current = bit;
223        while (current & bit) {
224            next = (current ^ bit) | (bit / 2);
225
226            usb_ohci_ed_t *ed_current = hc->qh_intr_last[current];
227            usb_ohci_ed_t *ed_next = hc->qh_intr_last[next];
228            ed_current->next = NULL;
229            ed_current->ed_nextED = ed_next->ed_self;
230
231            current++;
232        }
233        bit >>= 1;
234    }
235
236    /*
237     * after the last interrupt endpoint the isochronus follows
238     */
239    usb_ohci_ed_t *intr_ed = hc->qh_intr_last[0];
240    intr_ed->next = hc->qh_isoc_last;
241    intr_ed->ed_nextED = hc->qh_isoc_last->ed_self;
242    /*
243     * allocate and initiate the HCCA memory region
244     */
245    hc->hcca = usb_ohci_hcca_alloc();
246
247    for (uint16_t i = 0; i < USB_OHCI_NO_IRQS; i++) {
248        hc->hcca->hcca_interrupt_table[i] = hc->qh_intr_last[i
249                | USB_OHCI_NO_EP_DESCRIPTORS / 2]->ed_self;
250    }
251
252    hc->controller->hcdi_bus_fn = usb_ohci_get_bus_fn();
253    hc->controller->usb_revision = USB_REV_1_0;
254
255
256    /*
257     * initialize the hardware
258     */
259    if (usb_ohci_init_controller(hc, 0) != USB_ERR_OK) {
260        return USB_ERR_INVAL;
261    }
262
263    USB_DEBUG("usb_ohci_init() - calling usb_ohci_do_poll\n");
264    //usb_ohci_do_poll(hc->controller);
265
266    return USB_ERR_OK;
267
268}
269
270/**
271 * \brief   this function shuts down the controller
272 *
273 *
274 */
275void usb_ohci_detach(usb_ohci_hc_t *hc)
276{
277    ohci_intdisable_wr(hc->ohci_base, 0xFFFFFFFF);
278    ohci_control_hcfs_wrf(hc->ohci_base, 0);
279}
280
281/**
282 * \brief   the interrupt handler for this host controller
283 */
284void usb_ohci_interrupt(usb_ohci_hc_t *hc)
285{
286    struct usb_ohci_hcca *hcca = hc->hcca;
287    ohci_interrupt_t status = 0;
288    usb_paddr_t done = hcca->hcca_done_head;
289
290    /*
291     * check if we have some completed transfers
292     */
293    if (!done) {
294        status = 0;
295        /*
296         * we have other interrupts at the time hcca done head
297         * was written. read status register
298         */
299        if (USB_OHCI_HCCA_UNMASKED_IRQ(hcca)) {
300            status = ohci_intstatus_rd(hc->ohci_base);
301        }
302        /*
303         * we have just the WriteDoneHead interrupt
304         */
305        if ((hcca - USB_OHCI_HCCA_UNMASKED_IRQ(hcca))) {
306            status = ohci_interrupt_wdh_insert(status, 1);
307        }
308    } else {
309        /*
310         * the done head has not been written, so read the interrupt status
311         * and clear the WriteDoneHead
312         */
313        status = ohci_intstatus_rd(hc->ohci_base);
314        status = ohci_interrupt_wdh_insert(status, 0);
315    }
316
317    /*
318     * Master Interrupt Enable bit is always set on, so clear it
319     */
320    status = ohci_interrupt_mie_insert(status, 0);
321
322    if (status == 0) {
323        /*
324         * there are no interrupts to process, just return
325         */
326        return;
327    }
328
329    // acknowledge the interrupts
330    ohci_intstatus_wr(hc->ohci_base, status);
331
332    // get the enabled interrupts and clear the others
333    status &= hc->enabled_intrs;
334
335    if (status == 0) {
336        /*
337         * there are no interrupts to be enabled, so
338         * nothing to do left
339         */
340        return;
341    }
342
343    /*
344     * ScheduleOverrun Interrupt
345     *
346     * This bit is set when the USB schedule for the current Frame
347     * overruns and after the update of HccaFrameNumber. A scheduling
348     * overrun will also cause the SchedulingOverrunCount of HcCommandStatus
349     * to be incremented.
350     */
351    if (ohci_interrupt_so_extract(status)) {
352        debug_printf("ScheduleOverrun interrupt...\n");
353    }
354
355    /*
356     * ResumeDetected
357     * This bit is set when HC detects that a device on the USB is
358     * asserting resume signaling. It is the transition from no resume
359     * signaling to resume signaling causing this bit to be set. This bit
360     * is not set when HCD sets the USBRESUME state
361     */
362    if (ohci_interrupt_rd_extract(status)) {
363        debug_printf("ResumeDetected interrupt...\n");
364        }
365
366    /*
367     * UnrecoverableError
368     * This bit is set when HC detects a system error not related to
369     * USB. HC should not proceed with any processing nor signaling
370     * before the system error has been corrected. HCD clears this bit
371     * after HC has been reset.
372     */
373    if (ohci_interrupt_ue_extract(status)) {
374        debug_printf("UnrecoverableError interrupt...\n");
375
376        }
377
378    /*
379     * RootHubStatusChange
380     *
381     * This bit is set when the content of HcRhStatus or the content of
382     * any of HcRhPortStatus[NumberofDownstreamPort] has changed.
383     */
384    if (ohci_interrupt_rhsc_extract(status)) {
385        debug_printf("RootHubStatusChange interrupt...\n");
386
387        hc->enabled_intrs = ohci_interrupt_rhsc_insert(hc->enabled_intrs, 0);
388        ohci_intdisable_rhsc_wrf(hc->ohci_base, 1);
389
390        usb_ohci_root_hub_interrupt(hc);
391        }
392
393    status = ohci_interrupt_rhsc_insert(status, 0);
394    status = ohci_interrupt_wdh_insert(status, 0);
395    status = ohci_interrupt_so_insert(status, 0);
396
397    if (status) {
398        ohci_intdisable_wr(hc->ohci_base, status);
399        hc->enabled_intrs &= ~status;
400    }
401
402    usb_ohci_do_poll(hc->controller);
403}
404