Changes in uspace/drv/bus/usb/uhci/uhci.c [e991937:7de1988c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/uhci.c
re991937 r7de1988c 34 34 */ 35 35 36 /* XXX Fix this */ 37 #define _DDF_DATA_IMPLANT 38 36 39 #include <errno.h> 40 #include <stdbool.h> 37 41 #include <str_error.h> 38 42 #include <ddf/interrupt.h> 43 #include <usb_iface.h> 44 #include <usb/ddfiface.h> 39 45 #include <usb/debug.h> 40 #include <usb/host/hcd.h>41 #include <usb/host/ddf_helpers.h>42 46 43 47 #include "uhci.h" … … 45 49 #include "res.h" 46 50 #include "hc.h" 47 51 #include "root_hub.h" 52 53 /** Structure representing both functions of UHCI hc, USB host controller 54 * and USB root hub */ 55 typedef struct uhci { 56 /** Pointer to DDF representation of UHCI host controller */ 57 ddf_fun_t *hc_fun; 58 /** Pointer to DDF representation of UHCI root hub */ 59 ddf_fun_t *rh_fun; 60 61 /** Internal driver's representation of UHCI host controller */ 62 hc_t hc; 63 /** Internal driver's representation of UHCI root hub */ 64 rh_t rh; 65 } uhci_t; 66 67 static inline uhci_t *dev_to_uhci(ddf_dev_t *dev) 68 { 69 return ddf_dev_data_get(dev); 70 } 48 71 49 72 /** IRQ handling callback, forward status from call to diver structure. … … 56 79 { 57 80 assert(dev); 58 hcd_t *hcd = dev_to_hcd(dev);59 if (! hcd || !hcd->private_data) {81 uhci_t *uhci = dev_to_uhci(dev); 82 if (!uhci) { 60 83 usb_log_error("Interrupt on not yet initialized device.\n"); 61 84 return; 62 85 } 63 86 const uint16_t status = IPC_GET_ARG1(*call); 64 hc_interrupt(hcd->private_data, status); 65 } 87 hc_interrupt(&uhci->hc, status); 88 } 89 90 /** Operations supported by the HC driver */ 91 static ddf_dev_ops_t hc_ops = { 92 .interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */ 93 }; 94 95 /** Gets handle of the respective hc. 96 * 97 * @param[in] fun DDF function of uhci device. 98 * @param[out] handle Host cotnroller handle. 99 * @return Error code. 100 */ 101 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) 102 { 103 ddf_fun_t *hc_fun = dev_to_uhci(ddf_fun_get_dev(fun))->hc_fun; 104 assert(hc_fun); 105 106 if (handle != NULL) 107 *handle = ddf_fun_get_handle(hc_fun); 108 return EOK; 109 } 110 111 /** USB interface implementation used by RH */ 112 static usb_iface_t usb_iface = { 113 .get_hc_handle = usb_iface_get_hc_handle, 114 }; 115 116 /** Get root hub hw resources (I/O registers). 117 * 118 * @param[in] fun Root hub function. 119 * @return Pointer to the resource list used by the root hub. 120 */ 121 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun) 122 { 123 rh_t *rh = ddf_fun_data_get(fun); 124 assert(rh); 125 return &rh->resource_list; 126 } 127 128 /** Interface to provide the root hub driver with hw info */ 129 static hw_res_ops_t hw_res_iface = { 130 .get_resource_list = get_resource_list, 131 .enable_interrupt = NULL, 132 }; 133 134 /** RH function support for uhci_rhd */ 135 static ddf_dev_ops_t rh_ops = { 136 .interfaces[USB_DEV_IFACE] = &usb_iface, 137 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface 138 }; 66 139 67 140 /** Initialize hc and rh DDF structures and their respective drivers. … … 77 150 int device_setup_uhci(ddf_dev_t *device) 78 151 { 152 bool ih_registered = false; 153 bool hc_inited = false; 154 bool fun_bound = false; 155 int rc; 156 79 157 if (!device) 80 158 return EBADMEM; 81 159 82 #define CHECK_RET_RETURN(ret, message...) \ 83 if (ret != EOK) { \ 84 usb_log_error(message); \ 85 return ret; \ 86 } else (void)0 87 88 uintptr_t reg_base = 0; 89 size_t reg_size = 0; 160 uhci_t *instance = ddf_dev_data_alloc(device, sizeof(uhci_t)); 161 if (instance == NULL) { 162 usb_log_error("Failed to allocate OHCI driver.\n"); 163 return ENOMEM; 164 } 165 166 instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc"); 167 if (instance->hc_fun == NULL) { 168 usb_log_error("Failed to create UHCI HC function.\n"); 169 rc = ENOMEM; 170 goto error; 171 } 172 173 ddf_fun_set_ops(instance->hc_fun, &hc_ops); 174 ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic); 175 176 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh"); 177 if (instance->rh_fun == NULL) { 178 usb_log_error("Failed to create UHCI RH function.\n"); 179 rc = ENOMEM; 180 goto error; 181 } 182 183 ddf_fun_set_ops(instance->rh_fun, &rh_ops); 184 ddf_fun_data_implant(instance->rh_fun, &instance->rh); 185 186 addr_range_t regs; 90 187 int irq = 0; 91 188 92 int ret = get_my_registers(device, ®_base, ®_size, &irq); 93 CHECK_RET_RETURN(ret, "Failed to get I/O region for %" PRIun ": %s.\n", 94 ddf_dev_get_handle(device), str_error(ret)); 95 usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n", 96 (void *) reg_base, reg_size, irq); 97 98 const size_t ranges_count = hc_irq_pio_range_count(); 99 const size_t cmds_count = hc_irq_cmd_count(); 100 irq_pio_range_t irq_ranges[ranges_count]; 101 irq_cmd_t irq_cmds[cmds_count]; 102 ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 103 sizeof(irq_cmds), reg_base, reg_size); 104 CHECK_RET_RETURN(ret, "Failed to generate IRQ commands: %s.\n", 105 str_error(ret)); 106 107 irq_code_t irq_code = { 108 .rangecount = ranges_count, 109 .ranges = irq_ranges, 110 .cmdcount = cmds_count, 111 .cmds = irq_cmds 112 }; 113 114 /* Register handler to avoid interrupt lockup */ 115 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code); 116 CHECK_RET_RETURN(ret, "Failed to register interrupt handler: %s.\n", 117 str_error(ret)); 118 119 ret = disable_legacy(device); 120 CHECK_RET_RETURN(ret, "Failed to disable legacy USB: %s.\n", 121 str_error(ret)); 189 rc = get_my_registers(device, ®s, &irq); 190 if (rc != EOK) { 191 usb_log_error("Failed to get I/O addresses for %" PRIun ": %s.\n", 192 ddf_dev_get_handle(device), str_error(rc)); 193 goto error; 194 } 195 usb_log_debug("I/O regs at %p (size %zu), IRQ %d.\n", 196 RNGABSPTR(regs), RNGSZ(regs), irq); 197 198 rc = disable_legacy(device); 199 if (rc != EOK) { 200 usb_log_error("Failed to disable legacy USB: %s.\n", 201 str_error(rc)); 202 goto error; 203 } 204 205 rc = hc_register_irq_handler(device, ®s, irq, irq_handler); 206 if (rc != EOK) { 207 usb_log_error("Failed to register interrupt handler: %s.\n", 208 str_error(rc)); 209 goto error; 210 } 211 212 ih_registered = true; 122 213 123 214 bool interrupts = false; 124 r et= enable_interrupts(device);125 if (r et!= EOK) {215 rc = enable_interrupts(device); 216 if (rc != EOK) { 126 217 usb_log_warning("Failed to enable interrupts: %s." 127 " Falling back to polling.\n", str_error(r et));218 " Falling back to polling.\n", str_error(rc)); 128 219 } else { 129 220 usb_log_debug("Hw interrupts enabled.\n"); … … 131 222 } 132 223 133 ret = hcd_ddf_setup_hc(device, USB_SPEED_FULL, 134 BANDWIDTH_AVAILABLE_USB11, bandwidth_count_usb11); 135 CHECK_RET_RETURN(ret, "Failed to setup UHCI HCD.\n"); 136 137 hc_t *hc = malloc(sizeof(hc_t)); 138 ret = hc ? EOK : ENOMEM; 139 CHECK_RET_RETURN(ret, "Failed to allocate UHCI HC structure.\n"); 140 141 ret = hc_init(hc, (void*)reg_base, reg_size, interrupts); 142 CHECK_RET_RETURN(ret, 143 "Failed to init uhci_hcd: %s.\n", str_error(ret)); 144 145 hcd_set_implementation(dev_to_hcd(device), hc, hc_schedule, NULL, NULL); 146 147 /* 148 * Creating root hub registers a new USB device so HC 149 * needs to be ready at this time. 150 */ 151 ret = hcd_ddf_setup_root_hub(device); 152 if (ret != EOK) { 153 // TODO: Undo hcd_setup_device 154 hc_fini(hc); 155 CHECK_RET_RETURN(ret, "Failed to setup UHCI root hub: %s.\n", 156 str_error(ret)); 157 return ret; 224 rc = hc_init(&instance->hc, ®s, interrupts); 225 if (rc != EOK) { 226 usb_log_error("Failed to init uhci_hcd: %s.\n", str_error(rc)); 227 goto error; 228 } 229 230 hc_inited = true; 231 232 rc = ddf_fun_bind(instance->hc_fun); 233 if (rc != EOK) { 234 usb_log_error("Failed to bind UHCI device function: %s.\n", 235 str_error(rc)); 236 goto error; 237 } 238 239 fun_bound = true; 240 241 rc = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 242 if (rc != EOK) { 243 usb_log_error("Failed to add UHCI to HC class: %s.\n", 244 str_error(rc)); 245 goto error; 246 } 247 248 rc = rh_init(&instance->rh, instance->rh_fun, 249 (uintptr_t)instance->hc.registers + 0x10, 4); 250 if (rc != EOK) { 251 usb_log_error("Failed to setup UHCI root hub: %s.\n", 252 str_error(rc)); 253 goto error; 254 } 255 256 rc = ddf_fun_bind(instance->rh_fun); 257 if (rc != EOK) { 258 usb_log_error("Failed to register UHCI root hub: %s.\n", 259 str_error(rc)); 260 goto error; 158 261 } 159 262 160 263 return EOK; 264 265 error: 266 if (fun_bound) 267 ddf_fun_unbind(instance->hc_fun); 268 if (hc_inited) 269 hc_fini(&instance->hc); 270 if (ih_registered) 271 unregister_interrupt_handler(device, irq); 272 if (instance->hc_fun != NULL) 273 ddf_fun_destroy(instance->hc_fun); 274 if (instance->rh_fun != NULL) { 275 ddf_fun_destroy(instance->rh_fun); 276 } 277 return rc; 161 278 } 162 279 /**
Note:
See TracChangeset
for help on using the changeset viewer.