Changes in uspace/drv/bus/usb/ohci/hc.c [76fbd9a:d57122c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
r76fbd9a rd57122c 56 56 static const irq_cmd_t ohci_irq_commands[] = { 57 57 { .cmd = CMD_PIO_READ_32, .dstarg = 1, .addr = NULL /* filled later */ }, 58 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = 0 /* filled later */},58 { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS }, 59 59 { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 }, 60 60 { .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ }, … … 68 68 static int interrupt_emulator(hc_t *instance); 69 69 static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch); 70 70 /*----------------------------------------------------------------------------*/ 71 71 /** Get number of PIO ranges used in IRQ code. 72 72 * @return Number of ranges. … … 76 76 return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t); 77 77 } 78 79 78 /*----------------------------------------------------------------------------*/ 79 /*----------------------------------------------------------------------------*/ 80 80 /** Get number of commands used in IRQ code. 81 81 * @return Number of commands. … … 85 85 return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t); 86 86 } 87 87 /*----------------------------------------------------------------------------*/ 88 88 /** Generate IRQ code. 89 89 * @param[out] ranges PIO ranges buffer. … … 111 111 ohci_regs_t *registers = (ohci_regs_t *) regs; 112 112 cmds[0].addr = (void *) ®isters->interrupt_status; 113 cmds[1].value = OHCI_USED_INTERRUPTS;114 113 cmds[3].addr = (void *) ®isters->interrupt_status; 115 114 116 115 return EOK; 117 116 } 118 117 /*----------------------------------------------------------------------------*/ 119 118 /** Announce OHCI root hub to the DDF 120 119 * … … 175 174 #undef CHECK_RET_RELEASE 176 175 } 177 176 /*----------------------------------------------------------------------------*/ 178 177 /** Initialize OHCI hc driver structure 179 178 * … … 228 227 return EOK; 229 228 } 230 229 /*----------------------------------------------------------------------------*/ 231 230 void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep) 232 231 { … … 242 241 switch (ep->transfer_type) { 243 242 case USB_TRANSFER_CONTROL: 244 OHCI_CLR(instance->registers->control, C_CLE);243 instance->registers->control &= ~C_CLE; 245 244 endpoint_list_add_ep(list, ohci_ep); 246 OHCI_WR(instance->registers->control_current, 0);247 OHCI_SET(instance->registers->control, C_CLE);245 instance->registers->control_current = 0; 246 instance->registers->control |= C_CLE; 248 247 break; 249 248 case USB_TRANSFER_BULK: 250 OHCI_CLR(instance->registers->control, C_BLE);249 instance->registers->control &= ~C_BLE; 251 250 endpoint_list_add_ep(list, ohci_ep); 252 OHCI_WR(instance->registers->bulk_current, 0); 253 OHCI_SET(instance->registers->control, C_BLE); 251 instance->registers->control |= C_BLE; 254 252 break; 255 253 case USB_TRANSFER_ISOCHRONOUS: 256 254 case USB_TRANSFER_INTERRUPT: 257 OHCI_CLR(instance->registers->control, C_PLE |C_IE);255 instance->registers->control &= (~C_PLE & ~C_IE); 258 256 endpoint_list_add_ep(list, ohci_ep); 259 OHCI_SET(instance->registers->control, C_PLE | C_IE);260 break; 261 } 262 } 263 257 instance->registers->control |= C_PLE | C_IE; 258 break; 259 } 260 } 261 /*----------------------------------------------------------------------------*/ 264 262 void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep) 265 263 { … … 275 273 switch (ep->transfer_type) { 276 274 case USB_TRANSFER_CONTROL: 277 OHCI_CLR(instance->registers->control, C_CLE);275 instance->registers->control &= ~C_CLE; 278 276 endpoint_list_remove_ep(list, ohci_ep); 279 OHCI_WR(instance->registers->control_current, 0);280 OHCI_SET(instance->registers->control, C_CLE);277 instance->registers->control_current = 0; 278 instance->registers->control |= C_CLE; 281 279 break; 282 280 case USB_TRANSFER_BULK: 283 OHCI_CLR(instance->registers->control, C_BLE);281 instance->registers->control &= ~C_BLE; 284 282 endpoint_list_remove_ep(list, ohci_ep); 285 OHCI_WR(instance->registers->bulk_current, 0); 286 OHCI_SET(instance->registers->control, C_BLE); 283 instance->registers->control |= C_BLE; 287 284 break; 288 285 case USB_TRANSFER_ISOCHRONOUS: 289 286 case USB_TRANSFER_INTERRUPT: 290 OHCI_CLR(instance->registers->control, C_PLE |C_IE);287 instance->registers->control &= (~C_PLE & ~C_IE); 291 288 endpoint_list_remove_ep(list, ohci_ep); 292 OHCI_SET(instance->registers->control, C_PLE | C_IE);289 instance->registers->control |= C_PLE | C_IE; 293 290 break; 294 291 default: … … 296 293 } 297 294 } 298 295 /*----------------------------------------------------------------------------*/ 299 296 /** Add USB transfer to the schedule. 300 297 * … … 311 308 /* Check for root hub communication */ 312 309 if (batch->ep->address == instance->rh.address) { 313 usb_log_debug("OHCI root hub request.\n");314 310 rh_request(&instance->rh, batch); 315 311 return EOK; … … 327 323 { 328 324 case USB_TRANSFER_CONTROL: 329 OHCI_SET(instance->registers->command_status, CS_CLF);325 instance->registers->command_status |= CS_CLF; 330 326 break; 331 327 case USB_TRANSFER_BULK: 332 OHCI_SET(instance->registers->command_status, CS_BLF);328 instance->registers->command_status |= CS_BLF; 333 329 break; 334 330 default: … … 338 334 return EOK; 339 335 } 340 336 /*----------------------------------------------------------------------------*/ 341 337 /** Interrupt handling routine 342 338 * … … 346 342 void hc_interrupt(hc_t *instance, uint32_t status) 347 343 { 348 status = ohci_reg2host(status);349 344 assert(instance); 350 345 if ((status & ~I_SF) == 0) /* ignore sof status */ … … 357 352 fibril_mutex_lock(&instance->guard); 358 353 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca, 359 OHCI_RD(instance->registers->hcca),354 instance->registers->hcca, 360 355 (void *) addr_to_phys(instance->hcca)); 361 356 usb_log_debug2("Periodic current: %#" PRIx32 ".\n", 362 OHCI_RD(instance->registers->periodic_current));357 instance->registers->periodic_current); 363 358 364 359 link_t *current = list_first(&instance->pending_batches); … … 384 379 385 380 } 386 381 /*----------------------------------------------------------------------------*/ 387 382 /** Check status register regularly 388 383 * … … 402 397 return EOK; 403 398 } 404 399 /*----------------------------------------------------------------------------*/ 405 400 /** Turn off any (BIOS)driver that might be in control of the device. 406 401 * … … 415 410 416 411 usb_log_debug("Requesting OHCI control.\n"); 417 if ( OHCI_RD(instance->registers->revision)& R_LEGACY_FLAG) {412 if (instance->registers->revision & R_LEGACY_FLAG) { 418 413 /* Turn off legacy emulation, it should be enough to zero 419 414 * the lowest bit, but it caused problems. Thus clear all … … 424 419 (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET); 425 420 usb_log_debug("OHCI legacy register %p: %x.\n", 426 ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));421 ohci_emulation_reg, *ohci_emulation_reg); 427 422 /* Zero everything but A20State */ 428 OHCI_CLR(*ohci_emulation_reg, ~0x100);423 *ohci_emulation_reg &= 0x100; 429 424 usb_log_debug( 430 425 "OHCI legacy register (should be 0 or 0x100) %p: %x.\n", 431 ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));426 ohci_emulation_reg, *ohci_emulation_reg); 432 427 } 433 428 434 429 /* Interrupt routing enabled => smm driver is active */ 435 if ( OHCI_RD(instance->registers->control)& C_IR) {430 if (instance->registers->control & C_IR) { 436 431 usb_log_debug("SMM driver: request ownership change.\n"); 437 OHCI_SET(instance->registers->command_status, CS_OCR);432 instance->registers->command_status |= CS_OCR; 438 433 /* Hope that SMM actually knows its stuff or we can hang here */ 439 while ( OHCI_RD(instance->registers->control & C_IR)) {434 while (instance->registers->control & C_IR) { 440 435 async_usleep(1000); 441 436 } … … 445 440 return; 446 441 } 442 447 443 const unsigned hc_status = C_HCFS_GET(instance->registers->control); 448 444 /* Interrupt routing disabled && status != USB_RESET => BIOS active */ … … 453 449 return; 454 450 } 455 /* HC is suspended assert resume for 20ms */451 /* HC is suspended assert resume for 20ms, */ 456 452 C_HCFS_SET(instance->registers->control, C_HCFS_RESUME); 457 453 async_usleep(20000); … … 465 461 async_usleep(50000); 466 462 } 467 463 /*----------------------------------------------------------------------------*/ 468 464 /** OHCI hw initialization routine. 469 465 * … … 477 473 478 474 /* Save contents of fm_interval register */ 479 const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);475 const uint32_t fm_interval = instance->registers->fm_interval; 480 476 usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval); 481 477 … … 483 479 usb_log_debug2("HC reset.\n"); 484 480 size_t time = 0; 485 OHCI_WR(instance->registers->command_status, CS_HCR);486 while ( OHCI_RD(instance->registers->command_status)& CS_HCR) {481 instance->registers->command_status = CS_HCR; 482 while (instance->registers->command_status & CS_HCR) { 487 483 async_usleep(10); 488 484 time += 10; … … 491 487 492 488 /* Restore fm_interval */ 493 OHCI_WR(instance->registers->fm_interval, fm_interval);494 assert(( OHCI_RD(instance->registers->command_status)& CS_HCR) == 0);489 instance->registers->fm_interval = fm_interval; 490 assert((instance->registers->command_status & CS_HCR) == 0); 495 491 496 492 /* hc is now in suspend state */ 497 493 usb_log_debug2("HC should be in suspend state(%x).\n", 498 OHCI_RD(instance->registers->control));494 instance->registers->control); 499 495 500 496 /* Use HCCA */ 501 OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca));497 instance->registers->hcca = addr_to_phys(instance->hcca); 502 498 503 499 /* Use queues */ 504 OHCI_WR(instance->registers->bulk_head,505 instance->lists[USB_TRANSFER_BULK].list_head_pa );500 instance->registers->bulk_head = 501 instance->lists[USB_TRANSFER_BULK].list_head_pa; 506 502 usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n", 507 503 instance->lists[USB_TRANSFER_BULK].list_head, 508 504 instance->lists[USB_TRANSFER_BULK].list_head_pa); 509 505 510 OHCI_WR(instance->registers->control_head,511 instance->lists[USB_TRANSFER_CONTROL].list_head_pa );506 instance->registers->control_head = 507 instance->lists[USB_TRANSFER_CONTROL].list_head_pa; 512 508 usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n", 513 509 instance->lists[USB_TRANSFER_CONTROL].list_head, … … 515 511 516 512 /* Enable queues */ 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));513 instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE); 514 usb_log_debug2("All queues enabled(%x).\n", 515 instance->registers->control); 520 516 521 517 /* Enable interrupts */ 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);518 instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS; 519 usb_log_debug2("Enabled interrupts: %x.\n", 520 instance->registers->interrupt_enable); 521 instance->registers->interrupt_enable = I_MI; 526 522 527 523 /* Set periodic start to 90% */ 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); 524 uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK); 525 instance->registers->periodic_start = (frame_length / 10) * 9; 532 526 usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n", 533 OHCI_RD(instance->registers->periodic_start), 534 OHCI_RD(instance->registers->periodic_start), frame_length); 527 instance->registers->periodic_start, 528 instance->registers->periodic_start, frame_length); 529 535 530 C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL); 536 531 usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n", 537 OHCI_RD(instance->registers->control));538 } 539 532 instance->registers->control); 533 } 534 /*----------------------------------------------------------------------------*/ 540 535 /** Initialize schedule queues 541 536 * … … 571 566 return EOK; 572 567 } 573 568 /*----------------------------------------------------------------------------*/ 574 569 /** Initialize memory structures used by the OHCI hcd. 575 570 * … … 596 591 597 592 for (unsigned i = 0; i < 32; ++i) { 598 OHCI_WR(instance->hcca->int_ep[i],599 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa );593 instance->hcca->int_ep[i] = 594 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa; 600 595 } 601 596 usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note:
See TracChangeset
for help on using the changeset viewer.