Changeset 32fb6bce in mainline for uspace/drv/bus/usb/ohci
- Timestamp:
- 2017-12-18T22:50:21Z (8 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7f70d1c
- Parents:
- 1ea0bbf
- git-author:
- Ondřej Hlavatý <aearsis@…> (2017-12-18 22:04:50)
- git-committer:
- Ondřej Hlavatý <aearsis@…> (2017-12-18 22:50:21)
- Location:
- uspace/drv/bus/usb/ohci
- Files:
-
- 5 edited
-
hc.c (modified) (19 diffs)
-
hc.h (modified) (3 diffs)
-
main.c (modified) (2 diffs)
-
ohci_bus.c (modified) (2 diffs)
-
ohci_bus.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
r1ea0bbf r32fb6bce 101 101 * @return Error code. 102 102 */ 103 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res)103 int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 104 104 { 105 105 assert(code); … … 149 149 * @return Error code 150 150 */ 151 int hc_ init(hc_t *instance, const hw_res_list_parsed_t *hw_res)152 { 153 assert(instance);151 int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res) 152 { 153 hc_t *instance = hcd_to_hc(hcd); 154 154 assert(hw_res); 155 155 if (hw_res->mem_ranges.count != 1 || … … 186 186 * @param[in] instance Host controller structure to use. 187 187 */ 188 void hc_fini(hc_t *instance)188 int hc_gone(hc_device_t *instance) 189 189 { 190 190 assert(instance); 191 191 /* TODO: implement*/ 192 }; 192 return ENOTSUP; 193 } 193 194 194 195 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep) … … 260 261 } 261 262 262 int ohci_hc_status( hcd_t *hcd, uint32_t *status)263 { 264 assert( hcd);263 int ohci_hc_status(bus_t *bus_base, uint32_t *status) 264 { 265 assert(bus_base); 265 266 assert(status); 266 hc_t *instance = hcd_get_driver_data(hcd); 267 assert(instance); 268 269 if (instance->registers){ 270 *status = OHCI_RD(instance->registers->interrupt_status); 271 OHCI_WR(instance->registers->interrupt_status, *status); 267 268 ohci_bus_t *bus = (ohci_bus_t *) bus_base; 269 hc_t *hc = bus->hc; 270 assert(hc); 271 272 if (hc->registers){ 273 *status = OHCI_RD(hc->registers->interrupt_status); 274 OHCI_WR(hc->registers->interrupt_status, *status); 272 275 } 273 276 return EOK; … … 280 283 * @return Error code. 281 284 */ 282 int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch) 283 { 284 assert(hcd); 285 hc_t *instance = hcd_get_driver_data(hcd); 286 assert(instance); 285 int ohci_hc_schedule(usb_transfer_batch_t *batch) 286 { 287 assert(batch); 288 289 ohci_bus_t *bus = (ohci_bus_t *) endpoint_get_bus(batch->ep); 290 hc_t *hc = bus->hc; 291 assert(hc); 287 292 288 293 /* Check for root hub communication */ 289 if (batch->target.address == ohci_rh_get_address(& instance->rh)) {294 if (batch->target.address == ohci_rh_get_address(&hc->rh)) { 290 295 usb_log_debug("OHCI root hub request.\n"); 291 return ohci_rh_schedule(& instance->rh, batch);296 return ohci_rh_schedule(&hc->rh, batch); 292 297 } 293 298 ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch); … … 299 304 return err; 300 305 301 fibril_mutex_lock(& instance->guard);302 list_append(&ohci_batch->link, & instance->pending_batches);306 fibril_mutex_lock(&hc->guard); 307 list_append(&ohci_batch->link, &hc->pending_batches); 303 308 ohci_transfer_batch_commit(ohci_batch); 304 309 … … 307 312 { 308 313 case USB_TRANSFER_CONTROL: 309 OHCI_SET( instance->registers->command_status, CS_CLF);314 OHCI_SET(hc->registers->command_status, CS_CLF); 310 315 break; 311 316 case USB_TRANSFER_BULK: 312 OHCI_SET( instance->registers->command_status, CS_BLF);317 OHCI_SET(hc->registers->command_status, CS_BLF); 313 318 break; 314 319 default: 315 320 break; 316 321 } 317 fibril_mutex_unlock(& instance->guard);322 fibril_mutex_unlock(&hc->guard); 318 323 return EOK; 319 324 } … … 324 329 * @param[in] status Value of the status register at the time of interrupt. 325 330 */ 326 void ohci_hc_interrupt(hcd_t *hcd, uint32_t status) 327 { 328 assert(hcd); 329 hc_t *instance = hcd_get_driver_data(hcd); 331 void ohci_hc_interrupt(bus_t *bus_base, uint32_t status) 332 { 333 assert(bus_base); 334 335 ohci_bus_t *bus = (ohci_bus_t *) bus_base; 336 hc_t *hc = bus->hc; 337 assert(hc); 338 330 339 status = OHCI_RD(status); 331 assert( instance);340 assert(hc); 332 341 if ((status & ~I_SF) == 0) /* ignore sof status */ 333 342 return; 334 usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);343 usb_log_debug2("OHCI(%p) interrupt: %x.\n", hc, status); 335 344 if (status & I_RHSC) 336 ohci_rh_interrupt(& instance->rh);345 ohci_rh_interrupt(&hc->rh); 337 346 338 347 if (status & I_WDH) { 339 fibril_mutex_lock(& instance->guard);340 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,341 OHCI_RD( instance->registers->hcca),342 (void *) addr_to_phys( instance->hcca));348 fibril_mutex_lock(&hc->guard); 349 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", hc->hcca, 350 OHCI_RD(hc->registers->hcca), 351 (void *) addr_to_phys(hc->hcca)); 343 352 usb_log_debug2("Periodic current: %#" PRIx32 ".\n", 344 OHCI_RD( instance->registers->periodic_current));345 346 link_t *current = list_first(& instance->pending_batches);347 while (current && current != & instance->pending_batches.head) {353 OHCI_RD(hc->registers->periodic_current)); 354 355 link_t *current = list_first(&hc->pending_batches); 356 while (current && current != &hc->pending_batches.head) { 348 357 link_t *next = current->next; 349 358 ohci_transfer_batch_t *batch = … … 357 366 current = next; 358 367 } 359 fibril_mutex_unlock(& instance->guard);368 fibril_mutex_unlock(&hc->guard); 360 369 } 361 370 362 371 if (status & I_UE) { 363 372 usb_log_fatal("Error like no other!\n"); 364 hc_start( instance);373 hc_start(&hc->base); 365 374 } 366 375 … … 374 383 * @param[in] instance OHCI hc driver structure. 375 384 */ 376 void hc_gain_control(hc_t *instance)377 { 378 assert(instance);385 int hc_gain_control(hc_device_t *hcd) 386 { 387 hc_t *instance = hcd_to_hc(hcd); 379 388 380 389 usb_log_debug("Requesting OHCI control.\n"); … … 409 418 C_HCFS_SET(instance->registers->control, C_HCFS_RESET); 410 419 async_usleep(50000); 411 return ;420 return EOK; 412 421 } 413 422 … … 418 427 if (hc_status == C_HCFS_OPERATIONAL) { 419 428 usb_log_info("BIOS driver: HC operational.\n"); 420 return ;429 return EOK; 421 430 } 422 431 /* HC is suspended assert resume for 20ms */ … … 424 433 async_usleep(20000); 425 434 usb_log_info("BIOS driver: HC resumed.\n"); 426 return ;435 return EOK; 427 436 } 428 437 … … 431 440 usb_log_debug("Host controller found in reset state.\n"); 432 441 async_usleep(50000); 442 return EOK; 433 443 } 434 444 … … 437 447 * @param[in] instance OHCI hc driver structure. 438 448 */ 439 void hc_start(hc_t *instance) 440 { 449 int hc_start(hc_device_t *hcd) 450 { 451 hc_t *instance = hcd_to_hc(hcd); 441 452 ohci_rh_init(&instance->rh, instance->registers, "ohci rh"); 442 453 … … 489 500 490 501 /* Enable interrupts */ 491 if (instance-> hw_interrupts) {502 if (instance->base.irq_cap >= 0) { 492 503 OHCI_WR(instance->registers->interrupt_enable, 493 504 OHCI_USED_INTERRUPTS); … … 508 519 usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n", 509 520 OHCI_RD(instance->registers->control)); 521 522 return EOK; 510 523 } 511 524 … … 555 568 memset(&instance->rh, 0, sizeof(instance->rh)); 556 569 /* Init queues */ 557 constint ret = hc_init_transfer_lists(instance);570 int ret = hc_init_transfer_lists(instance); 558 571 if (ret != EOK) { 559 572 return ret; … … 574 587 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 575 588 589 if ((ret = ohci_bus_init(&instance->bus, instance))) { 590 usb_log_error("HC(%p): Failed to setup bus : %s", 591 instance, str_error(ret)); 592 return ret; 593 } 594 595 hc_device_setup(&instance->base, (bus_t *) &instance->bus); 596 576 597 return EOK; 577 598 } -
uspace/drv/bus/usb/ohci/hc.h
r1ea0bbf r32fb6bce 58 58 /** Main OHCI driver structure */ 59 59 typedef struct hc { 60 /** Common hcd header */ 61 hc_device_t base; 62 60 63 /** Memory mapped I/O registers area */ 61 64 ohci_regs_t *registers; … … 70 73 list_t pending_batches; 71 74 72 /** Fibril for periodic checks if interrupts can't be used */73 fid_t interrupt_emulator;74 75 75 /** Guards schedule and endpoint manipulation */ 76 76 fibril_mutex_t guard; 77 78 /** interrupts available */79 bool hw_interrupts;80 77 81 78 /** USB hub emulation structure */ … … 86 83 } hc_t; 87 84 88 extern int hc_init(hc_t *, const hw_res_list_parsed_t *); 89 extern void hc_gain_control(hc_t *instance); 90 extern void hc_start(hc_t *instance); 91 extern void hc_fini(hc_t *); 85 static inline hc_t * hcd_to_hc(hc_device_t *hcd) 86 { 87 assert(hcd); 88 return (hc_t *) hcd; 89 } 90 91 extern int hc_add(hc_device_t *, const hw_res_list_parsed_t *); 92 extern int hc_gen_irq_code(irq_code_t *, hc_device_t *, const hw_res_list_parsed_t *); 93 extern int hc_gain_control(hc_device_t *); 94 extern int hc_start(hc_device_t *); 95 extern int hc_gone(hc_device_t *); 92 96 93 97 extern void hc_enqueue_endpoint(hc_t *, const endpoint_t *); 94 98 extern void hc_dequeue_endpoint(hc_t *, const endpoint_t *); 95 99 96 int ohci_hc_gen_irq_code(irq_code_t *code, hcd_t *hcd, const hw_res_list_parsed_t *hw_res); 97 98 extern void ohci_hc_interrupt(hcd_t *, uint32_t); 99 extern int ohci_hc_status(hcd_t *, uint32_t *); 100 extern int ohci_hc_schedule(hcd_t *, usb_transfer_batch_t *); 100 extern int ohci_hc_schedule(usb_transfer_batch_t *); 101 extern int ohci_hc_status(bus_t *, uint32_t *); 102 extern void ohci_hc_interrupt(bus_t *, uint32_t); 101 103 102 104 #endif -
uspace/drv/bus/usb/ohci/main.c
r1ea0bbf r32fb6bce 48 48 49 49 #define NAME "ohci" 50 static int ohci_driver_init(hcd_t *, const hw_res_list_parsed_t *, ddf_dev_t *);51 static int ohci_driver_start(hcd_t *, bool);52 static int ohci_driver_claim(hcd_t *, ddf_dev_t *);53 static void ohci_driver_fini(hcd_t *);54 50 55 static const ddf_hc_driver_t ohci_hc_driver = { 56 .irq_code_gen = ohci_hc_gen_irq_code, 57 .init = ohci_driver_init, 58 .claim = ohci_driver_claim, 59 .start = ohci_driver_start, 51 static const hc_driver_t ohci_driver = { 52 .name = NAME, 53 .hc_device_size = sizeof(hc_t), 54 55 .hc_add = hc_add, 56 .irq_code_gen = hc_gen_irq_code, 57 .claim = hc_gain_control, 58 .start = hc_start, 60 59 .setup_root_hub = hcd_setup_virtual_root_hub, 61 .fini = ohci_driver_fini, 62 .name = "OHCI", 63 .ops = { 64 .schedule = ohci_hc_schedule, 65 .irq_hook = ohci_hc_interrupt, 66 .status_hook = ohci_hc_status, 67 }, 68 }; 69 70 71 static int ohci_driver_init(hcd_t *hcd, const hw_res_list_parsed_t *res, ddf_dev_t *device) 72 { 73 int err; 74 75 assert(hcd); 76 assert(hcd_get_driver_data(hcd) == NULL); 77 78 hc_t *instance = malloc(sizeof(hc_t)); 79 if (!instance) 80 return ENOMEM; 81 82 if ((err = hc_init(instance, res)) != EOK) 83 goto err; 84 85 if ((err = ohci_bus_init(&instance->bus, hcd, instance))) 86 goto err; 87 88 hcd_set_implementation(hcd, instance, &ohci_hc_driver.ops, &instance->bus.base.base); 89 90 return EOK; 91 92 err: 93 free(instance); 94 return err; 95 } 96 97 static int ohci_driver_claim(hcd_t *hcd, ddf_dev_t *dev) 98 { 99 hc_t *hc = hcd_get_driver_data(hcd); 100 assert(hc); 101 102 hc_gain_control(hc); 103 104 return EOK; 105 } 106 107 static int ohci_driver_start(hcd_t *hcd, bool interrupts) 108 { 109 hc_t *hc = hcd_get_driver_data(hcd); 110 assert(hc); 111 112 hc->hw_interrupts = interrupts; 113 hc_start(hc); 114 return EOK; 115 } 116 117 static void ohci_driver_fini(hcd_t *hcd) 118 { 119 assert(hcd); 120 hc_t *hc = hcd_get_driver_data(hcd); 121 if (hc) 122 hc_fini(hc); 123 124 hcd_set_implementation(hcd, NULL, NULL, NULL); 125 free(hc); 126 } 127 128 /** Initializes a new ddf driver instance of OHCI hcd. 129 * 130 * @param[in] device DDF instance of the device to initialize. 131 * @return Error code. 132 */ 133 static int ohci_dev_add(ddf_dev_t *device) 134 { 135 usb_log_debug("ohci_dev_add() called\n"); 136 assert(device); 137 return hcd_ddf_add_hc(device, &ohci_hc_driver); 138 } 139 140 static int ohci_fun_online(ddf_fun_t *fun) 141 { 142 return hcd_ddf_device_online(fun); 143 } 144 145 static int ohci_fun_offline(ddf_fun_t *fun) 146 { 147 return hcd_ddf_device_offline(fun); 148 } 149 150 151 static const driver_ops_t ohci_driver_ops = { 152 .dev_add = ohci_dev_add, 153 .fun_online = ohci_fun_online, 154 .fun_offline = ohci_fun_offline 155 }; 156 157 static const driver_t ohci_driver = { 158 .name = NAME, 159 .driver_ops = &ohci_driver_ops 60 .hc_gone = hc_gone, 160 61 }; 161 62 … … 171 72 { 172 73 log_init(NAME); 173 return ddf_driver_main(&ohci_driver);74 return hc_driver_main(&ohci_driver); 174 75 } 175 76 -
uspace/drv/bus/usb/ohci/ohci_bus.c
r1ea0bbf r32fb6bce 158 158 .parent = &usb2_bus_ops, 159 159 160 .interrupt = ohci_hc_interrupt, 161 .status = ohci_hc_status, 162 160 163 .endpoint_destroy = ohci_endpoint_destroy, 161 164 .endpoint_create = ohci_endpoint_create, … … 167 170 .batch_create = ohci_create_batch, 168 171 .batch_destroy = ohci_destroy_batch, 172 .batch_schedule = ohci_hc_schedule, 169 173 }; 170 174 171 175 172 int ohci_bus_init(ohci_bus_t *bus, hc d_t *hcd, hc_t *hc)176 int ohci_bus_init(ohci_bus_t *bus, hc_t *hc) 173 177 { 174 178 assert(hc); 175 179 assert(bus); 176 180 177 178 181 usb2_bus_t *usb2_bus = (usb2_bus_t *) bus; 179 182 bus_t *bus_base = (bus_t *) bus; 180 183 181 usb2_bus_init(usb2_bus, hcd,BANDWIDTH_AVAILABLE_USB11);184 usb2_bus_init(usb2_bus, BANDWIDTH_AVAILABLE_USB11); 182 185 bus_base->ops = &ohci_bus_ops; 183 186 -
uspace/drv/bus/usb/ohci/ohci_bus.h
r1ea0bbf r32fb6bce 62 62 } ohci_bus_t; 63 63 64 int ohci_bus_init(ohci_bus_t *, hc d_t *, hc_t *);64 int ohci_bus_init(ohci_bus_t *, hc_t *); 65 65 66 66 /** Get and convert assigned ohci_endpoint_t structure
Note:
See TracChangeset
for help on using the changeset viewer.
