Changeset cffa14e6 in mainline
- Timestamp:
- 2013-07-24T17:27:56Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- db71e2a
- Parents:
- c442f63
- Location:
- uspace/drv/bus/usb
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ehci/main.c
rc442f63 rcffa14e6 33 33 * Main routines of EHCI driver. 34 34 */ 35 36 35 #include <ddf/driver.h> 37 36 #include <ddf/interrupt.h> 38 37 #include <device/hw_res.h> 39 38 #include <errno.h> 40 #include <stdbool.h>41 39 #include <str_error.h> 42 40 … … 72 70 static int ehci_dev_add(ddf_dev_t *device) 73 71 { 74 ddf_fun_t *hc_fun = NULL;75 bool fun_bound = false;76 77 72 assert(device); 73 #define CHECK_RET_RETURN(ret, message...) \ 74 if (ret != EOK) { \ 75 usb_log_error(message); \ 76 return ret; \ 77 } 78 78 79 79 uintptr_t reg_base = 0; … … 81 81 int irq = 0; 82 82 83 int rc = get_my_registers(device, ®_base, ®_size, &irq); 84 if (rc != EOK) { 85 usb_log_error("Failed to get memory addresses for %" PRIun 86 ": %s.\n", ddf_dev_get_handle(device), str_error(rc)); 87 goto error; 88 } 89 83 int ret = get_my_registers(device, ®_base, ®_size, &irq); 84 CHECK_RET_RETURN(ret, 85 "Failed to get memory addresses for %" PRIun ": %s.\n", 86 ddf_dev_get_handle(device), str_error(ret)); 90 87 usb_log_info("Memory mapped regs at 0x%" PRIxn " (size %zu), IRQ %d.\n", 91 88 reg_base, reg_size, irq); 92 89 93 rc = disable_legacy(device, reg_base, reg_size); 94 if (rc != EOK) { 95 usb_log_error("Failed to disable legacy USB: %s.\n", 96 str_error(rc)); 97 goto error; 98 } 90 ret = disable_legacy(device, reg_base, reg_size); 91 CHECK_RET_RETURN(ret, 92 "Failed to disable legacy USB: %s.\n", str_error(ret)); 99 93 100 hc_fun = ddf_fun_create(device, fun_exposed, "ehci_hc");94 ddf_fun_t *hc_fun = ddf_fun_create(device, fun_exposed, "ehci_hc"); 101 95 if (hc_fun == NULL) { 102 96 usb_log_error("Failed to create EHCI function.\n"); 103 rc = ENOMEM; 104 goto error; 97 return ENOMEM; 105 98 } 106 107 99 hcd_t *ehci_hc = ddf_fun_data_alloc(hc_fun, sizeof(hcd_t)); 108 100 if (ehci_hc == NULL) { 109 101 usb_log_error("Failed to alloc generic HC driver.\n"); 110 rc = ENOMEM; 111 goto error; 102 return ENOMEM; 112 103 } 113 114 104 /* High Speed, no bandwidth */ 115 105 hcd_init(ehci_hc, USB_SPEED_HIGH, 0, NULL); 116 106 ddf_fun_set_ops(hc_fun, &hc_ops); 117 107 118 rc = ddf_fun_bind(hc_fun); 119 if (rc != EOK) { 120 usb_log_error("Failed to bind EHCI function: %s.\n", 121 str_error(rc)); 122 goto error; 123 } 124 125 fun_bound = true; 126 127 rc = ddf_fun_add_to_category(hc_fun, USB_HC_CATEGORY); 128 if (rc != EOK) { 129 usb_log_error("Failed to add EHCI to HC class: %s.\n", 130 str_error(rc)); 131 goto error; 132 } 108 ret = ddf_fun_bind(hc_fun); 109 CHECK_RET_RETURN(ret, 110 "Failed to bind EHCI function: %s.\n", 111 str_error(ret)); 112 ret = ddf_fun_add_to_category(hc_fun, USB_HC_CATEGORY); 113 CHECK_RET_RETURN(ret, 114 "Failed to add EHCI to HC class: %s.\n", 115 str_error(ret)); 133 116 134 117 usb_log_info("Controlling new EHCI device `%s' (handle %" PRIun ").\n", … … 136 119 137 120 return EOK; 138 error: 139 if (fun_bound) 140 ddf_fun_unbind(hc_fun); 141 if (hc_fun != NULL) 142 ddf_fun_destroy(hc_fun); 143 return rc; 121 #undef CHECK_RET_RETURN 144 122 } 145 123 -
uspace/drv/bus/usb/ehci/res.c
rc442f63 rcffa14e6 145 145 return ENOMEM; 146 146 147 #define CHECK_RET_HANGUP_RETURN(ret, message...) \ 148 if (ret != EOK) { \ 149 usb_log_error(message); \ 150 async_hangup(parent_sess); \ 151 return ret; \ 152 } else (void)0 153 147 154 /* Read the first EEC. i.e. Legacy Support register */ 148 155 uint32_t usblegsup; 149 int r c= pci_config_space_read_32(parent_sess,156 int ret = pci_config_space_read_32(parent_sess, 150 157 eecp + USBLEGSUP_OFFSET, &usblegsup); 151 if (rc != EOK) { 152 usb_log_error("Failed to read USBLEGSUP: %s.\n", 153 str_error(rc)); 154 goto error; 155 } 156 158 CHECK_RET_HANGUP_RETURN(ret, 159 "Failed to read USBLEGSUP: %s.\n", str_error(ret)); 157 160 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 158 161 … … 160 163 * byte. (OS Control semaphore)*/ 161 164 usb_log_debug("Requesting OS control.\n"); 162 r c= pci_config_space_write_8(parent_sess,165 ret = pci_config_space_write_8(parent_sess, 163 166 eecp + USBLEGSUP_OFFSET + 3, 1); 164 if (rc != EOK) { 165 usb_log_error("Failed to request OS EHCI control: %s.\n", 166 str_error(rc)); 167 goto error; 168 } 167 CHECK_RET_HANGUP_RETURN(ret, "Failed to request OS EHCI control: %s.\n", 168 str_error(ret)); 169 169 170 170 size_t wait = 0; 171 171 /* Wait for BIOS to release control. */ 172 r c= pci_config_space_read_32(172 ret = pci_config_space_read_32( 173 173 parent_sess, eecp + USBLEGSUP_OFFSET, &usblegsup); 174 if (rc != EOK) {175 usb_log_error("Failed reading PCI config space: %s.\n",176 str_error(rc));177 goto error;178 }179 180 174 while ((wait < DEFAULT_WAIT) && (usblegsup & USBLEGSUP_BIOS_CONTROL)) { 181 175 async_usleep(WAIT_STEP); 182 r c= pci_config_space_read_32(parent_sess,176 ret = pci_config_space_read_32(parent_sess, 183 177 eecp + USBLEGSUP_OFFSET, &usblegsup); 184 if (rc != EOK) {185 usb_log_error("Failed reading PCI config space: %s.\n",186 str_error(rc));187 goto error;188 }189 178 wait += WAIT_STEP; 190 179 } … … 199 188 usb_log_warning( "BIOS failed to release control after " 200 189 "%zu usecs, force it.\n", wait); 201 r c= pci_config_space_write_32(parent_sess,190 ret = pci_config_space_write_32(parent_sess, 202 191 eecp + USBLEGSUP_OFFSET, USBLEGSUP_OS_CONTROL); 203 if (rc != EOK) { 204 usb_log_error("Failed to force OS control: " 205 "%s.\n", str_error(rc)); 206 goto error; 207 } 208 192 CHECK_RET_HANGUP_RETURN(ret, "Failed to force OS control: " 193 "%s.\n", str_error(ret)); 209 194 /* 210 195 * Check capability type here, value of 01h identifies the capability … … 216 201 /* Read the second EEC Legacy Support and Control register */ 217 202 uint32_t usblegctlsts; 218 r c= pci_config_space_read_32(parent_sess,203 ret = pci_config_space_read_32(parent_sess, 219 204 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts); 220 if (rc != EOK) { 221 usb_log_error("Failed to get USBLEGCTLSTS: %s.\n", 222 str_error(rc)); 223 goto error; 224 } 225 205 CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS: %s.\n", 206 str_error(ret)); 226 207 usb_log_debug("USBLEGCTLSTS: %" PRIx32 ".\n", usblegctlsts); 227 208 /* … … 230 211 * interfering. NOTE: Three upper bits are WC 231 212 */ 232 r c= pci_config_space_write_32(parent_sess,213 ret = pci_config_space_write_32(parent_sess, 233 214 eecp + USBLEGCTLSTS_OFFSET, 0xe0000000); 234 if (rc != EOK) { 235 usb_log_error("Failed(%d) zero USBLEGCTLSTS.\n", rc); 236 goto error; 237 } 238 215 CHECK_RET_HANGUP_RETURN(ret, "Failed(%d) zero USBLEGCTLSTS.\n", ret); 239 216 udelay(10); 240 r c= pci_config_space_read_32(parent_sess,217 ret = pci_config_space_read_32(parent_sess, 241 218 eecp + USBLEGCTLSTS_OFFSET, &usblegctlsts); 242 if (rc != EOK) { 243 usb_log_error("Failed to get USBLEGCTLSTS 2: %s.\n", 244 str_error(rc)); 245 goto error; 246 } 247 219 CHECK_RET_HANGUP_RETURN(ret, "Failed to get USBLEGCTLSTS 2: %s.\n", 220 str_error(ret)); 248 221 usb_log_debug("Zeroed USBLEGCTLSTS: %" PRIx32 ".\n", 249 222 usblegctlsts); … … 251 224 252 225 /* Read again Legacy Support register */ 253 r c= pci_config_space_read_32(parent_sess,226 ret = pci_config_space_read_32(parent_sess, 254 227 eecp + USBLEGSUP_OFFSET, &usblegsup); 255 if (rc != EOK) { 256 usb_log_error("Failed to read USBLEGSUP: %s.\n", 257 str_error(rc)); 258 goto error; 259 } 260 228 CHECK_RET_HANGUP_RETURN(ret, "Failed to read USBLEGSUP: %s.\n", 229 str_error(ret)); 261 230 usb_log_debug("USBLEGSUP: %" PRIx32 ".\n", usblegsup); 262 231 async_hangup(parent_sess); 263 232 return EOK; 264 error: 265 async_hangup(parent_sess); 266 return rc; 233 #undef CHECK_RET_HANGUP_RETURN 267 234 } 268 235 … … 272 239 usb_log_debug("Disabling EHCI legacy support.\n"); 273 240 241 #define CHECK_RET_RETURN(ret, message...) \ 242 if (ret != EOK) { \ 243 usb_log_error(message); \ 244 return ret; \ 245 } else (void)0 246 274 247 /* Map EHCI registers */ 275 248 void *regs = NULL; 276 int rc = pio_enable((void*)reg_base, reg_size, ®s); 277 if (rc != EOK) { 278 usb_log_error("Failed to map registers %p: %s.\n", 279 (void *) reg_base, str_error(rc)); 280 return rc; 281 } 249 int ret = pio_enable((void*)reg_base, reg_size, ®s); 250 CHECK_RET_RETURN(ret, "Failed to map registers %p: %s.\n", 251 (void *) reg_base, str_error(ret)); 282 252 283 253 usb_log_debug2("Registers mapped at: %p.\n", regs); … … 293 263 usb_log_debug("Value of EECP: %x.\n", eecp); 294 264 295 rc = disable_extended_caps(device, eecp); 296 if (rc != EOK) { 297 usb_log_error("Failed to disable extended capabilities: %s.\n", 298 str_error(rc)); 299 return rc; 300 } 265 ret = disable_extended_caps(device, eecp); 266 CHECK_RET_RETURN(ret, "Failed to disable extended capabilities: %s.\n", 267 str_error(ret)); 268 269 #undef CHECK_RET_RETURN 301 270 302 271 /* … … 337 306 usbcmd, *usbcmd, usbsts, *usbsts, usbint, *usbint, usbconf,*usbconf); 338 307 339 return r c;308 return ret; 340 309 } 341 310 -
uspace/drv/bus/usb/ohci/hc.c
rc442f63 rcffa14e6 35 35 36 36 #include <errno.h> 37 #include <stdbool.h>38 37 #include <str_error.h> 39 38 #include <adt/list.h> … … 84 83 }; 85 84 86 enum {87 /** Number of PIO ranges used in IRQ code */88 hc_irq_pio_range_count =89 sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t),90 91 /** Number of commands used in IRQ code */92 hc_irq_cmd_count =93 sizeof(ohci_irq_commands) / sizeof(irq_cmd_t)94 };95 96 85 static void hc_gain_control(hc_t *instance); 97 86 static void hc_start(hc_t *instance); … … 100 89 static int interrupt_emulator(hc_t *instance); 101 90 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 } 102 107 103 108 /** Generate IRQ code. … … 132 137 } 133 138 134 /** Register interrupt handler.135 *136 * @param[in] device Host controller DDF device137 * @param[in] reg_base Register range base138 * @param[in] reg_size Register range size139 * @param[in] irq Interrupt number140 * @paran[in] handler Interrupt handler141 *142 * @return EOK on success or negative error code143 */144 int hc_register_irq_handler(ddf_dev_t *device, uintptr_t reg_base, size_t reg_size,145 int irq, interrupt_handler_t handler)146 {147 int rc;148 149 irq_pio_range_t irq_ranges[hc_irq_pio_range_count];150 irq_cmd_t irq_cmds[hc_irq_cmd_count];151 152 irq_code_t irq_code = {153 .rangecount = hc_irq_pio_range_count,154 .ranges = irq_ranges,155 .cmdcount = hc_irq_cmd_count,156 .cmds = irq_cmds157 };158 159 rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,160 sizeof(irq_cmds), reg_base, reg_size);161 if (rc != EOK) {162 usb_log_error("Failed to generate IRQ code: %s.\n",163 str_error(rc));164 return rc;165 }166 167 /* Register handler to avoid interrupt lockup */168 rc = register_interrupt_handler(device, irq, handler, &irq_code);169 if (rc != EOK) {170 usb_log_error("Failed to register interrupt handler: %s.\n",171 str_error(rc));172 return rc;173 }174 175 return EOK;176 }177 178 139 /** Announce OHCI root hub to the DDF 179 140 * … … 184 145 int hc_register_hub(hc_t *instance, ddf_fun_t *hub_fun) 185 146 { 186 bool addr_reqd = false;187 bool ep_added = false;188 bool fun_bound = false;189 int rc;190 191 147 assert(instance); 192 148 assert(hub_fun); … … 194 150 /* Try to get address 1 for root hub. */ 195 151 instance->rh.address = 1; 196 rc= usb_device_manager_request_address(152 int ret = usb_device_manager_request_address( 197 153 &instance->generic.dev_manager, &instance->rh.address, false, 198 154 USB_SPEED_FULL); 199 if (r c!= EOK) {155 if (ret != EOK) { 200 156 usb_log_error("Failed to get OHCI root hub address: %s\n", 201 str_error(rc)); 202 goto error; 203 } 204 205 addr_reqd = true; 206 207 rc = usb_endpoint_manager_add_ep( 157 str_error(ret)); 158 return ret; 159 } 160 161 #define CHECK_RET_UNREG_RETURN(ret, message...) \ 162 if (ret != EOK) { \ 163 usb_log_error(message); \ 164 usb_endpoint_manager_remove_ep( \ 165 &instance->generic.ep_manager, instance->rh.address, 0, \ 166 USB_DIRECTION_BOTH, NULL, NULL); \ 167 usb_device_manager_release_address( \ 168 &instance->generic.dev_manager, instance->rh.address); \ 169 return ret; \ 170 } else (void)0 171 172 ret = usb_endpoint_manager_add_ep( 208 173 &instance->generic.ep_manager, instance->rh.address, 0, 209 174 USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, USB_SPEED_FULL, 64, 210 175 0, NULL, NULL); 211 if (rc != EOK) { 212 usb_log_error("Failed to register root hub control endpoint: %s.\n", 213 str_error(rc)); 214 goto error; 215 } 216 217 ep_added = true; 218 219 rc = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100); 220 if (rc != EOK) { 221 usb_log_error("Failed to add root hub match-id: %s.\n", 222 str_error(rc)); 223 goto error; 224 } 225 226 rc = ddf_fun_bind(hub_fun); 227 if (rc != EOK) { 228 usb_log_error("Failed to bind root hub function: %s.\n", 229 str_error(rc)); 230 goto error; 231 } 232 233 fun_bound = true; 234 235 rc = usb_device_manager_bind_address(&instance->generic.dev_manager, 176 CHECK_RET_UNREG_RETURN(ret, 177 "Failed to register root hub control endpoint: %s.\n", 178 str_error(ret)); 179 180 ret = ddf_fun_add_match_id(hub_fun, "usb&class=hub", 100); 181 CHECK_RET_UNREG_RETURN(ret, 182 "Failed to add root hub match-id: %s.\n", str_error(ret)); 183 184 ret = ddf_fun_bind(hub_fun); 185 CHECK_RET_UNREG_RETURN(ret, 186 "Failed to bind root hub function: %s.\n", str_error(ret)); 187 188 ret = usb_device_manager_bind_address(&instance->generic.dev_manager, 236 189 instance->rh.address, ddf_fun_get_handle(hub_fun)); 237 if (r c != EOK) {190 if (ret != EOK) 238 191 usb_log_warning("Failed to bind root hub address: %s.\n", 239 str_error(rc)); 240 } 192 str_error(ret)); 241 193 242 194 return EOK; 243 error: 244 if (fun_bound) 245 ddf_fun_unbind(hub_fun); 246 if (ep_added) { 247 usb_endpoint_manager_remove_ep( 248 &instance->generic.ep_manager, instance->rh.address, 0, 249 USB_DIRECTION_BOTH, NULL, NULL); 250 } 251 if (addr_reqd) { 252 usb_device_manager_release_address( 253 &instance->generic.dev_manager, instance->rh.address); 254 } 255 return rc; 195 #undef CHECK_RET_RELEASE 256 196 } 257 197 … … 268 208 assert(instance); 269 209 270 int rc = 210 #define CHECK_RET_RETURN(ret, message...) \ 211 if (ret != EOK) { \ 212 usb_log_error(message); \ 213 return ret; \ 214 } else (void)0 215 216 int ret = 271 217 pio_enable((void*)regs, reg_size, (void**)&instance->registers); 272 if (rc != EOK) { 273 usb_log_error("Failed to gain access to device registers: %s.\n", 274 str_error(rc)); 275 return rc; 276 } 218 CHECK_RET_RETURN(ret, 219 "Failed to gain access to device registers: %s.\n", str_error(ret)); 277 220 278 221 list_initialize(&instance->pending_batches); … … 285 228 instance->generic.ep_remove_hook = ohci_endpoint_fini; 286 229 287 rc = hc_init_memory(instance); 288 if (rc != EOK) { 289 usb_log_error("Failed to create OHCI memory structures: %s.\n", 290 str_error(rc)); 291 return rc; 292 } 230 ret = hc_init_memory(instance); 231 CHECK_RET_RETURN(ret, "Failed to create OHCI memory structures: %s.\n", 232 str_error(ret)); 233 #undef CHECK_RET_RETURN 293 234 294 235 fibril_mutex_initialize(&instance->guard); -
uspace/drv/bus/usb/ohci/hc.h
rc442f63 rcffa14e6 35 35 #define DRV_OHCI_HC_H 36 36 37 #include <ddf/interrupt.h>38 37 #include <fibril.h> 39 38 #include <fibril_synch.h> … … 75 74 } hc_t; 76 75 76 size_t hc_irq_pio_range_count(void); 77 size_t hc_irq_cmd_count(void); 77 78 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t, 78 79 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
rc442f63 rcffa14e6 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 149 145 if (device == NULL) 150 146 return EBADMEM; … … 156 152 } 157 153 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)0 165 158 166 instance->hc_fun = ddf_fun_create(device, fun_exposed, "ohci_hc"); 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 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)); 166 170 ddf_fun_set_ops(instance->hc_fun, &hc_ops); 167 171 ddf_fun_data_implant(instance->hc_fun, &instance->hc); 168 172 169 173 instance->rh_fun = ddf_fun_create(device, fun_inner, "ohci_rh"); 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 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)); 177 177 ddf_fun_set_ops(instance->rh_fun, &rh_ops); 178 178 … … 181 181 int irq = 0; 182 182 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 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)); 191 187 usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n", 192 188 (void *) reg_base, reg_size, irq); 193 189 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; 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)); 202 211 203 212 /* Try to enable interrupts */ 204 213 bool interrupts = false; 205 r c= enable_interrupts(device);206 if (r c!= EOK) {214 ret = enable_interrupts(device); 215 if (ret != EOK) { 207 216 usb_log_warning("Failed to enable interrupts: %s." 208 " Falling back to polling\n", str_error(r c));217 " Falling back to polling\n", str_error(ret)); 209 218 /* We don't need that handler */ 210 219 unregister_interrupt_handler(device, irq); 211 ih_registered = false;212 220 } else { 213 221 usb_log_debug("Hw interrupts enabled.\n"); … … 215 223 } 216 224 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; 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 258 251 } 259 252 /** -
uspace/drv/bus/usb/uhci/hc.c
rc442f63 rcffa14e6 90 90 static int hc_debug_checker(void *arg); 91 91 92 enum { 93 /** Number of PIO ranges used in IRQ code */ 94 hc_irq_pio_range_count = 95 sizeof(uhci_irq_pio_ranges) / sizeof(irq_pio_range_t), 96 97 /* Number of commands used in IRQ code */ 98 hc_irq_cmd_count = 99 sizeof(uhci_irq_commands) / sizeof(irq_cmd_t) 100 }; 92 93 /** Get number of PIO ranges used in IRQ code. 94 * @return Number of ranges. 95 */ 96 size_t hc_irq_pio_range_count(void) 97 { 98 return sizeof(uhci_irq_pio_ranges) / sizeof(irq_pio_range_t); 99 } 100 101 /** Get number of commands used in IRQ code. 102 * @return Number of commands. 103 */ 104 size_t hc_irq_cmd_count(void) 105 { 106 return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t); 107 } 101 108 102 109 /** Generate IRQ code. … … 126 133 cmds[0].addr = ®isters->usbsts; 127 134 cmds[3].addr = ®isters->usbsts; 128 129 return EOK;130 }131 132 /** Register interrupt handler.133 *134 * @param[in] device Host controller DDF device135 * @param[in] reg_base Register range base136 * @param[in] reg_size Register range size137 * @param[in] irq Interrupt number138 * @paran[in] handler Interrupt handler139 *140 * @return EOK on success or negative error code141 */142 int hc_register_irq_handler(ddf_dev_t *device, uintptr_t reg_base, size_t reg_size,143 int irq, interrupt_handler_t handler)144 {145 int rc;146 irq_pio_range_t irq_ranges[hc_irq_pio_range_count];147 irq_cmd_t irq_cmds[hc_irq_cmd_count];148 rc = hc_get_irq_code(irq_ranges, sizeof(irq_ranges), irq_cmds,149 sizeof(irq_cmds), reg_base, reg_size);150 if (rc != EOK) {151 usb_log_error("Failed to generate IRQ commands: %s.\n",152 str_error(rc));153 return rc;154 }155 156 irq_code_t irq_code = {157 .rangecount = hc_irq_pio_range_count,158 .ranges = irq_ranges,159 .cmdcount = hc_irq_cmd_count,160 .cmds = irq_cmds161 };162 163 /* Register handler to avoid interrupt lockup */164 rc = register_interrupt_handler(device, irq, handler, &irq_code);165 if (rc != EOK) {166 usb_log_error("Failed to register interrupt handler: %s.\n",167 str_error(rc));168 return rc;169 }170 135 171 136 return EOK; … … 244 209 { 245 210 assert(reg_size >= sizeof(uhci_regs_t)); 246 int rc; 211 int ret; 212 213 #define CHECK_RET_RETURN(ret, message...) \ 214 if (ret != EOK) { \ 215 usb_log_error(message); \ 216 return ret; \ 217 } else (void) 0 247 218 248 219 instance->hw_interrupts = interrupts; … … 251 222 /* allow access to hc control registers */ 252 223 uhci_regs_t *io; 253 rc = pio_enable(regs, reg_size, (void **)&io); 254 if (rc != EOK) { 255 usb_log_error("Failed to gain access to registers at %p: %s.\n", 256 io, str_error(rc)); 257 return rc; 258 } 259 224 ret = pio_enable(regs, reg_size, (void **)&io); 225 CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p: %s.\n", 226 io, str_error(ret)); 260 227 instance->registers = io; 261 228 usb_log_debug( 262 229 "Device registers at %p (%zuB) accessible.\n", io, reg_size); 263 230 264 r c= hc_init_mem_structures(instance);265 if (rc != EOK) {266 usb_log_error("Failed to initialize UHCI memory structures: %s.\n",267 str_error(rc));268 return rc; 269 } 231 ret = hc_init_mem_structures(instance); 232 CHECK_RET_RETURN(ret, 233 "Failed to initialize UHCI memory structures: %s.\n", 234 str_error(ret)); 235 236 #undef CHECK_RET_RETURN 270 237 271 238 hcd_init(&instance->generic, USB_SPEED_FULL, … … 430 397 431 398 return EOK; 399 #undef CHECK_RET_CLEAR_RETURN 432 400 } 433 401 -
uspace/drv/bus/usb/uhci/hc.h
rc442f63 rcffa14e6 36 36 #define DRV_UHCI_HC_H 37 37 38 #include <ddf/interrupt.h>39 38 #include <fibril.h> 40 39 #include <usb/host/hcd.h> … … 120 119 } hc_t; 121 120 122 int hc_register_irq_handler(ddf_dev_t *, uintptr_t, size_t, int, interrupt_handler_t); 121 size_t hc_irq_pio_range_count(void); 122 size_t hc_irq_cmd_count(void); 123 123 int hc_get_irq_code(irq_pio_range_t [], size_t, irq_cmd_t [], size_t, uintptr_t, 124 124 size_t); -
uspace/drv/bus/usb/uhci/uhci.c
rc442f63 rcffa14e6 38 38 39 39 #include <errno.h> 40 #include <stdbool.h>41 40 #include <str_error.h> 42 41 #include <ddf/interrupt.h> … … 150 149 int device_setup_uhci(ddf_dev_t *device) 151 150 { 152 bool ih_registered = false;153 bool hc_inited = false;154 bool fun_bound = false;155 int rc;156 157 151 if (!device) 158 152 return EBADMEM; … … 164 158 } 165 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; 166 172 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 int ret = (instance->hc_fun == NULL) ? ENOMEM : EOK; 174 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI HC function.\n"); 173 175 ddf_fun_set_ops(instance->hc_fun, &hc_ops); 174 176 ddf_fun_data_implant(instance->hc_fun, &instance->hc.generic); 175 177 176 178 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 179 ret = (instance->rh_fun == NULL) ? ENOMEM : EOK; 180 CHECK_RET_DEST_FREE_RETURN(ret, "Failed to create UHCI RH function.\n"); 183 181 ddf_fun_set_ops(instance->rh_fun, &rh_ops); 184 182 ddf_fun_data_implant(instance->rh_fun, &instance->rh); … … 188 186 int irq = 0; 189 187 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 } 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)); 196 192 usb_log_debug("I/O regs at 0x%p (size %zu), IRQ %d.\n", 197 193 (void *) reg_base, reg_size, irq); 198 194 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; 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)); 214 219 215 220 bool interrupts = false; 216 r c= enable_interrupts(device);217 if (r c!= EOK) {221 ret = enable_interrupts(device); 222 if (ret != EOK) { 218 223 usb_log_warning("Failed to enable interrupts: %s." 219 " Falling back to polling.\n", str_error(r c));224 " Falling back to polling.\n", str_error(ret)); 220 225 } else { 221 226 usb_log_debug("Hw interrupts enabled.\n"); … … 223 228 } 224 229 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, 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 250 (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 } 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)); 263 257 264 258 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; 259 #undef CHECK_RET_FINI_RETURN 279 260 } 280 261 /** -
uspace/drv/bus/usb/uhcirh/main.c
rc442f63 rcffa14e6 93 93 size_t io_size = 0; 94 94 uhci_root_hub_t *rh = NULL; 95 int r c;95 int ret = EOK; 96 96 97 rc = hc_get_my_registers(device, &io_regs, &io_size); 98 if (rc != EOK) { 99 usb_log_error( "Failed to get registers from HC: %s.\n", 100 str_error(rc)); 101 return rc; 102 } 97 #define CHECK_RET_FREE_RH_RETURN(ret, message...) \ 98 if (ret != EOK) { \ 99 usb_log_error(message); \ 100 return ret; \ 101 } else (void)0 103 102 103 ret = hc_get_my_registers(device, &io_regs, &io_size); 104 CHECK_RET_FREE_RH_RETURN(ret, 105 "Failed to get registers from HC: %s.\n", str_error(ret)); 104 106 usb_log_debug("I/O regs at %p (size %zuB).\n", 105 107 (void *) io_regs, io_size); 106 108 107 109 rh = ddf_dev_data_alloc(device, sizeof(uhci_root_hub_t)); 108 if (rh == NULL) { 109 usb_log_error("Failed to allocate rh driver instance.\n"); 110 return ENOMEM; 111 } 110 ret = (rh == NULL) ? ENOMEM : EOK; 111 CHECK_RET_FREE_RH_RETURN(ret, 112 "Failed to allocate rh driver instance.\n"); 112 113 113 rc = uhci_root_hub_init(rh, (void*)io_regs, io_size, device); 114 if (rc != EOK) { 115 usb_log_error("Failed(%d) to initialize rh driver instance: " 116 "%s.\n", rc, str_error(rc)); 117 return rc; 118 } 114 ret = uhci_root_hub_init(rh, (void*)io_regs, io_size, device); 115 CHECK_RET_FREE_RH_RETURN(ret, 116 "Failed(%d) to initialize rh driver instance: %s.\n", 117 ret, str_error(ret)); 119 118 120 119 usb_log_info("Controlling root hub '%s' (%" PRIun ").\n", 121 120 ddf_dev_get_name(device), ddf_dev_get_handle(device)); 122 123 121 return EOK; 124 122 } -
uspace/drv/bus/usb/uhcirh/port.c
rc442f63 rcffa14e6 150 150 { 151 151 uhci_port_t *instance = port; 152 int rc;153 152 assert(instance); 154 153 155 154 unsigned allowed_failures = MAX_ERROR_COUNT; 155 #define CHECK_RET_FAIL(ret, msg...) \ 156 if (ret != EOK) { \ 157 usb_log_error(msg); \ 158 if (!(allowed_failures-- > 0)) { \ 159 usb_log_fatal( \ 160 "Maximum number of failures reached, " \ 161 "bailing out.\n"); \ 162 return ret; \ 163 } \ 164 continue; \ 165 } else (void)0 156 166 157 167 while (1) { … … 172 182 instance->id_string, port_status); 173 183 174 rc = usb_hc_connection_open(&instance->hc_connection); 175 if (rc != EOK) { 176 usb_log_error("%s: Failed to connect to HC %s.\n", 177 instance->id_string, str_error(rc)); 178 if (!(allowed_failures-- > 0)) 179 goto fatal_error; 180 continue; 181 } 184 int ret = usb_hc_connection_open(&instance->hc_connection); 185 CHECK_RET_FAIL(ret, "%s: Failed to connect to HC %s.\n", 186 instance->id_string, str_error(ret)); 182 187 183 188 /* Remove any old device */ … … 199 204 } 200 205 201 rc = usb_hc_connection_close(&instance->hc_connection); 202 if (rc != EOK) { 203 usb_log_error("%s: Failed to disconnect from HC %s.\n", 204 instance->id_string, str_error(rc)); 205 if (!(allowed_failures-- > 0)) 206 goto fatal_error; 207 continue; 208 } 209 } 210 211 return EOK; 212 213 fatal_error: 214 usb_log_fatal("Maximum number of failures reached, bailing out.\n"); 215 return rc; 206 ret = usb_hc_connection_close(&instance->hc_connection); 207 CHECK_RET_FAIL(ret, "%s: Failed to disconnect from hc: %s.\n", 208 instance->id_string, str_error(ret)); 209 } 210 return EOK; 216 211 } 217 212
Note:
See TracChangeset
for help on using the changeset viewer.