Changes in uspace/drv/bus/usb/uhci/uhci.c [c53007f:795448f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/uhci.c
rc53007f r795448f 33 33 * @brief UHCI driver 34 34 */ 35 36 /* XXX Fix this */37 #define _DDF_DATA_IMPLANT38 39 35 #include <errno.h> 40 #include <stdbool.h>41 36 #include <str_error.h> 42 37 #include <ddf/interrupt.h> … … 65 60 } uhci_t; 66 61 67 static inline uhci_t *dev_to_uhci(ddf_dev_t *dev) 68 { 69 return ddf_dev_data_get(dev); 70 } 71 62 static inline uhci_t * dev_to_uhci(const ddf_dev_t *dev) 63 { 64 assert(dev); 65 return dev->driver_data; 66 } 67 /*----------------------------------------------------------------------------*/ 72 68 /** IRQ handling callback, forward status from call to diver structure. 73 69 * … … 87 83 hc_interrupt(&uhci->hc, status); 88 84 } 89 85 /*----------------------------------------------------------------------------*/ 90 86 /** Operations supported by the HC driver */ 91 87 static ddf_dev_ops_t hc_ops = { 92 88 .interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */ 93 89 }; 94 90 /*----------------------------------------------------------------------------*/ 95 91 /** Gets handle of the respective hc. 96 92 * … … 101 97 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) 102 98 { 103 ddf_fun_t *hc_fun = dev_to_uhci(ddf_fun_get_dev(fun))->hc_fun; 99 assert(fun); 100 ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun; 104 101 assert(hc_fun); 105 102 106 103 if (handle != NULL) 107 *handle = ddf_fun_get_handle(hc_fun);104 *handle = hc_fun->handle; 108 105 return EOK; 109 106 } 110 107 /*----------------------------------------------------------------------------*/ 111 108 /** USB interface implementation used by RH */ 112 109 static usb_iface_t usb_iface = { 113 110 .get_hc_handle = usb_iface_get_hc_handle, 114 111 }; 115 112 /*----------------------------------------------------------------------------*/ 116 113 /** Get root hub hw resources (I/O registers). 117 114 * … … 121 118 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun) 122 119 { 123 rh_t *rh = ddf_fun_data_get(fun); 120 assert(fun); 121 rh_t *rh = fun->driver_data; 124 122 assert(rh); 125 123 return &rh->resource_list; 126 124 } 127 125 /*----------------------------------------------------------------------------*/ 128 126 /** Interface to provide the root hub driver with hw info */ 129 127 static hw_res_ops_t hw_res_iface = { … … 131 129 .enable_interrupt = NULL, 132 130 }; 133 131 /*----------------------------------------------------------------------------*/ 134 132 /** RH function support for uhci_rhd */ 135 133 static ddf_dev_ops_t rh_ops = { … … 137 135 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface 138 136 }; 139 137 /*----------------------------------------------------------------------------*/ 140 138 /** Initialize hc and rh DDF structures and their respective drivers. 141 139 * … … 150 148 int device_setup_uhci(ddf_dev_t *device) 151 149 { 152 bool ih_registered = false;153 bool hc_inited = false;154 bool fun_bound = false;155 int rc;156 157 150 if (!device) 158 151 return EBADMEM; … … 164 157 } 165 158 159 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \ 160 if (ret != EOK) { \ 161 if (instance->hc_fun) \ 162 instance->hc_fun->driver_data = NULL; \ 163 ddf_fun_destroy(instance->hc_fun); \ 164 if (instance->rh_fun) {\ 165 instance->rh_fun->driver_data = NULL; \ 166 ddf_fun_destroy(instance->rh_fun); \ 167 } \ 168 usb_log_error(message); \ 169 return ret; \ 170 } else (void)0 171 172 instance->rh_fun = NULL; 166 173 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); 174 int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK; 175 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n"); 176 instance->hc_fun->ops = &hc_ops; 177 instance->hc_fun->driver_data = &instance->hc.generic; 175 178 176 179 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); 180 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK; 181 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n"); 182 instance->rh_fun->ops = &rh_ops; 183 instance->rh_fun->driver_data = &instance->rh; 185 184 186 185 uintptr_t reg_base = 0; … … 188 187 int irq = 0; 189 188 190 rc = get_my_registers(device, ®_base, ®_size, &irq); 191 if (rc != EOK) { 192 usb_log_error("Failed to get I/O addresses for %" PRIun ": %s.\n", 193 ddf_dev_get_handle(device), str_error(rc)); 194 goto error; 195 } 189 ret = get_my_registers(device, ®_base, ®_size, &irq); 190 CHECK_RET_DEST_FREE_RETURN(ret, 191 "Failed to get I/O addresses for %" PRIun ": %s.\n", 192 device->handle, str_error(ret)); 196 193 usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n", 197 194 (void *) reg_base, reg_size, irq); 198 195 199 rc = disable_legacy(device); 200 if (rc != EOK) { 201 usb_log_error("Failed to disable legacy USB: %s.\n", 202 str_error(rc)); 203 goto error; 204 } 205 206 rc = hc_register_irq_handler(device, reg_base, reg_size, irq, irq_handler); 207 if (rc != EOK) { 208 usb_log_error("Failed to register interrupt handler: %s.\n", 209 str_error(rc)); 210 goto error; 211 } 212 213 ih_registered = true; 196 ret = disable_legacy(device); 197 CHECK_RET_DEST_FREE_RETURN(ret, 198 "Failed to disable legacy USB: %s.\n", str_error(ret)); 199 200 const size_t ranges_count = hc_irq_pio_range_count(); 201 const size_t cmds_count = hc_irq_cmd_count(); 202 irq_pio_range_t irq_ranges[ranges_count]; 203 irq_cmd_t irq_cmds[cmds_count]; 204 ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 205 sizeof(irq_cmds), reg_base, reg_size); 206 CHECK_RET_DEST_FREE_RETURN(ret, 207 "Failed to generate IRQ commands: %s.\n", str_error(ret)); 208 209 irq_code_t irq_code = { 210 .rangecount = ranges_count, 211 .ranges = irq_ranges, 212 .cmdcount = cmds_count, 213 .cmds = irq_cmds 214 }; 215 216 /* Register handler to avoid interrupt lockup */ 217 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code); 218 CHECK_RET_DEST_FREE_RETURN(ret, 219 "Failed to register interrupt handler: %s.\n", str_error(ret)); 214 220 215 221 bool interrupts = false; 216 r c= enable_interrupts(device);217 if (r c!= EOK) {222 ret = enable_interrupts(device); 223 if (ret != EOK) { 218 224 usb_log_warning("Failed to enable interrupts: %s." 219 " Falling back to polling.\n", str_error(r c));225 " Falling back to polling.\n", str_error(ret)); 220 226 } else { 221 227 usb_log_debug("Hw interrupts enabled.\n"); … … 223 229 } 224 230 225 rc = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts); 226 if (rc != EOK) { 227 usb_log_error("Failed to init uhci_hcd: %s.\n", str_error(rc)); 228 goto error; 229 } 230 231 hc_inited = true; 232 233 rc = ddf_fun_bind(instance->hc_fun); 234 if (rc != EOK) { 235 usb_log_error("Failed to bind UHCI device function: %s.\n", 236 str_error(rc)); 237 goto error; 238 } 239 240 fun_bound = true; 241 242 rc = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 243 if (rc != EOK) { 244 usb_log_error("Failed to add UHCI to HC class: %s.\n", 245 str_error(rc)); 246 goto error; 247 } 248 249 rc = rh_init(&instance->rh, instance->rh_fun, 231 ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts); 232 CHECK_RET_DEST_FREE_RETURN(ret, 233 "Failed to init uhci_hcd: %s.\n", str_error(ret)); 234 235 #define CHECK_RET_FINI_RETURN(ret, message...) \ 236 if (ret != EOK) { \ 237 hc_fini(&instance->hc); \ 238 CHECK_RET_DEST_FREE_RETURN(ret, message); \ 239 return ret; \ 240 } else (void)0 241 242 ret = ddf_fun_bind(instance->hc_fun); 243 CHECK_RET_FINI_RETURN(ret, "Failed to bind UHCI device function: %s.\n", 244 str_error(ret)); 245 246 ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 247 CHECK_RET_FINI_RETURN(ret, 248 "Failed to add UHCI to HC class: %s.\n", str_error(ret)); 249 250 ret = rh_init(&instance->rh, instance->rh_fun, 250 251 (uintptr_t)instance->hc.registers + 0x10, 4); 251 if (rc != EOK) { 252 usb_log_error("Failed to setup UHCI root hub: %s.\n", 253 str_error(rc)); 254 goto error; 255 } 256 257 rc = ddf_fun_bind(instance->rh_fun); 258 if (rc != EOK) { 259 usb_log_error("Failed to register UHCI root hub: %s.\n", 260 str_error(rc)); 261 goto error; 262 } 252 CHECK_RET_FINI_RETURN(ret, 253 "Failed to setup UHCI root hub: %s.\n", str_error(ret)); 254 255 ret = ddf_fun_bind(instance->rh_fun); 256 CHECK_RET_FINI_RETURN(ret, 257 "Failed to register UHCI root hub: %s.\n", str_error(ret)); 263 258 264 259 return EOK; 265 266 error: 267 if (fun_bound) 268 ddf_fun_unbind(instance->hc_fun); 269 if (hc_inited) 270 hc_fini(&instance->hc); 271 if (ih_registered) 272 unregister_interrupt_handler(device, irq); 273 if (instance->hc_fun != NULL) 274 ddf_fun_destroy(instance->hc_fun); 275 if (instance->rh_fun != NULL) { 276 ddf_fun_destroy(instance->rh_fun); 277 } 278 return rc; 260 #undef CHECK_RET_FINI_RETURN 279 261 } 280 262 /**
Note:
See TracChangeset
for help on using the changeset viewer.