Changes in uspace/drv/bus/usb/uhci/uhci.c [7de1988c:56fd7cf] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/uhci.c
r7de1988c r56fd7cf 38 38 39 39 #include <errno.h> 40 #include <stdbool.h>41 40 #include <str_error.h> 42 41 #include <ddf/interrupt.h> … … 150 149 int device_setup_uhci(ddf_dev_t *device) 151 150 { 152 bool ih_registered = false;153 bool hc_inited = false;154 bool fun_bound = false;155 int rc;156 157 151 if (!device) 158 152 return EBADMEM; … … 164 158 } 165 159 160 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \ 161 if (ret != EOK) { \ 162 if (instance->hc_fun) \ 163 ddf_fun_destroy(instance->hc_fun); \ 164 if (instance->rh_fun) {\ 165 ddf_fun_destroy(instance->rh_fun); \ 166 } \ 167 usb_log_error(message); \ 168 return ret; \ 169 } else (void)0 170 171 instance->rh_fun = NULL; 166 172 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 int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK; 174 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n"); 173 175 ddf_fun_set_ops(instance->hc_fun, &hc_ops); 174 176 ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic); 175 177 176 178 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 179 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK; 180 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n"); 183 181 ddf_fun_set_ops(instance->rh_fun, &rh_ops); 184 182 ddf_fun_data_implant(instance->rh_fun, &instance->rh); 185 183 186 addr_range_t regs; 184 uintptr_t reg_base = 0; 185 size_t reg_size = 0; 187 186 int irq = 0; 188 187 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; 188 ret = get_my_registers(device, ®_base, ®_size, &irq); 189 CHECK_RET_DEST_FREE_RETURN(ret, 190 "Failed to get I/O addresses for %" PRIun ": %s.\n", 191 ddf_dev_get_handle(device), str_error(ret)); 192 usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n", 193 (void *) reg_base, reg_size, irq); 194 195 ret = disable_legacy(device); 196 CHECK_RET_DEST_FREE_RETURN(ret, 197 "Failed to disable legacy USB: %s.\n", str_error(ret)); 198 199 const size_t ranges_count = hc_irq_pio_range_count(); 200 const size_t cmds_count = hc_irq_cmd_count(); 201 irq_pio_range_t irq_ranges[ranges_count]; 202 irq_cmd_t irq_cmds[cmds_count]; 203 ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 204 sizeof(irq_cmds), reg_base, reg_size); 205 CHECK_RET_DEST_FREE_RETURN(ret, 206 "Failed to generate IRQ commands: %s.\n", str_error(ret)); 207 208 irq_code_t irq_code = { 209 .rangecount = ranges_count, 210 .ranges = irq_ranges, 211 .cmdcount = cmds_count, 212 .cmds = irq_cmds 213 }; 214 215 /* Register handler to avoid interrupt lockup */ 216 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code); 217 CHECK_RET_DEST_FREE_RETURN(ret, 218 "Failed to register interrupt handler: %s.\n", str_error(ret)); 213 219 214 220 bool interrupts = false; 215 r c= enable_interrupts(device);216 if (r c!= EOK) {221 ret = enable_interrupts(device); 222 if (ret != EOK) { 217 223 usb_log_warning("Failed to enable interrupts: %s." 218 " Falling back to polling.\n", str_error(r c));224 " Falling back to polling.\n", str_error(ret)); 219 225 } else { 220 226 usb_log_debug("Hw interrupts enabled.\n"); … … 222 228 } 223 229 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, 230 ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts); 231 CHECK_RET_DEST_FREE_RETURN(ret, 232 "Failed to init uhci_hcd: %s.\n", str_error(ret)); 233 234 #define CHECK_RET_FINI_RETURN(ret, message...) \ 235 if (ret != EOK) { \ 236 hc_fini(&instance->hc); \ 237 CHECK_RET_DEST_FREE_RETURN(ret, message); \ 238 return ret; \ 239 } else (void)0 240 241 ret = ddf_fun_bind(instance->hc_fun); 242 CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n", 243 str_error(ret)); 244 245 ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 246 CHECK_RET_FINI_RETURN(ret, 247 "Failed to add UHCI to HC class: %s.\n", str_error(ret)); 248 249 ret = rh_init(&instance->rh, instance->rh_fun, 249 250 (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; 261 } 251 CHECK_RET_FINI_RETURN(ret, 252 "Failed to setup UHCI root hub: %s.\n", str_error(ret)); 253 254 ret = ddf_fun_bind(instance->rh_fun); 255 CHECK_RET_FINI_RETURN(ret, 256 "Failed to register UHCI root hub: %s.\n", str_error(ret)); 262 257 263 258 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; 259 #undef CHECK_RET_FINI_RETURN 278 260 } 279 261 /**
Note:
See TracChangeset
for help on using the changeset viewer.