Changes in uspace/drv/bus/usb/ohci/root_hub.c [827ec41:76fbd9a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/root_hub.c
r827ec41 r76fbd9a 33 33 */ 34 34 #include <assert.h> 35 #include <byteorder.h> 35 36 #include <errno.h> 36 37 #include <str_error.h> 37 38 #include <fibril_synch.h> 38 39 40 #include <usb/usb.h> 39 41 #include <usb/debug.h> 40 42 #include <usb/dev/request.h> 41 43 #include <usb/classes/hub.h> 42 44 43 #include "root_hub.h"44 45 #include <usb/classes/classes.h> 45 46 #include <usb/classes/hub.h> 46 47 #include <usb/dev/driver.h> 47 48 #include "ohci_regs.h" 49 #include "root_hub.h" 48 50 49 51 /** … … 122 124 { 123 125 assert(request); 126 usb_log_debug("Sending interrupt vector(%zu) %hhx:%hhx.\n", 127 size, ((uint8_t*)&mask)[0], ((uint8_t*)&mask)[1]); 124 128 usb_transfer_batch_finish_error(request, &mask, size, EOK); 125 129 usb_transfer_batch_destroy(request); … … 150 154 151 155 instance->registers = regs; 152 instance->port_count = 153 (instance->registers->rh_desc_a >> RHDA_NDS_SHIFT) & RHDA_NDS_MASK;156 instance->port_count = OHCI_RD(regs->rh_desc_a) & RHDA_NDS_MASK; 157 usb_log_debug2("rh_desc_a: %x.\n", OHCI_RD(regs->rh_desc_a)); 154 158 if (instance->port_count > 15) { 155 159 usb_log_warning("OHCI specification does not allow more than 15" … … 163 167 164 168 #if defined OHCI_POWER_SWITCH_no 169 usb_log_debug("OHCI rh: Set power mode to no power switching.\n"); 165 170 /* Set port power mode to no power-switching. (always on) */ 166 instance->registers->rh_desc_a |= RHDA_NPS_FLAG;171 OHCI_SET(regs->rh_desc_a, RHDA_NPS_FLAG); 167 172 168 173 /* Set to no over-current reporting */ 169 instance->registers->rh_desc_a |= RHDA_NOCP_FLAG;174 OHCI_SET(regs->rh_desc_a, RHDA_NOCP_FLAG); 170 175 171 176 #elif defined OHCI_POWER_SWITCH_ganged 172 /* Set port power mode to no ganged power-switching. */ 173 instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG; 174 instance->registers->rh_desc_a &= ~RHDA_PSM_FLAG; 175 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 177 usb_log_debug("OHCI rh: Set power mode to ganged power switching.\n"); 178 /* Set port power mode to ganged power-switching. */ 179 OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG); 180 OHCI_CLR(regs->rh_desc_a, RHDA_PSM_FLAG); 181 182 /* Turn off power (hub driver will turn this back on)*/ 183 OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER); 176 184 177 185 /* Set to global over-current */ 178 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;179 instance->registers->rh_desc_a &= ~RHDA_OCPM_FLAG;186 OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG); 187 OHCI_CLR(regs->rh_desc_a, RHDA_OCPM_FLAG); 180 188 #else 181 /* Set port power mode to no per port power-switching. */ 182 instance->registers->rh_desc_a &= ~RHDA_NPS_FLAG; 183 instance->registers->rh_desc_a |= RHDA_PSM_FLAG; 189 usb_log_debug("OHCI rh: Set power mode to per-port power switching.\n"); 190 /* Set port power mode to per port power-switching. */ 191 OHCI_CLR(regs->rh_desc_a, RHDA_NPS_FLAG); 192 OHCI_SET(regs->rh_desc_a, RHDA_PSM_FLAG); 184 193 185 194 /* Control all ports by global switch and turn them off */ 186 instance->registers->rh_desc_b &= (RHDB_PCC_MASK << RHDB_PCC_SHIFT);187 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER;195 OHCI_CLR(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT); 196 OHCI_WR(regs->rh_status, RHS_CLEAR_GLOBAL_POWER); 188 197 189 198 /* Return control to per port state */ 190 instance->registers->rh_desc_b |= 191 ((1 << (instance->port_count + 1)) - 1) << RHDB_PCC_SHIFT; 199 OHCI_SET(regs->rh_desc_b, RHDB_PCC_MASK << RHDB_PCC_SHIFT); 192 200 193 201 /* Set per port over-current */ 194 instance->registers->rh_desc_a &= ~RHDA_NOCP_FLAG;195 instance->registers->rh_desc_a |= RHDA_OCPM_FLAG;202 OHCI_CLR(regs->rh_desc_a, RHDA_NOCP_FLAG); 203 OHCI_SET(regs->rh_desc_a, RHDA_OCPM_FLAG); 196 204 #endif 197 205 … … 202 210 instance->port_count); 203 211 } 204 /*----------------------------------------------------------------------------*/ 212 205 213 /** 206 214 * Process root hub request. … … 226 234 fibril_mutex_lock(&instance->guard); 227 235 assert(instance->unfinished_interrupt_transfer == NULL); 228 uint16_t mask = create_interrupt_mask(instance);236 const uint16_t mask = create_interrupt_mask(instance); 229 237 if (mask == 0) { 230 usb_log_debug("No changes ...\n");238 usb_log_debug("No changes(%hx)...\n", mask); 231 239 instance->unfinished_interrupt_transfer = request; 232 240 } else { … … 243 251 } 244 252 } 245 /*----------------------------------------------------------------------------*/ 253 246 254 /** 247 255 * Process interrupt on a hub device. … … 257 265 if (instance->unfinished_interrupt_transfer) { 258 266 usb_log_debug("Finalizing interrupt transfer\n"); 259 uint16_t mask = create_interrupt_mask(instance);267 const uint16_t mask = create_interrupt_mask(instance); 260 268 interrupt_request(instance->unfinished_interrupt_transfer, 261 269 mask, instance->interrupt_mask_size); … … 264 272 fibril_mutex_unlock(&instance->guard); 265 273 } 266 /*----------------------------------------------------------------------------*/ 274 267 275 /** 268 276 * Create hub descriptor. … … 282 290 instance->hub_descriptor_size = size; 283 291 284 uint32_t hub_desc = instance->registers->rh_desc_a;285 uint32_t port_desc = instance->registers->rh_desc_b;292 const uint32_t hub_desc = OHCI_RD(instance->registers->rh_desc_a); 293 const uint32_t port_desc = OHCI_RD(instance->registers->rh_desc_b); 286 294 287 295 /* bDescLength */ … … 305 313 instance->descriptors.hub[4] = 0; 306 314 /* bPwrOn2PwrGood */ 307 instance->descriptors.hub[5] = 308 (hub_desc >> RHDA_POTPGT_SHIFT) & RHDA_POTPGT_MASK; 315 instance->descriptors.hub[5] = hub_desc >> RHDA_POTPGT_SHIFT; 309 316 /* bHubContrCurrent, root hubs don't need no power. */ 310 317 instance->descriptors.hub[6] = 0; 311 318 312 319 /* Device Removable and some legacy 1.0 stuff*/ 313 instance->descriptors.hub[7] = 314 (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK & 0xff; 320 instance->descriptors.hub[7] = (port_desc >> RHDB_DR_SHIFT) & 0xff; 315 321 instance->descriptors.hub[8] = 0xff; 316 322 if (instance->interrupt_mask_size == 2) { 317 323 instance->descriptors.hub[8] = 318 (port_desc >> RHDB_DR_SHIFT) & RHDB_DR_MASK>> 8;324 (port_desc >> RHDB_DR_SHIFT) >> 8; 319 325 instance->descriptors.hub[9] = 0xff; 320 326 instance->descriptors.hub[10] = 0xff; 321 327 } 322 328 } 323 /*----------------------------------------------------------------------------*/ 329 324 330 /** Initialize hub descriptors. 325 331 * … … 341 347 instance->interrupt_mask_size; 342 348 343 instance->descriptors.configuration.total_length = 349 instance->descriptors.configuration.total_length = uint16_host2usb( 344 350 sizeof(usb_standard_configuration_descriptor_t) + 345 351 sizeof(usb_standard_endpoint_descriptor_t) + 346 352 sizeof(usb_standard_interface_descriptor_t) + 347 instance->hub_descriptor_size ;348 } 349 /*----------------------------------------------------------------------------*/ 353 instance->hub_descriptor_size); 354 } 355 350 356 /** 351 357 * Create bitmap of changes to answer status interrupt. … … 364 370 365 371 /* Only local power source change and over-current change can happen */ 366 if (instance->registers->rh_status & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) { 372 if (OHCI_RD(instance->registers->rh_status) 373 & (RHS_LPSC_FLAG | RHS_OCIC_FLAG)) { 367 374 mask |= 1; 368 375 } 369 376 for (size_t port = 1; port <= instance->port_count; ++port) { 370 377 /* Write-clean bits are those that indicate change */ 371 if (RHPS_CHANGE_WC_MASK 372 & instance->registers->rh_port_status[port - 1]) { 373 378 if (OHCI_RD(instance->registers->rh_port_status[port - 1]) 379 & RHPS_CHANGE_WC_MASK) { 374 380 mask |= (1 << port); 375 381 } 376 382 } 377 /* USB is little endian */378 return host2uint32_t_le(mask);379 } 380 /*----------------------------------------------------------------------------*/ 383 usb_log_debug2("OHCI root hub interrupt mask: %hx.\n", mask); 384 return uint16_host2usb(mask); 385 } 386 381 387 /** 382 388 * Create answer to status request. … … 396 402 usb_device_request_setup_packet_t *request_packet = 397 403 (usb_device_request_setup_packet_t*)request->setup_buffer; 404 405 const uint16_t index = uint16_usb2host(request_packet->index); 398 406 399 407 switch (request_packet->request_type) … … 406 414 TRANSFER_END(request, EOVERFLOW); 407 415 } else { 408 uint32_t data = instance->registers->rh_status & 409 (RHS_LPS_FLAG | RHS_LPSC_FLAG 410 | RHS_OCI_FLAG | RHS_OCIC_FLAG); 416 const uint32_t data = 417 OHCI_RD(instance->registers->rh_status) & 418 (RHS_LPS_FLAG | RHS_LPSC_FLAG 419 | RHS_OCI_FLAG | RHS_OCIC_FLAG); 411 420 TRANSFER_END_DATA(request, &data, sizeof(data)); 412 421 } … … 420 429 TRANSFER_END(request, EOVERFLOW); 421 430 } else { 422 unsigned port = request_packet->index;431 const unsigned port = index; 423 432 if (port < 1 || port > instance->port_count) 424 433 TRANSFER_END(request, EINVAL); 425 426 uint32_t data = 427 instance->registers->rh_port_status[port - 1]; 434 /* Register format matches the format of port status 435 * field */ 436 const uint32_t data = uint32_usb2host(OHCI_RD( 437 instance->registers->rh_port_status[port - 1])); 428 438 TRANSFER_END_DATA(request, &data, sizeof(data)); 429 439 } … … 434 444 TRANSFER_END(request, EOVERFLOW); 435 445 } else { 436 uint16_t data =446 const uint16_t data = 437 447 uint16_host2usb(USB_DEVICE_STATUS_SELF_POWERED); 438 448 TRANSFER_END_DATA(request, &data, sizeof(data)); … … 441 451 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_INTERFACE): 442 452 /* Hubs are allowed to have only one interface */ 443 if ( request_packet->index != 0)453 if (index != 0) 444 454 TRANSFER_END(request, EINVAL); 445 455 /* Fall through, as the answer will be the same: 0x0000 */ 446 456 case SETUP_REQUEST_TO_HOST(USB_REQUEST_TYPE_STANDARD, USB_REQUEST_RECIPIENT_ENDPOINT): 447 457 /* Endpoint 0 (default control) and 1 (interrupt) */ 448 if ( request_packet->index >= 2)458 if (index >= 2) 449 459 TRANSFER_END(request, EINVAL); 450 460 … … 455 465 } else { 456 466 /* Endpoints are OK. (We don't halt) */ 457 uint16_t data = 0;467 const uint16_t data = 0; 458 468 TRANSFER_END_DATA(request, &data, sizeof(data)); 459 469 } … … 465 475 466 476 } 467 /*----------------------------------------------------------------------------*/ 477 468 478 /** 469 479 * Create answer to a descriptor request. … … 482 492 usb_device_request_setup_packet_t *setup_request = 483 493 (usb_device_request_setup_packet_t *) request->setup_buffer; 484 uint16_t setup_request_value = setup_request->value_high; 485 switch (setup_request_value) 494 /* "The wValue field specifies the descriptor type in the high byte 495 * and the descriptor index in the low byte (refer to Table 9-5)." */ 496 const int desc_type = uint16_usb2host(setup_request->value) >> 8; 497 switch (desc_type) 486 498 { 487 499 case USB_DESCTYPE_HUB: … … 530 542 setup_request->value, 531 543 setup_request->request_type, setup_request->request, 532 setup_request_value, setup_request->index,544 desc_type, setup_request->index, 533 545 setup_request->length); 534 546 TRANSFER_END(request, EINVAL); … … 537 549 TRANSFER_END(request, ENOTSUP); 538 550 } 539 /*----------------------------------------------------------------------------*/ 551 540 552 /** 541 553 * process feature-enabling request on hub … … 556 568 switch (feature) 557 569 { 558 case USB_HUB_FEATURE_PORT_POWER: //8 559 /* No power switching */ 560 if (instance->registers->rh_desc_a & RHDA_NPS_FLAG) 561 return EOK; 562 /* Ganged power switching */ 563 if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) { 564 instance->registers->rh_status = RHS_SET_GLOBAL_POWER; 565 return EOK; 570 case USB_HUB_FEATURE_PORT_POWER: /*8*/ 571 { 572 const uint32_t rhda = 573 OHCI_RD(instance->registers->rh_desc_a); 574 /* No power switching */ 575 if (rhda & RHDA_NPS_FLAG) 576 return EOK; 577 /* Ganged power switching, one port powers all */ 578 if (!(rhda & RHDA_PSM_FLAG)) { 579 OHCI_WR(instance->registers->rh_status, 580 RHS_SET_GLOBAL_POWER); 581 return EOK; 582 } 566 583 } 567 case USB_HUB_FEATURE_PORT_ENABLE: //1 568 case USB_HUB_FEATURE_PORT_SUSPEND: //2 569 case USB_HUB_FEATURE_PORT_RESET: //4 570 /* Nice thing is that these shifts correspond to the position 571 * of control bits in register */ 572 instance->registers->rh_port_status[port - 1] = (1 << feature); 584 /* Fall through */ 585 case USB_HUB_FEATURE_PORT_ENABLE: /*1*/ 586 case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/ 587 case USB_HUB_FEATURE_PORT_RESET: /*4*/ 588 usb_log_debug2("Setting port POWER, ENABLE, SUSPEND or RESET " 589 "on port %zu.\n", port); 590 OHCI_WR(instance->registers->rh_port_status[port - 1], 591 1 << feature); 573 592 return EOK; 574 593 default: … … 576 595 } 577 596 } 578 /*----------------------------------------------------------------------------*/ 597 579 598 /** 580 599 * Process feature clear request. … … 596 615 switch (feature) 597 616 { 598 case USB_HUB_FEATURE_PORT_POWER: //8 599 /* No power switching */ 600 if (instance->registers->rh_desc_a & RHDA_NPS_FLAG) 601 return ENOTSUP; 602 /* Ganged power switching */ 603 if (!(instance->registers->rh_desc_a & RHDA_PSM_FLAG)) { 604 instance->registers->rh_status = RHS_CLEAR_GLOBAL_POWER; 617 case USB_HUB_FEATURE_PORT_POWER: /*8*/ 618 { 619 const uint32_t rhda = 620 OHCI_RD(instance->registers->rh_desc_a); 621 /* No power switching */ 622 if (rhda & RHDA_NPS_FLAG) 623 return ENOTSUP; 624 /* Ganged power switching, one port powers all */ 625 if (!(rhda & RHDA_PSM_FLAG)) { 626 OHCI_WR(instance->registers->rh_status, 627 RHS_CLEAR_GLOBAL_POWER); 628 return EOK; 629 } 630 OHCI_WR(instance->registers->rh_port_status[port - 1], 631 RHPS_CLEAR_PORT_POWER); 605 632 return EOK; 606 633 } 607 instance->registers->rh_port_status[port - 1] = 608 RHPS_CLEAR_PORT_POWER; 634 635 case USB_HUB_FEATURE_PORT_ENABLE: /*1*/ 636 OHCI_WR(instance->registers->rh_port_status[port - 1], 637 RHPS_CLEAR_PORT_ENABLE); 609 638 return EOK; 610 639 611 case USB_HUB_FEATURE_PORT_ ENABLE: //1612 instance->registers->rh_port_status[port - 1] =613 RHPS_CLEAR_PORT_ENABLE;640 case USB_HUB_FEATURE_PORT_SUSPEND: /*2*/ 641 OHCI_WR(instance->registers->rh_port_status[port - 1], 642 RHPS_CLEAR_PORT_SUSPEND); 614 643 return EOK; 615 644 616 case USB_HUB_FEATURE_PORT_SUSPEND: //2 617 instance->registers->rh_port_status[port - 1] = 618 RHPS_CLEAR_PORT_SUSPEND; 619 return EOK; 620 621 case USB_HUB_FEATURE_C_PORT_CONNECTION: //16 622 case USB_HUB_FEATURE_C_PORT_ENABLE: //17 623 case USB_HUB_FEATURE_C_PORT_SUSPEND: //18 624 case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: //19 625 case USB_HUB_FEATURE_C_PORT_RESET: //20 626 /* Nice thing is that these shifts correspond to the position 627 * of control bits in register */ 628 instance->registers->rh_port_status[port - 1] = (1 << feature); 645 case USB_HUB_FEATURE_C_PORT_CONNECTION: /*16*/ 646 case USB_HUB_FEATURE_C_PORT_ENABLE: /*17*/ 647 case USB_HUB_FEATURE_C_PORT_SUSPEND: /*18*/ 648 case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: /*19*/ 649 case USB_HUB_FEATURE_C_PORT_RESET: /*20*/ 650 usb_log_debug2("Clearing port C_CONNECTION, C_ENABLE, " 651 "C_SUSPEND, C_OC or C_RESET on port %zu.\n", port); 652 /* Bit offsets correspond to the feature number */ 653 OHCI_WR(instance->registers->rh_port_status[port - 1], 654 1 << feature); 629 655 return EOK; 630 656 … … 633 659 } 634 660 } 635 /*----------------------------------------------------------------------------*/ 661 636 662 /** 637 663 * process one of requests that do not request nor carry additional data … … 654 680 case USB_HUB_REQ_TYPE_SET_PORT_FEATURE: 655 681 usb_log_debug("USB_HUB_REQ_TYPE_SET_PORT_FEATURE\n"); 656 int ret = set_feature_port(instance,682 const int ret = set_feature_port(instance, 657 683 setup_request->value, setup_request->index); 658 684 TRANSFER_END(request, ret); … … 671 697 } 672 698 } 673 /*----------------------------------------------------------------------------*/ 699 674 700 /** 675 701 * process one of requests that do not request nor carry additional data … … 693 719 case USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE: 694 720 usb_log_debug("USB_HUB_REQ_TYPE_CLEAR_PORT_FEATURE\n"); 695 int ret = clear_feature_port(instance,721 const int ret = clear_feature_port(instance, 696 722 setup_request->value, setup_request->index); 697 723 TRANSFER_END(request, ret); … … 706 732 * as root hubs do not support local power status feature. 707 733 * (OHCI pg. 127) */ 708 if (setup_request->value == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 709 instance->registers->rh_status = RHS_OCIC_FLAG; 734 if (uint16_usb2host(setup_request->value) 735 == USB_HUB_FEATURE_C_HUB_OVER_CURRENT) { 736 OHCI_WR(instance->registers->rh_status, RHS_OCIC_FLAG); 710 737 TRANSFER_END(request, EOK); 711 738 } … … 717 744 } 718 745 } 719 /*----------------------------------------------------------------------------*/ 746 720 747 /** 721 748 * Process hub control request. … … 771 798 if (request->buffer_size == 0) 772 799 TRANSFER_END(request, EOVERFLOW); 773 uint8_t config = 1;800 const uint8_t config = 1; 774 801 TRANSFER_END_DATA(request, &config, sizeof(config)); 775 802 … … 790 817 TRANSFER_END(request, EINVAL); 791 818 792 instance->address = setup_request->value;819 instance->address = uint16_usb2host(setup_request->value); 793 820 TRANSFER_END(request, EOK); 794 821 795 822 case USB_DEVREQ_SET_CONFIGURATION: 796 823 usb_log_debug("USB_DEVREQ_SET_CONFIGURATION: %u\n", 797 setup_request->value);824 uint16_usb2host(setup_request->value)); 798 825 /* We have only one configuration, it's number is 1 */ 799 826 if (uint16_usb2host(setup_request->value) != 1)
Note:
See TracChangeset
for help on using the changeset viewer.