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