Changes in uspace/drv/bus/usb/ohci/hc.c [9d58539:ea8b91d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
r9d58539 rea8b91d 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 28 29 /** @addtogroup drvusbohcihc 29 30 * @{ … … 32 33 * @brief OHCI Host controller driver routines 33 34 */ 35 34 36 #include <errno.h> 35 37 #include <str_error.h> … … 49 51 static const irq_pio_range_t ohci_pio_ranges[] = { 50 52 { 51 .base = 0, /* filled later */53 .base = 0, 52 54 .size = sizeof(ohci_regs_t) 53 55 } … … 55 57 56 58 static const irq_cmd_t ohci_irq_commands[] = { 57 { .cmd = CMD_PIO_READ_32, .dstarg = 1, .addr = NULL /* filled later */ }, 58 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS }, 59 { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 }, 60 { .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ }, 61 { .cmd = CMD_ACCEPT }, 59 { 60 .cmd = CMD_PIO_READ_32, 61 .dstarg = 1, 62 .addr = NULL 63 }, 64 { 65 .cmd = CMD_AND, 66 .srcarg = 1, 67 .dstarg = 2, 68 .value = 0 69 }, 70 { 71 .cmd = CMD_PREDICATE, 72 .srcarg = 2, 73 .value = 2 74 }, 75 { 76 .cmd = CMD_PIO_WRITE_A_32, 77 .srcarg = 1, 78 .addr = NULL 79 }, 80 { 81 .cmd = CMD_ACCEPT 82 } 62 83 }; 63 84 … … 68 89 static int interrupt_emulator(hc_t *instance); 69 90 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 70 /*----------------------------------------------------------------------------*/ 91 71 92 /** Get number of PIO ranges used in IRQ code. 72 93 * @return Number of ranges. … … 76 97 return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t); 77 98 } 78 /*----------------------------------------------------------------------------*/ 79 /*----------------------------------------------------------------------------*/ 99 80 100 /** Get number of commands used in IRQ code. 81 101 * @return Number of commands. … … 85 105 return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t); 86 106 } 87 /*----------------------------------------------------------------------------*/ 107 88 108 /** Generate IRQ code. 89 109 * @param[out] ranges PIO ranges buffer. … … 112 132 cmds[0].addr = (void *) ®isters->interrupt_status; 113 133 cmds[3].addr = (void *) ®isters->interrupt_status; 134 OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS); 114 135 115 136 return EOK; 116 137 } 117 /*----------------------------------------------------------------------------*/ 138 118 139 /** Announce OHCI root hub to the DDF 119 140 * … … 174 195 #undef CHECK_RET_RELEASE 175 196 } 176 /*----------------------------------------------------------------------------*/ 197 177 198 /** Initialize OHCI hc driver structure 178 199 * … … 227 248 return EOK; 228 249 } 229 /*----------------------------------------------------------------------------*/ 250 230 251 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep) 231 252 { … … 241 262 switch (ep->transfer_type) { 242 263 case USB_TRANSFER_CONTROL: 243 instance->registers->control &= ~C_CLE;264 OHCI_CLR(instance->registers->control, C_CLE); 244 265 endpoint_list_add_ep(list, ohci_ep); 245 instance->registers->control_current = 0;246 instance->registers->control |= C_CLE;266 OHCI_WR(instance->registers->control_current, 0); 267 OHCI_SET(instance->registers->control, C_CLE); 247 268 break; 248 269 case USB_TRANSFER_BULK: 249 instance->registers->control &= ~C_BLE;270 OHCI_CLR(instance->registers->control, C_BLE); 250 271 endpoint_list_add_ep(list, ohci_ep); 251 instance->registers->control |= C_BLE; 272 OHCI_WR(instance->registers->bulk_current, 0); 273 OHCI_SET(instance->registers->control, C_BLE); 252 274 break; 253 275 case USB_TRANSFER_ISOCHRONOUS: 254 276 case USB_TRANSFER_INTERRUPT: 255 instance->registers->control &= (~C_PLE & ~C_IE);277 OHCI_CLR(instance->registers->control, C_PLE | C_IE); 256 278 endpoint_list_add_ep(list, ohci_ep); 257 instance->registers->control |= C_PLE | C_IE;258 break; 259 } 260 } 261 /*----------------------------------------------------------------------------*/ 279 OHCI_SET(instance->registers->control, C_PLE | C_IE); 280 break; 281 } 282 } 283 262 284 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep) 263 285 { … … 273 295 switch (ep->transfer_type) { 274 296 case USB_TRANSFER_CONTROL: 275 instance->registers->control &= ~C_CLE;297 OHCI_CLR(instance->registers->control, C_CLE); 276 298 endpoint_list_remove_ep(list, ohci_ep); 277 instance->registers->control_current = 0;278 instance->registers->control |= C_CLE;299 OHCI_WR(instance->registers->control_current, 0); 300 OHCI_SET(instance->registers->control, C_CLE); 279 301 break; 280 302 case USB_TRANSFER_BULK: 281 instance->registers->control &= ~C_BLE;303 OHCI_CLR(instance->registers->control, C_BLE); 282 304 endpoint_list_remove_ep(list, ohci_ep); 283 instance->registers->control |= C_BLE; 305 OHCI_WR(instance->registers->bulk_current, 0); 306 OHCI_SET(instance->registers->control, C_BLE); 284 307 break; 285 308 case USB_TRANSFER_ISOCHRONOUS: 286 309 case USB_TRANSFER_INTERRUPT: 287 instance->registers->control &= (~C_PLE & ~C_IE);310 OHCI_CLR(instance->registers->control, C_PLE | C_IE); 288 311 endpoint_list_remove_ep(list, ohci_ep); 289 instance->registers->control |= C_PLE | C_IE;312 OHCI_SET(instance->registers->control, C_PLE | C_IE); 290 313 break; 291 314 default: … … 293 316 } 294 317 } 295 /*----------------------------------------------------------------------------*/ 318 296 319 /** Add USB transfer to the schedule. 297 320 * … … 308 331 /* Check for root hub communication */ 309 332 if (batch->ep->address == instance->rh.address) { 333 usb_log_debug("OHCI root hub request.\n"); 310 334 rh_request(&instance->rh, batch); 311 335 return EOK; … … 323 347 { 324 348 case USB_TRANSFER_CONTROL: 325 instance->registers->command_status |= CS_CLF;349 OHCI_SET(instance->registers->command_status, CS_CLF); 326 350 break; 327 351 case USB_TRANSFER_BULK: 328 instance->registers->command_status |= CS_BLF;352 OHCI_SET(instance->registers->command_status, CS_BLF); 329 353 break; 330 354 default: … … 334 358 return EOK; 335 359 } 336 /*----------------------------------------------------------------------------*/ 360 337 361 /** Interrupt handling routine 338 362 * … … 342 366 void hc_interrupt(hc_t *instance, uint32_t status) 343 367 { 368 status = OHCI_RD(status); 344 369 assert(instance); 345 370 if ((status & ~I_SF) == 0) /* ignore sof status */ … … 352 377 fibril_mutex_lock(&instance->guard); 353 378 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca, 354 instance->registers->hcca,379 OHCI_RD(instance->registers->hcca), 355 380 (void *) addr_to_phys(instance->hcca)); 356 381 usb_log_debug2("Periodic current: %#" PRIx32 ".\n", 357 instance->registers->periodic_current);382 OHCI_RD(instance->registers->periodic_current)); 358 383 359 384 link_t *current = list_first(&instance->pending_batches); … … 379 404 380 405 } 381 /*----------------------------------------------------------------------------*/ 406 382 407 /** Check status register regularly 383 408 * … … 397 422 return EOK; 398 423 } 399 /*----------------------------------------------------------------------------*/ 424 400 425 /** Turn off any (BIOS)driver that might be in control of the device. 401 426 * … … 410 435 411 436 usb_log_debug("Requesting OHCI control.\n"); 412 if ( instance->registers->revision& R_LEGACY_FLAG) {437 if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) { 413 438 /* Turn off legacy emulation, it should be enough to zero 414 439 * the lowest bit, but it caused problems. Thus clear all … … 419 444 (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET); 420 445 usb_log_debug("OHCI legacy register %p: %x.\n", 421 ohci_emulation_reg, *ohci_emulation_reg);446 ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg)); 422 447 /* Zero everything but A20State */ 423 *ohci_emulation_reg &= 0x100;448 OHCI_CLR(*ohci_emulation_reg, ~0x100); 424 449 usb_log_debug( 425 450 "OHCI legacy register (should be 0 or 0x100) %p: %x.\n", 426 ohci_emulation_reg, *ohci_emulation_reg);451 ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg)); 427 452 } 428 453 429 454 /* Interrupt routing enabled => smm driver is active */ 430 if ( instance->registers->control& C_IR) {455 if (OHCI_RD(instance->registers->control) & C_IR) { 431 456 usb_log_debug("SMM driver: request ownership change.\n"); 432 instance->registers->command_status |= CS_OCR;457 OHCI_SET(instance->registers->command_status, CS_OCR); 433 458 /* Hope that SMM actually knows its stuff or we can hang here */ 434 while ( instance->registers->control & C_IR) {459 while (OHCI_RD(instance->registers->control & C_IR)) { 435 460 async_usleep(1000); 436 461 } … … 449 474 return; 450 475 } 451 /* HC is suspended assert resume for 20ms ,*/476 /* HC is suspended assert resume for 20ms */ 452 477 C_HCFS_SET(instance->registers->control, C_HCFS_RESUME); 453 478 async_usleep(20000); … … 461 486 async_usleep(50000); 462 487 } 463 /*----------------------------------------------------------------------------*/ 488 464 489 /** OHCI hw initialization routine. 465 490 * … … 473 498 474 499 /* Save contents of fm_interval register */ 475 const uint32_t fm_interval = instance->registers->fm_interval;500 const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval); 476 501 usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval); 477 502 … … 479 504 usb_log_debug2("HC reset.\n"); 480 505 size_t time = 0; 481 instance->registers->command_status = CS_HCR;482 while ( instance->registers->command_status& CS_HCR) {506 OHCI_WR(instance->registers->command_status, CS_HCR); 507 while (OHCI_RD(instance->registers->command_status) & CS_HCR) { 483 508 async_usleep(10); 484 509 time += 10; … … 487 512 488 513 /* Restore fm_interval */ 489 instance->registers->fm_interval = fm_interval;490 assert(( instance->registers->command_status& CS_HCR) == 0);514 OHCI_WR(instance->registers->fm_interval, fm_interval); 515 assert((OHCI_RD(instance->registers->command_status) & CS_HCR) == 0); 491 516 492 517 /* hc is now in suspend state */ 493 518 usb_log_debug2("HC should be in suspend state(%x).\n", 494 instance->registers->control);519 OHCI_RD(instance->registers->control)); 495 520 496 521 /* Use HCCA */ 497 instance->registers->hcca = addr_to_phys(instance->hcca);522 OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca)); 498 523 499 524 /* Use queues */ 500 instance->registers->bulk_head =501 instance->lists[USB_TRANSFER_BULK].list_head_pa ;525 OHCI_WR(instance->registers->bulk_head, 526 instance->lists[USB_TRANSFER_BULK].list_head_pa); 502 527 usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n", 503 528 instance->lists[USB_TRANSFER_BULK].list_head, 504 529 instance->lists[USB_TRANSFER_BULK].list_head_pa); 505 530 506 instance->registers->control_head =507 instance->lists[USB_TRANSFER_CONTROL].list_head_pa ;531 OHCI_WR(instance->registers->control_head, 532 instance->lists[USB_TRANSFER_CONTROL].list_head_pa); 508 533 usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n", 509 534 instance->lists[USB_TRANSFER_CONTROL].list_head, … … 511 536 512 537 /* Enable queues */ 513 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);514 usb_log_debug 2("All queues enabled(%x).\n",515 instance->registers->control);538 OHCI_SET(instance->registers->control, (C_PLE | C_IE | C_CLE | C_BLE)); 539 usb_log_debug("Queues enabled(%x).\n", 540 OHCI_RD(instance->registers->control)); 516 541 517 542 /* Enable interrupts */ 518 instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS;519 usb_log_debug 2("Enabled interrupts: %x.\n",520 instance->registers->interrupt_enable);521 instance->registers->interrupt_enable = I_MI;543 OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS); 544 usb_log_debug("Enabled interrupts: %x.\n", 545 OHCI_RD(instance->registers->interrupt_enable)); 546 OHCI_WR(instance->registers->interrupt_enable, I_MI); 522 547 523 548 /* Set periodic start to 90% */ 524 uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK); 525 instance->registers->periodic_start = (frame_length / 10) * 9; 549 const uint32_t frame_length = 550 (fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK; 551 OHCI_WR(instance->registers->periodic_start, 552 ((frame_length / 10) * 9) & PS_MASK << PS_SHIFT); 526 553 usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n", 527 instance->registers->periodic_start, 528 instance->registers->periodic_start, frame_length); 529 554 OHCI_RD(instance->registers->periodic_start), 555 OHCI_RD(instance->registers->periodic_start), frame_length); 530 556 C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL); 531 557 usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n", 532 instance->registers->control);533 } 534 /*----------------------------------------------------------------------------*/ 558 OHCI_RD(instance->registers->control)); 559 } 560 535 561 /** Initialize schedule queues 536 562 * … … 566 592 return EOK; 567 593 } 568 /*----------------------------------------------------------------------------*/ 594 569 595 /** Initialize memory structures used by the OHCI hcd. 570 596 * … … 587 613 if (instance->hcca == NULL) 588 614 return ENOMEM; 589 bzero(instance->hcca, sizeof(hcca_t));590 615 usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca); 591 616 592 for (unsigned i = 0; i < 32; ++i) {593 instance->hcca->int_ep[i] =594 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa ;617 for (unsigned i = 0; i < HCCA_INT_EP_COUNT; ++i) { 618 hcca_set_int_ep(instance->hcca, i, 619 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 595 620 } 596 621 usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note:
See TracChangeset
for help on using the changeset viewer.