Changes in uspace/drv/bus/usb/uhci/uhci.c [5b89d43b:56fd7cf] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/uhci.c
r5b89d43b r56fd7cf 38 38 39 39 #include <errno.h> 40 #include <stdbool.h>41 40 #include <str_error.h> 42 41 #include <ddf/interrupt.h> … … 132 131 }; 133 132 134 static pio_window_t *get_pio_window(ddf_fun_t *fun)135 {136 rh_t *rh = ddf_fun_data_get(fun);137 138 if (rh == NULL)139 return NULL;140 return &rh->pio_window;141 }142 143 static pio_window_ops_t pio_window_iface = {144 .get_pio_window = get_pio_window145 };146 147 133 /** RH function support for uhci_rhd */ 148 134 static ddf_dev_ops_t rh_ops = { 149 135 .interfaces[USB_DEV_IFACE] = &usb_iface, 150 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface, 151 .interfaces[PIO_WINDOW_DEV_IFACE] = &pio_window_iface 136 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface 152 137 }; 153 138 … … 164 149 int device_setup_uhci(ddf_dev_t *device) 165 150 { 166 bool ih_registered = false;167 bool hc_inited = false;168 bool fun_bound = false;169 int rc;170 171 151 if (!device) 172 152 return EBADMEM; … … 178 158 } 179 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; 180 172 instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc"); 181 if (instance->hc_fun == NULL) { 182 usb_log_error("Failed to create UHCI HC function.\n"); 183 rc = ENOMEM; 184 goto error; 185 } 186 173 int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK; 174 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n"); 187 175 ddf_fun_set_ops(instance->hc_fun, &hc_ops); 188 176 ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic); 189 177 190 178 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_rh"); 191 if (instance->rh_fun == NULL) { 192 usb_log_error("Failed to create UHCI RH function.\n"); 193 rc = ENOMEM; 194 goto error; 195 } 196 179 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK; 180 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n"); 197 181 ddf_fun_set_ops(instance->rh_fun, &rh_ops); 198 182 ddf_fun_data_implant(instance->rh_fun, &instance->rh); 199 183 200 addr_range_t regs; 184 uintptr_t reg_base = 0; 185 size_t reg_size = 0; 201 186 int irq = 0; 202 187 203 rc = get_my_registers(device, ®s, &irq); 204 if (rc != EOK) { 205 usb_log_error("Failed to get I/O addresses for %" PRIun ": %s.\n", 206 ddf_dev_get_handle(device), str_error(rc)); 207 goto error; 208 } 209 usb_log_debug("I/O regs at %p (size %zu), IRQ %d.\n", 210 RNGABSPTR(regs), RNGSZ(regs), irq); 211 212 rc = disable_legacy(device); 213 if (rc != EOK) { 214 usb_log_error("Failed to disable legacy USB: %s.\n", 215 str_error(rc)); 216 goto error; 217 } 218 219 rc = hc_register_irq_handler(device, ®s, irq, irq_handler); 220 if (rc != EOK) { 221 usb_log_error("Failed to register interrupt handler: %s.\n", 222 str_error(rc)); 223 goto error; 224 } 225 226 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)); 227 219 228 220 bool interrupts = false; 229 r c= enable_interrupts(device);230 if (r c!= EOK) {221 ret = enable_interrupts(device); 222 if (ret != EOK) { 231 223 usb_log_warning("Failed to enable interrupts: %s." 232 " Falling back to polling.\n", str_error(r c));224 " Falling back to polling.\n", str_error(ret)); 233 225 } else { 234 226 usb_log_debug("Hw interrupts enabled.\n"); … … 236 228 } 237 229 238 rc = hc_init(&instance->hc, ®s, interrupts); 239 if (rc != EOK) { 240 usb_log_error("Failed to init uhci_hcd: %s.\n", str_error(rc)); 241 goto error; 242 } 243 244 hc_inited = true; 245 246 rc = ddf_fun_bind(instance->hc_fun); 247 if (rc != EOK) { 248 usb_log_error("Failed to bind UHCI device function: %s.\n", 249 str_error(rc)); 250 goto error; 251 } 252 253 fun_bound = true; 254 255 rc = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 256 if (rc != EOK) { 257 usb_log_error("Failed to add UHCI to HC class: %s.\n", 258 str_error(rc)); 259 goto error; 260 } 261 262 rc = rh_init(&instance->rh, instance->rh_fun, ®s, 0x10, 4); 263 if (rc != EOK) { 264 usb_log_error("Failed to setup UHCI root hub: %s.\n", 265 str_error(rc)); 266 goto error; 267 } 268 269 rc = ddf_fun_bind(instance->rh_fun); 270 if (rc != EOK) { 271 usb_log_error("Failed to register UHCI root hub: %s.\n", 272 str_error(rc)); 273 goto error; 274 } 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, 250 (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)); 275 257 276 258 return EOK; 277 278 error: 279 if (fun_bound) 280 ddf_fun_unbind(instance->hc_fun); 281 if (hc_inited) 282 hc_fini(&instance->hc); 283 if (ih_registered) 284 unregister_interrupt_handler(device, irq); 285 if (instance->hc_fun != NULL) 286 ddf_fun_destroy(instance->hc_fun); 287 if (instance->rh_fun != NULL) { 288 ddf_fun_destroy(instance->rh_fun); 289 } 290 return rc; 259 #undef CHECK_RET_FINI_RETURN 291 260 } 292 261 /**
Note:
See TracChangeset
for help on using the changeset viewer.