1/** 2 * \brief this file contains the initialization code for the generic 3 * host controller 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 19#include <barrelfish/barrelfish.h> 20 21#include <usb/usb.h> 22 23#include <usb_controller.h> 24#include <usb_device.h> 25 26#include "controller/ohci/usb_ohci.h" 27#include "controller/uhci/usb_uhci.h" 28#include "controller/ehci/usb_ehci.h" 29#include "controller/xhci/usb_xhci.h" 30 31/// list of currently available host controllers 32static usb_host_controller_t *host_controllers = NULL; 33 34/** 35 * \brief initializes the USB host controller 36 * 37 * \param hc pointer ot the generic host controller 38 * \param version the version [{O, U, E, X}HCI] 39 * \param controller_base the base address of the controller 40 */ 41usb_error_t usb_hc_init(usb_host_controller_t *hc, usb_hc_version_t version, 42 uintptr_t controller_base) 43{ 44 if (hc == NULL) { 45 return (USB_ERR_NOMEM); 46 } 47 48 /* initialize the done queue and the interrupt queue of the host controller*/ 49 hc->done_queue.head.first = NULL; 50 hc->done_queue.head.last_next = &(hc->done_queue.head.first); 51 52 hc->intr_queue.head.first = NULL; 53 hc->intr_queue.head.last_next = &(hc->intr_queue.head.first); 54 55 usb_error_t err = USB_ERR_INVAL; 56 void *controller; 57 58 /* initalize the specific host controller */ 59 switch (version) { 60 case USB_UHCI: 61 USER_PANIC("UHCI controller currently not supported\n"); 62 break; 63 case USB_OHCI: 64 /* XXX: some functionality is implemented, but not tested... */ 65 controller = malloc(sizeof(usb_ohci_hc_t)); 66 if (controller == NULL) { 67 return (USB_ERR_NOMEM); 68 } 69 memset(controller, 0, sizeof(usb_ohci_hc_t)); 70 hc->hc_type = USB_OHCI; 71 hc->hc_control = controller; 72 ((usb_ohci_hc_t*) controller)->controller = hc; 73 err = usb_ohci_init((usb_ohci_hc_t*) controller, 74 (uintptr_t) controller_base); 75 break; 76 case USB_EHCI: 77 /* allocate the ehci controller */ 78 controller = malloc(sizeof(usb_ehci_hc_t)); 79 80 if (controller == NULL) { 81 return (USB_ERR_NOMEM); 82 } 83 memset(controller, 0, sizeof(usb_ehci_hc_t)); 84 85 /* associate it with the generic host controller */ 86 hc->hc_type = USB_EHCI; 87 hc->hc_control = controller; 88 ((usb_ehci_hc_t*) controller)->controller = hc; 89 90 /* set the interrupt handler function */ 91 hc->handle_intr = usb_ehci_interrupt; 92 93 /* initalize the controller */ 94 err = usb_ehci_init((usb_ehci_hc_t*) controller, controller_base); 95 break; 96 case USB_XHCI: 97 USER_PANIC("XHCI controller currently not supported\n"); 98 break; 99 default: 100 return (USB_ERR_INVAL); 101 break; 102 103 } 104 105 /* on success: link the new controller into the host controller list */ 106 if (err == USB_ERR_OK) { 107 if (host_controllers == NULL) { 108 hc->next = NULL; 109 hc->prev_next = NULL; 110 host_controllers = hc; 111 } else { 112 hc->next = host_controllers; 113 host_controllers->prev_next = &(hc->next); 114 host_controllers = hc; 115 } 116 hc->initialized = 1; 117 118 return (USB_ERR_OK); 119 } 120 121 return (err); 122 123} 124 125/** 126 * \brief interrupt handler function for host controller interrupts 127 * 128 * \param arg currently null 129 * 130 * This function is called on every interrupt. The interrupt is then forwared 131 * to the specific interrupt handler functions of the respective HCs 132 */ 133void usb_hc_intr_handler(void *arg) 134{ 135 usb_host_controller_t *hc = host_controllers; 136 137 while (hc != NULL) { 138 if (hc->handle_intr != NULL) { 139 (hc->handle_intr)(hc); 140 } 141 hc = hc->next; 142 } 143} 144