Changes in uspace/drv/bus/usb/uhci/uhci.c [795448f:c53007f] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/uhci/uhci.c
r795448f rc53007f 33 33 * @brief UHCI driver 34 34 */ 35 36 /* XXX Fix this */ 37 #define _DDF_DATA_IMPLANT 38 35 39 #include <errno.h> 40 #include <stdbool.h> 36 41 #include <str_error.h> 37 42 #include <ddf/interrupt.h> … … 60 65 } uhci_t; 61 66 62 static inline uhci_t * dev_to_uhci(const ddf_dev_t *dev) 63 { 64 assert(dev); 65 return dev->driver_data; 66 } 67 /*----------------------------------------------------------------------------*/ 67 static inline uhci_t *dev_to_uhci(ddf_dev_t *dev) 68 { 69 return ddf_dev_data_get(dev); 70 } 71 68 72 /** IRQ handling callback, forward status from call to diver structure. 69 73 * … … 83 87 hc_interrupt(&uhci->hc, status); 84 88 } 85 /*----------------------------------------------------------------------------*/ 89 86 90 /** Operations supported by the HC driver */ 87 91 static ddf_dev_ops_t hc_ops = { 88 92 .interfaces[USBHC_DEV_IFACE] = &hcd_iface, /* see iface.h/c */ 89 93 }; 90 /*----------------------------------------------------------------------------*/ 94 91 95 /** Gets handle of the respective hc. 92 96 * … … 97 101 static int usb_iface_get_hc_handle(ddf_fun_t *fun, devman_handle_t *handle) 98 102 { 99 assert(fun); 100 ddf_fun_t *hc_fun = dev_to_uhci(fun->dev)->hc_fun; 103 ddf_fun_t *hc_fun = dev_to_uhci(ddf_fun_get_dev(fun))->hc_fun; 101 104 assert(hc_fun); 102 105 103 106 if (handle != NULL) 104 *handle = hc_fun->handle;107 *handle = ddf_fun_get_handle(hc_fun); 105 108 return EOK; 106 109 } 107 /*----------------------------------------------------------------------------*/ 110 108 111 /** USB interface implementation used by RH */ 109 112 static usb_iface_t usb_iface = { 110 113 .get_hc_handle = usb_iface_get_hc_handle, 111 114 }; 112 /*----------------------------------------------------------------------------*/ 115 113 116 /** Get root hub hw resources (I/O registers). 114 117 * … … 118 121 static hw_resource_list_t *get_resource_list(ddf_fun_t *fun) 119 122 { 120 assert(fun); 121 rh_t *rh = fun->driver_data; 123 rh_t *rh = ddf_fun_data_get(fun); 122 124 assert(rh); 123 125 return &rh->resource_list; 124 126 } 125 /*----------------------------------------------------------------------------*/ 127 126 128 /** Interface to provide the root hub driver with hw info */ 127 129 static hw_res_ops_t hw_res_iface = { … … 129 131 .enable_interrupt = NULL, 130 132 }; 131 /*----------------------------------------------------------------------------*/ 133 132 134 /** RH function support for uhci_rhd */ 133 135 static ddf_dev_ops_t rh_ops = { … … 135 137 .interfaces[HW_RES_DEV_IFACE] = &hw_res_iface 136 138 }; 137 /*----------------------------------------------------------------------------*/ 139 138 140 /** Initialize hc and rh DDF structures and their respective drivers. 139 141 * … … 148 150 int device_setup_uhci(ddf_dev_t *device) 149 151 { 152 bool ih_registered = false; 153 bool hc_inited = false; 154 bool fun_bound = false; 155 int rc; 156 150 157 if (!device) 151 158 return EBADMEM; … … 157 164 } 158 165 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)0171 172 instance->rh_fun = NULL;173 166 instance->hc_fun = ddf_fun_create(device, fun_exposed, "uhci_hc"); 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; 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); 178 175 179 176 instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci_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; 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); 184 185 185 186 uintptr_t reg_base = 0; … … 187 188 int irq = 0; 188 189 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)); 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 } 193 196 usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n", 194 197 (void *) reg_base, reg_size, irq); 195 198 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)); 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; 220 214 221 215 bool interrupts = false; 222 r et= enable_interrupts(device);223 if (r et!= EOK) {216 rc = enable_interrupts(device); 217 if (rc != EOK) { 224 218 usb_log_warning("Failed to enable interrupts: %s." 225 " Falling back to polling.\n", str_error(r et));219 " Falling back to polling.\n", str_error(rc)); 226 220 } else { 227 221 usb_log_debug("Hw interrupts enabled.\n"); … … 229 223 } 230 224 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, 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, 251 250 (uintptr_t)instance->hc.registers + 0x10, 4); 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)); 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 } 258 263 259 264 return EOK; 260 #undef CHECK_RET_FINI_RETURN 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; 261 279 } 262 280 /**
Note:
See TracChangeset
for help on using the changeset viewer.