Changeset 507c6f3 in mainline
- Timestamp:
- 2013-07-05T10:18:25Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 98abd40, f83666c
- Parents:
- b2010e2
- Location:
- uspace/drv/bus/usb/ohci
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
rb2010e2 r507c6f3 83 83 }; 84 84 85 enum { 86 /** Number of PIO ranges used in IRQ code */ 87 hc_irq_pio_range_count = 88 sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t), 89 90 /** Number of commands used in IRQ code */ 91 hc_irq_cmd_count = 92 sizeof(ohci_irq_commands) / sizeof(irq_cmd_t) 93 }; 94 85 95 static void hc_gain_control(hc_t *instance); 86 96 static void hc_start(hc_t *instance); … … 89 99 static int interrupt_emulator(hc_t *instance); 90 100 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 91 92 /** Get number of PIO ranges used in IRQ code.93 * @return Number of ranges.94 */95 size_t hc_irq_pio_range_count(void)96 {97 return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);98 }99 100 /** Get number of commands used in IRQ code.101 * @return Number of commands.102 */103 size_t hc_irq_cmd_count(void)104 {105 return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);106 }107 101 108 102 /** Generate IRQ code. … … 133 127 cmds[3].addr = (void *) ®isters->interrupt_status; 134 128 OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS); 129 130 return EOK; 131 } 132 133 /** Register interrupt handler. 134 * 135 * @param[in] device Host controller DDF device 136 * @param[in] reg_base Register range base 137 * @param[in] reg_size Register range size 138 * @param[in] irq Interrupt number 139 * @paran[in] handler Interrupt handler 140 * 141 * @return EOK on success or negative error code 142 */ 143 int hc_register_irq_handler(ddf_dev_t *device, uintptr_t reg_base, size_t reg_size, 144 int irq, interrupt_handler_t handler) 145 { 146 int rc; 147 148 irq_pio_range_t irq_ranges[hc_irq_pio_range_count]; 149 irq_cmd_t irq_cmds[hc_irq_cmd_count]; 150 151 irq_code_t irq_code = { 152 .rangecount = hc_irq_pio_range_count, 153 .ranges = irq_ranges, 154 .cmdcount = hc_irq_cmd_count, 155 .cmds = irq_cmds 156 }; 157 158 rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 159 sizeof(irq_cmds), reg_base, reg_size); 160 if (rc != EOK) { 161 usb_log_error("Failed to generate IRQ code: %s.\n", 162 str_error(rc)); 163 return rc; 164 } 165 166 /* Register handler to avoid interrupt lockup */ 167 rc = register_interrupt_handler(device, irq, handler, &irq_code); 168 if (rc != EOK) { 169 usb_log_error("Failed to register interrupt handler: %s.\n", 170 str_error(rc)); 171 return rc; 172 } 135 173 136 174 return EOK; -
uspace/drv/bus/usb/ohci/hc.h
rb2010e2 r507c6f3 35 35 #define DRV_OHCI_HC_H 36 36 37 #include <ddf/interrupt.h> 37 38 #include <fibril.h> 38 39 #include <fibril_synch.h> … … 74 75 } hc_t; 75 76 76 size_t hc_irq_pio_range_count(void);77 size_t hc_irq_cmd_count(void);78 77 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t, 79 78 size_t); 79 int hc_register_irq_handler(ddf_dev_t *, uintptr_t, size_t, int, interrupt_handler_t); 80 80 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun); 81 81 int hc_init(hc_t *instance, uintptr_t regs, size_t reg_size, bool interrupts); -
uspace/drv/bus/usb/ohci/ohci.c
rb2010e2 r507c6f3 143 143 int device_setup_ohci(ddf_dev_t *device) 144 144 { 145 bool ih_registered = false; 146 bool hc_inited = false; 147 int rc; 148 145 149 if (device == NULL) 146 150 return EBADMEM; … … 152 156 } 153 157 154 #define CHECK_RET_DEST_FREE_RETURN(ret, message...) \155 if (ret != EOK) { \156 if (instance->hc_fun) { \157 ddf_fun_destroy(instance->hc_fun); \158 } \159 if (instance->rh_fun) { \160 ddf_fun_destroy(instance->rh_fun); \161 } \162 usb_log_error(message); \163 return ret; \164 } else (void)0165 166 158 instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc"); 167 int ret = instance->hc_fun ? EOK : ENOMEM; 168 CHECK_RET_DEST_FREE_RETURN(ret, 169 "Failed to create OHCI HC function: %s.\n", str_error(ret)); 159 if (instance->hc_fun == NULL) { 160 usb_log_error("Failed to create OHCI HC function: %s.\n", 161 str_error(ENOMEM)); 162 rc = ENOMEM; 163 goto error; 164 } 165 170 166 ddf_fun_set_ops(instance->hc_fun, &hc_ops); 171 167 ddf_fun_data_implant(instance->hc_fun, &instance->hc); 172 168 173 169 instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh"); 174 ret = instance->rh_fun ? EOK : ENOMEM; 175 CHECK_RET_DEST_FREE_RETURN(ret, 176 "Failed to create OHCI RH function: %s.\n", str_error(ret)); 170 if (instance->rh_fun == NULL) { 171 usb_log_error("Failed to create OHCI RH function: %s.\n", 172 str_error(ENOMEM)); 173 rc = ENOMEM; 174 goto error; 175 } 176 177 177 ddf_fun_set_ops(instance->rh_fun, &rh_ops); 178 178 … … 181 181 int irq = 0; 182 182 183 ret = get_my_registers(device, ®_base, ®_size, &irq); 184 CHECK_RET_DEST_FREE_RETURN(ret, 185 "Failed to get register memory addresses for %" PRIun ": %s.\n", 186 ddf_dev_get_handle(device), str_error(ret)); 183 rc = get_my_registers(device, ®_base, ®_size, &irq); 184 if (rc != EOK) { 185 usb_log_error("Failed to get register memory addresses " 186 "for %" PRIun ": %s.\n", ddf_dev_get_handle(device), 187 str_error(rc)); 188 goto error; 189 } 190 187 191 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n", 188 192 (void *) reg_base, reg_size, irq); 189 193 190 const size_t ranges_count = hc_irq_pio_range_count(); 191 const size_t cmds_count = hc_irq_cmd_count(); 192 irq_pio_range_t irq_ranges[ranges_count]; 193 irq_cmd_t irq_cmds[cmds_count]; 194 irq_code_t irq_code = { 195 .rangecount = ranges_count, 196 .ranges = irq_ranges, 197 .cmdcount = cmds_count, 198 .cmds = irq_cmds 199 }; 200 201 ret = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds, 202 sizeof(irq_cmds), reg_base, reg_size); 203 CHECK_RET_DEST_FREE_RETURN(ret, 204 "Failed to generate IRQ code: %s.\n", str_error(ret)); 205 206 207 /* Register handler to avoid interrupt lockup */ 208 ret = register_interrupt_handler(device, irq, irq_handler, &irq_code); 209 CHECK_RET_DEST_FREE_RETURN(ret, 210 "Failed to register interrupt handler: %s.\n", str_error(ret)); 194 rc = hc_register_irq_handler(device, reg_base, reg_size, irq, irq_handler); 195 if (rc != EOK) { 196 usb_log_error("Failed to register interrupt handler: %s.\n", 197 str_error(rc)); 198 goto error; 199 } 200 201 ih_registered = true; 211 202 212 203 /* Try to enable interrupts */ 213 204 bool interrupts = false; 214 r et= enable_interrupts(device);215 if (r et!= EOK) {205 rc = enable_interrupts(device); 206 if (rc != EOK) { 216 207 usb_log_warning("Failed to enable interrupts: %s." 217 " Falling back to polling\n", str_error(r et));208 " Falling back to polling\n", str_error(rc)); 218 209 /* We don't need that handler */ 219 210 unregister_interrupt_handler(device, irq); 211 ih_registered = false; 220 212 } else { 221 213 usb_log_debug("Hw interrupts enabled.\n"); … … 223 215 } 224 216 225 ret = hc_init(&instance->hc, reg_base, reg_size, interrupts); 226 CHECK_RET_DEST_FREE_RETURN(ret, 227 "Failed to init ohci_hcd: %s.\n", str_error(ret)); 228 229 #define CHECK_RET_FINI_RETURN(ret, message...) \ 230 if (ret != EOK) { \ 231 hc_fini(&instance->hc); \ 232 unregister_interrupt_handler(device, irq); \ 233 CHECK_RET_DEST_FREE_RETURN(ret, message); \ 234 } else (void)0 235 236 237 ret = ddf_fun_bind(instance->hc_fun); 238 CHECK_RET_FINI_RETURN(ret, 239 "Failed to bind OHCI device function: %s.\n", str_error(ret)); 240 241 ret = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 242 CHECK_RET_FINI_RETURN(ret, 243 "Failed to add OHCI to HC class: %s.\n", str_error(ret)); 244 245 ret = hc_register_hub(&instance->hc, instance->rh_fun); 246 CHECK_RET_FINI_RETURN(ret, 247 "Failed to register OHCI root hub: %s.\n", str_error(ret)); 248 return ret; 249 250 #undef CHECK_RET_FINI_RETURN 217 rc = hc_init(&instance->hc, reg_base, reg_size, interrupts); 218 if (rc != EOK) { 219 usb_log_error("Failed to init ohci_hcd: %s.\n", str_error(rc)); 220 goto error; 221 } 222 223 hc_inited = true; 224 225 rc = ddf_fun_bind(instance->hc_fun); 226 if (rc != EOK) { 227 usb_log_error("Failed to bind OHCI device function: %s.\n", 228 str_error(rc)); 229 goto error; 230 } 231 232 rc = ddf_fun_add_to_category(instance->hc_fun, USB_HC_CATEGORY); 233 if (rc != EOK) { 234 usb_log_error("Failed to add OHCI to HC category: %s.\n", 235 str_error(rc)); 236 goto error; 237 } 238 239 rc = hc_register_hub(&instance->hc, instance->rh_fun); 240 if (rc != EOK) { 241 usb_log_error("Failed to register OHCI root hub: %s.\n", 242 str_error(rc)); 243 goto error; 244 } 245 246 return EOK; 247 248 error: 249 if (hc_inited) 250 hc_fini(&instance->hc); 251 if (ih_registered) 252 unregister_interrupt_handler(device, irq); 253 if (instance->hc_fun != NULL) 254 ddf_fun_destroy(instance->hc_fun); 255 if (instance->rh_fun != NULL) 256 ddf_fun_destroy(instance->rh_fun); 257 return rc; 251 258 } 252 259 /**
Note:
See TracChangeset
for help on using the changeset viewer.