Changes in uspace/drv/bus/usb/uhci/uhci.c [56fd7cf:7de1988c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/uhci.c
r56fd7cf r7de1988c 38 38 39 39 #include <errno.h> 40 #include <stdbool.h> 40 41 #include <str_error.h> 41 42 #include <ddf/interrupt.h> … … 149 150 int device_setup_uhci(ddf_dev_t *device) 150 151 { 152 bool ih_registered = false; 153 bool hc_inited = false; 154 bool fun_bound = false; 155 int rc; 156 151 157 if (!device) 152 158 return EBADMEM; … … 158 164 } 159 165 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)0170 171 instance->rh_fun = NULL;172 166 instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc"); 173 int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK; 174 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n"); 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 175 173 ddf_fun_set_ops(instance->hc_fun, &hc_ops); 176 174 ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic); 177 175 178 176 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh"); 179 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK; 180 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n"); 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 181 183 ddf_fun_set_ops(instance->rh_fun, &rh_ops); 182 184 ddf_fun_data_implant(instance->rh_fun, &instance->rh); 183 185 184 uintptr_t reg_base = 0; 185 size_t reg_size = 0; 186 addr_range_t regs; 186 187 int irq = 0; 187 188 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)); 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; 219 213 220 214 bool interrupts = false; 221 r et= enable_interrupts(device);222 if (r et!= EOK) {215 rc = enable_interrupts(device); 216 if (rc != EOK) { 223 217 usb_log_warning("Failed to enable interrupts: %s." 224 " Falling back to polling.\n", str_error(r et));218 " Falling back to polling.\n", str_error(rc)); 225 219 } else { 226 220 usb_log_debug("Hw interrupts enabled.\n"); … … 228 222 } 229 223 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, 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, 250 249 (uintptr_t)instance->hc.registers + 0x10, 4); 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)); 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 } 257 262 258 263 return EOK; 259 #undef CHECK_RET_FINI_RETURN 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; 260 278 } 261 279 /**
Note:
See TracChangeset
for help on using the changeset viewer.