Changes in uspace/drv/bus/usb/ohci/hc.c [d57122c:65eac7b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
rd57122c r65eac7b 47 47 (I_SO | I_WDH | I_UE | I_RHSC) 48 48 49 static const irq_pio_range_t ohci_pio_ranges[] = { 50 { 51 .base = 0, /* filled later */ 52 .size = sizeof(ohci_regs_t) 53 } 54 }; 55 56 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 }, 49 static const irq_cmd_t ohci_irq_commands[] = 50 { 51 { .cmd = CMD_MEM_READ_32, .dstarg = 1, .addr = NULL /*filled later*/ }, 52 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = 0 /*filled later*/}, 59 53 { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 }, 60 { .cmd = CMD_ PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later*/ },54 { .cmd = CMD_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ }, 61 55 { .cmd = CMD_ACCEPT }, 62 56 }; … … 69 63 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 70 64 /*----------------------------------------------------------------------------*/ 71 /** Get number of PIO ranges used in IRQ code.72 * @return Number of ranges.73 */74 size_t hc_irq_pio_range_count(void)75 {76 return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);77 }78 /*----------------------------------------------------------------------------*/79 /*----------------------------------------------------------------------------*/80 65 /** Get number of commands used in IRQ code. 81 66 * @return Number of commands. … … 86 71 } 87 72 /*----------------------------------------------------------------------------*/ 88 /** Generate IRQ code. 89 * @param[out] ranges PIO ranges buffer. 90 * @param[in] ranges_size Size of the ranges buffer (bytes). 91 * @param[out] cmds Commands buffer. 92 * @param[in] cmds_size Size of the commands buffer (bytes). 73 /** Generate IRQ code commands. 74 * @param[out] cmds Place to store the commands. 75 * @param[in] cmd_size Size of the place (bytes). 93 76 * @param[in] regs Physical address of device's registers. 94 77 * @param[in] reg_size Size of the register area (bytes). … … 96 79 * @return Error code. 97 80 */ 98 int 99 hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[], 100 size_t cmds_size, uintptr_t regs, size_t reg_size) 101 { 102 if ((ranges_size < sizeof(ohci_pio_ranges)) || 103 (cmds_size < sizeof(ohci_irq_commands)) || 104 (reg_size < sizeof(ohci_regs_t))) 81 int hc_get_irq_commands( 82 irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size) 83 { 84 if (cmd_size < sizeof(ohci_irq_commands) 85 || reg_size < sizeof(ohci_regs_t)) 105 86 return EOVERFLOW; 106 87 107 memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges)); 108 ranges[0].base = regs; 88 /* Create register mapping to use in IRQ handler. 89 * This mapping should be present in kernel only. 90 * Remove it from here when kernel knows how to create mappings 91 * and accepts physical addresses in IRQ code. 92 * TODO: remove */ 93 ohci_regs_t *registers; 94 const int ret = pio_enable((void*)regs, reg_size, (void**)®isters); 95 if (ret != EOK) 96 return ret; 97 98 /* Some bogus access to force create mapping. DO NOT remove, 99 * unless whole virtual addresses in irq is replaced 100 * NOTE: Compiler won't remove this as ohci_regs_t members 101 * are declared volatile. 102 * 103 * Introducing CMD_MEM set of IRQ code commands broke 104 * assumption that IRQ code does not cause page faults. 105 * If this happens during idling (THREAD == NULL) 106 * it causes kernel panic. 107 */ 108 registers->revision; 109 109 110 110 memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands)); 111 ohci_regs_t *registers = (ohci_regs_t *) regs; 112 cmds[0].addr = (void *) ®isters->interrupt_status; 113 cmds[3].addr = (void *) ®isters->interrupt_status; 114 111 112 void *address = (void*)®isters->interrupt_status; 113 cmds[0].addr = address; 114 cmds[1].value = OHCI_USED_INTERRUPTS; 115 cmds[3].addr = address; 115 116 return EOK; 116 117 } … … 241 242 switch (ep->transfer_type) { 242 243 case USB_TRANSFER_CONTROL: 243 instance->registers->control &= ~C_CLE;244 OHCI_CLR(instance->registers->control, C_CLE); 244 245 endpoint_list_add_ep(list, ohci_ep); 245 instance->registers->control_current = 0;246 instance->registers->control |= C_CLE;246 OHCI_WR(instance->registers->control_current, 0); 247 OHCI_SET(instance->registers->control, C_CLE); 247 248 break; 248 249 case USB_TRANSFER_BULK: 249 instance->registers->control &= ~C_BLE;250 OHCI_CLR(instance->registers->control, C_BLE); 250 251 endpoint_list_add_ep(list, ohci_ep); 251 instance->registers->control |= C_BLE; 252 OHCI_WR(instance->registers->bulk_current, 0); 253 OHCI_SET(instance->registers->control, C_BLE); 252 254 break; 253 255 case USB_TRANSFER_ISOCHRONOUS: 254 256 case USB_TRANSFER_INTERRUPT: 255 instance->registers->control &= (~C_PLE & ~C_IE);257 OHCI_CLR(instance->registers->control, C_PLE | C_IE); 256 258 endpoint_list_add_ep(list, ohci_ep); 257 instance->registers->control |= C_PLE | C_IE;259 OHCI_SET(instance->registers->control, C_PLE | C_IE); 258 260 break; 259 261 } … … 273 275 switch (ep->transfer_type) { 274 276 case USB_TRANSFER_CONTROL: 275 instance->registers->control &= ~C_CLE;277 OHCI_CLR(instance->registers->control, C_CLE); 276 278 endpoint_list_remove_ep(list, ohci_ep); 277 instance->registers->control_current = 0;278 instance->registers->control |= C_CLE;279 OHCI_WR(instance->registers->control_current, 0); 280 OHCI_SET(instance->registers->control, C_CLE); 279 281 break; 280 282 case USB_TRANSFER_BULK: 281 instance->registers->control &= ~C_BLE;283 OHCI_CLR(instance->registers->control, C_BLE); 282 284 endpoint_list_remove_ep(list, ohci_ep); 283 instance->registers->control |= C_BLE; 285 OHCI_WR(instance->registers->bulk_current, 0); 286 OHCI_SET(instance->registers->control, C_BLE); 284 287 break; 285 288 case USB_TRANSFER_ISOCHRONOUS: 286 289 case USB_TRANSFER_INTERRUPT: 287 instance->registers->control &= (~C_PLE & ~C_IE);290 OHCI_CLR(instance->registers->control, C_PLE | C_IE); 288 291 endpoint_list_remove_ep(list, ohci_ep); 289 instance->registers->control |= C_PLE | C_IE;292 OHCI_SET(instance->registers->control, C_PLE | C_IE); 290 293 break; 291 294 default: … … 308 311 /* Check for root hub communication */ 309 312 if (batch->ep->address == instance->rh.address) { 313 usb_log_debug("OHCI root hub request.\n"); 310 314 rh_request(&instance->rh, batch); 311 315 return EOK; … … 323 327 { 324 328 case USB_TRANSFER_CONTROL: 325 instance->registers->command_status |= CS_CLF;329 OHCI_SET(instance->registers->command_status, CS_CLF); 326 330 break; 327 331 case USB_TRANSFER_BULK: 328 instance->registers->command_status |= CS_BLF;332 OHCI_SET(instance->registers->command_status, CS_BLF); 329 333 break; 330 334 default: … … 342 346 void hc_interrupt(hc_t *instance, uint32_t status) 343 347 { 348 status = ohci_reg2host(status); 344 349 assert(instance); 345 350 if ((status & ~I_SF) == 0) /* ignore sof status */ … … 352 357 fibril_mutex_lock(&instance->guard); 353 358 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca, 354 instance->registers->hcca,359 OHCI_RD(instance->registers->hcca), 355 360 (void *) addr_to_phys(instance->hcca)); 356 361 usb_log_debug2("Periodic current: %#" PRIx32 ".\n", 357 instance->registers->periodic_current);362 OHCI_RD(instance->registers->periodic_current)); 358 363 359 364 link_t *current = list_first(&instance->pending_batches); … … 410 415 411 416 usb_log_debug("Requesting OHCI control.\n"); 412 if ( instance->registers->revision& R_LEGACY_FLAG) {417 if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) { 413 418 /* Turn off legacy emulation, it should be enough to zero 414 419 * the lowest bit, but it caused problems. Thus clear all … … 419 424 (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET); 420 425 usb_log_debug("OHCI legacy register %p: %x.\n", 421 ohci_emulation_reg, *ohci_emulation_reg);426 ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg)); 422 427 /* Zero everything but A20State */ 423 *ohci_emulation_reg &= 0x100;428 OHCI_CLR(*ohci_emulation_reg, ~0x100); 424 429 usb_log_debug( 425 430 "OHCI legacy register (should be 0 or 0x100) %p: %x.\n", 426 ohci_emulation_reg, *ohci_emulation_reg);431 ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg)); 427 432 } 428 433 429 434 /* Interrupt routing enabled => smm driver is active */ 430 if ( instance->registers->control& C_IR) {435 if (OHCI_RD(instance->registers->control) & C_IR) { 431 436 usb_log_debug("SMM driver: request ownership change.\n"); 432 instance->registers->command_status |= CS_OCR;437 OHCI_SET(instance->registers->command_status, CS_OCR); 433 438 /* Hope that SMM actually knows its stuff or we can hang here */ 434 while ( instance->registers->control & C_IR) {439 while (OHCI_RD(instance->registers->control & C_IR)) { 435 440 async_usleep(1000); 436 441 } … … 440 445 return; 441 446 } 442 443 447 const unsigned hc_status = C_HCFS_GET(instance->registers->control); 444 448 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ … … 449 453 return; 450 454 } 451 /* HC is suspended assert resume for 20ms ,*/455 /* HC is suspended assert resume for 20ms */ 452 456 C_HCFS_SET(instance->registers->control, C_HCFS_RESUME); 453 457 async_usleep(20000); … … 473 477 474 478 /* Save contents of fm_interval register */ 475 const uint32_t fm_interval = instance->registers->fm_interval;479 const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval); 476 480 usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval); 477 481 … … 479 483 usb_log_debug2("HC reset.\n"); 480 484 size_t time = 0; 481 instance->registers->command_status = CS_HCR;482 while ( instance->registers->command_status& CS_HCR) {485 OHCI_WR(instance->registers->command_status, CS_HCR); 486 while (OHCI_RD(instance->registers->command_status) & CS_HCR) { 483 487 async_usleep(10); 484 488 time += 10; … … 487 491 488 492 /* Restore fm_interval */ 489 instance->registers->fm_interval = fm_interval;490 assert(( instance->registers->command_status& CS_HCR) == 0);493 OHCI_WR(instance->registers->fm_interval, fm_interval); 494 assert((OHCI_RD(instance->registers->command_status) & CS_HCR) == 0); 491 495 492 496 /* hc is now in suspend state */ 493 497 usb_log_debug2("HC should be in suspend state(%x).\n", 494 instance->registers->control);498 OHCI_RD(instance->registers->control)); 495 499 496 500 /* Use HCCA */ 497 instance->registers->hcca = addr_to_phys(instance->hcca);501 OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca)); 498 502 499 503 /* Use queues */ 500 instance->registers->bulk_head =501 instance->lists[USB_TRANSFER_BULK].list_head_pa ;504 OHCI_WR(instance->registers->bulk_head, 505 instance->lists[USB_TRANSFER_BULK].list_head_pa); 502 506 usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n", 503 507 instance->lists[USB_TRANSFER_BULK].list_head, 504 508 instance->lists[USB_TRANSFER_BULK].list_head_pa); 505 509 506 instance->registers->control_head =507 instance->lists[USB_TRANSFER_CONTROL].list_head_pa ;510 OHCI_WR(instance->registers->control_head, 511 instance->lists[USB_TRANSFER_CONTROL].list_head_pa); 508 512 usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n", 509 513 instance->lists[USB_TRANSFER_CONTROL].list_head, … … 511 515 512 516 /* 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);517 OHCI_SET(instance->registers->control, (C_PLE | C_IE | C_CLE | C_BLE)); 518 usb_log_debug("Queues enabled(%x).\n", 519 OHCI_RD(instance->registers->control)); 516 520 517 521 /* 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;522 OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS); 523 usb_log_debug("Enabled interrupts: %x.\n", 524 OHCI_RD(instance->registers->interrupt_enable)); 525 OHCI_WR(instance->registers->interrupt_enable, I_MI); 522 526 523 527 /* 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; 528 const uint32_t frame_length = 529 (fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK; 530 OHCI_WR(instance->registers->periodic_start, 531 ((frame_length / 10) * 9) & PS_MASK << PS_SHIFT); 526 532 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 533 OHCI_RD(instance->registers->periodic_start), 534 OHCI_RD(instance->registers->periodic_start), frame_length); 530 535 C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL); 531 536 usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n", 532 instance->registers->control);537 OHCI_RD(instance->registers->control)); 533 538 } 534 539 /*----------------------------------------------------------------------------*/ … … 591 596 592 597 for (unsigned i = 0; i < 32; ++i) { 593 instance->hcca->int_ep[i] =594 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa ;598 OHCI_WR(instance->hcca->int_ep[i], 599 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 595 600 } 596 601 usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note:
See TracChangeset
for help on using the changeset viewer.