1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * EHCI Host Controller Driver (EHCI) 31 * 32 * The EHCI driver is a software driver which interfaces to the Universal 33 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to 34 * the Host Controller is defined by the EHCI Host Controller Interface. 35 * 36 * This module contains the code for root hub related functions. 37 * 38 * NOTE: 39 * 40 * ONE_XFER is not supported on root hub interrupt polling 41 */ 42 43 #include <sys/usb/hcd/ehci/ehcid.h> 44 #include <sys/usb/hcd/ehci/ehci_util.h> 45 #include <sys/usb/usba/usba_types.h> 46 47 /* Static function prototypes */ 48 static int ehci_handle_set_clear_port_feature( 49 ehci_state_t *ehcip, 50 uchar_t bRequest, 51 uint16_t wValue, 52 uint16_t port); 53 static void ehci_handle_port_power( 54 ehci_state_t *ehcip, 55 uint16_t port, 56 uint_t on); 57 static void ehci_handle_port_enable( 58 ehci_state_t *ehcip, 59 uint16_t port, 60 uint_t on); 61 static void ehci_handle_clrchng_port_enable( 62 ehci_state_t *ehcip, 63 uint16_t port); 64 static void ehci_handle_port_suspend( 65 ehci_state_t *ehcip, 66 uint16_t port, 67 uint_t on); 68 static void ehci_handle_clrchng_port_suspend( 69 ehci_state_t *ehcip, 70 uint16_t port); 71 static void ehci_handle_port_reset( 72 ehci_state_t *ehcip, 73 uint16_t port); 74 static void ehci_root_hub_reset_occured( 75 ehci_state_t *ehcip); 76 static void ehci_handle_complete_port_reset( 77 ehci_state_t *ehcip, 78 uint16_t port); 79 static void ehci_handle_clear_port_connection( 80 ehci_state_t *ehcip, 81 uint16_t port); 82 static void ehci_handle_clrchng_port_over_current( 83 ehci_state_t *ehcip, 84 uint16_t port); 85 static void ehci_handle_get_port_status( 86 ehci_state_t *ehcip, 87 uint16_t port); 88 static void ehci_handle_get_hub_descriptor( 89 ehci_state_t *ehcip); 90 static void ehci_handle_get_hub_status( 91 ehci_state_t *ehcip); 92 static uint_t ehci_get_root_hub_port_status( 93 ehci_state_t *ehcip, 94 uint16_t port); 95 static int ehci_is_port_owner( 96 ehci_state_t *ehcip, 97 uint16_t port); 98 static int ehci_root_hub_allocate_intr_pipe_resource( 99 ehci_state_t *ehcip, 100 usb_flags_t flags); 101 static void ehci_root_hub_intr_pipe_cleanup( 102 ehci_state_t *ehcip, 103 usb_cr_t completion_reason); 104 static void ehci_handle_root_hub_status_change(void *arg); 105 static void ehci_root_hub_hcdi_callback( 106 usba_pipe_handle_data_t *ph, 107 usb_cr_t completion_reason); 108 109 110 /* 111 * ehci_init_root_hub: 112 * 113 * Initialize the root hub 114 */ 115 int 116 ehci_init_root_hub(ehci_state_t *ehcip) 117 { 118 usb_hub_descr_t *root_hub_descr = 119 &ehcip->ehci_root_hub.rh_descr; 120 uint_t i, length, port_state; 121 uint32_t capability; 122 123 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 124 "ehci_init_root_hub:"); 125 126 /* Read the EHCI capability register */ 127 capability = Get_Cap(ehci_hcs_params); 128 129 /* 130 * Build the Root hub descriptor by looking EHCI capability 131 * and operational registers. 132 */ 133 root_hub_descr->bDescriptorType = ROOT_HUB_DESCRIPTOR_TYPE; 134 135 if ((capability & EHCI_HCS_NUM_PORTS) > EHCI_MAX_RH_PORTS) { 136 137 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 138 "ehci_init_root_hub: Invalid no of root hub ports 0x%x", 139 capability & EHCI_HCS_NUM_PORTS); 140 141 return (USB_FAILURE); 142 } 143 144 /* Obtain the number of downstream ports */ 145 root_hub_descr->bNbrPorts = capability & EHCI_HCS_NUM_PORTS; 146 147 length = root_hub_descr->bNbrPorts / 8; 148 149 if (length) { 150 root_hub_descr->bDescLength = 7 + (2 * (length + 1)); 151 } else { 152 root_hub_descr->bDescLength = ROOT_HUB_DESCRIPTOR_LENGTH; 153 } 154 155 /* 156 * Obtain the number of Classic or Companion USB 1.1 (OHCI/UHCI) 157 * Host Controllers information. 158 */ 159 ehcip->ehci_root_hub.rh_companion_controllers = (capability & 160 EHCI_HCS_NUM_COMP_CTRLS) >> EHCI_HCS_NUM_COMP_CTRL_SHIFT; 161 162 /* 163 * Determine the Power Switching Mode 164 * 165 * EHCI Specification, root hub supports either no power switching 166 * individual port power switching. Also determine the Over-current 167 * Protection Mode. 168 */ 169 if (capability & EHCI_HCS_PORT_POWER_CONTROL) { 170 /* Each port is powered individually */ 171 root_hub_descr-> wHubCharacteristics = 172 HUB_CHARS_INDIVIDUAL_PORT_POWER; 173 174 /* Assume individual overcurrent reporting */ 175 root_hub_descr->wHubCharacteristics |= 176 HUB_CHARS_INDIV_OVER_CURRENT; 177 178 /* Each port will start off in the POWERED_OFF mode */ 179 port_state = POWERED_OFF; 180 } else { 181 /* The ports are powered when the ctlr is powered */ 182 root_hub_descr-> 183 wHubCharacteristics = HUB_CHARS_NO_POWER_SWITCHING; 184 185 /* Assume no overcurrent reporting */ 186 root_hub_descr->wHubCharacteristics |= 187 HUB_CHARS_NO_OVER_CURRENT; 188 189 port_state = DISCONNECTED; 190 } 191 192 /* Look at the port indicator information */ 193 if (capability & EHCI_HCS_PORT_INDICATOR) { 194 root_hub_descr->wHubCharacteristics |= HUB_CHARS_PORT_INDICATOR; 195 } 196 197 /* 198 * Obtain the power on to power good time of the ports. 199 * 200 * Assume: Zero for this field. 201 */ 202 root_hub_descr->bPwrOn2PwrGood = 2; 203 204 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 205 "Power on to power good %d", root_hub_descr->bPwrOn2PwrGood); 206 207 /* Indicate if the device is removable */ 208 root_hub_descr->DeviceRemovable = 0; 209 210 /* Set PortPowerControlMask to zero */ 211 root_hub_descr->PortPwrCtrlMask = 0; 212 213 /* Set the state of each port and initialize the status */ 214 for (i = 0; i < root_hub_descr->bNbrPorts; i++) { 215 216 /* Initilize state/status of each root hub port */ 217 ehcip->ehci_root_hub.rh_port_state[i] = port_state; 218 ehcip->ehci_root_hub.rh_port_status[i] = 0; 219 } 220 221 return (USB_SUCCESS); 222 } 223 224 225 /* 226 * ehci_load_root_hub_driver: 227 * 228 * Attach the root hub 229 */ 230 static usb_dev_descr_t ehci_root_hub_device_descriptor = { 231 0x12, /* bLength */ 232 0x01, /* bDescriptorType, Device */ 233 0x200, /* bcdUSB, v2.0 */ 234 0x09, /* bDeviceClass */ 235 0x00, /* bDeviceSubClass */ 236 0x01, /* bDeviceProtocol */ 237 0x40, /* bMaxPacketSize0 */ 238 0x00, /* idVendor */ 239 0x00, /* idProduct */ 240 0x00, /* bcdDevice */ 241 0x00, /* iManufacturer */ 242 0x00, /* iProduct */ 243 0x00, /* iSerialNumber */ 244 0x01 /* bNumConfigurations */ 245 }; 246 247 static uchar_t ehci_root_hub_config_descriptor[] = { 248 /* One configuartion */ 249 0x09, /* bLength */ 250 0x02, /* bDescriptorType, Configuartion */ 251 0x19, 0x00, /* wTotalLength */ 252 0x01, /* bNumInterfaces */ 253 0x01, /* bConfigurationValue */ 254 0x00, /* iConfiguration */ 255 0x40, /* bmAttributes */ 256 0x00, /* MaxPower */ 257 258 /* One Interface */ 259 0x09, /* bLength */ 260 0x04, /* bDescriptorType, Interface */ 261 0x00, /* bInterfaceNumber */ 262 0x00, /* bAlternateSetting */ 263 0x01, /* bNumEndpoints */ 264 0x09, /* bInterfaceClass */ 265 0x01, /* bInterfaceSubClass */ 266 0x00, /* bInterfaceProtocol */ 267 0x00, /* iInterface */ 268 269 /* One Endpoint (status change endpoint) */ 270 0x07, /* bLength */ 271 0x05, /* bDescriptorType, Endpoint */ 272 0x81, /* bEndpointAddress */ 273 0x03, /* bmAttributes */ 274 0x01, 0x00, /* wMaxPacketSize, 1 + (EHCI_MAX_RH_PORTS / 8) */ 275 0xff /* bInterval */ 276 }; 277 278 int 279 ehci_load_root_hub_driver(ehci_state_t *ehcip) 280 { 281 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 282 "ehci_load_root_hub_driver:"); 283 284 return (usba_hubdi_bind_root_hub(ehcip->ehci_dip, 285 ehci_root_hub_config_descriptor, 286 sizeof (ehci_root_hub_config_descriptor), 287 &ehci_root_hub_device_descriptor)); 288 } 289 290 291 /* 292 * ehci_unload_root_hub_driver: 293 */ 294 int 295 ehci_unload_root_hub_driver(ehci_state_t *ehcip) 296 { 297 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 298 "ehci_unload_root_hub_driver:"); 299 300 return (usba_hubdi_unbind_root_hub(ehcip->ehci_dip)); 301 } 302 303 304 /* 305 * ehci_handle_root_hub_pipe_open: 306 * 307 * Handle opening of control and interrupt pipes on root hub. 308 */ 309 /* ARGSUSED */ 310 int 311 ehci_handle_root_hub_pipe_open( 312 usba_pipe_handle_data_t *ph, 313 usb_flags_t usb_flags) 314 { 315 ehci_state_t *ehcip = ehci_obtain_state( 316 ph->p_usba_device->usb_root_hub_dip); 317 usb_ep_descr_t *eptd = &ph->p_ep; 318 319 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 320 "ehci_handle_root_hub_pipe_open: Root hub pipe open"); 321 322 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 323 324 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) { 325 case USB_EP_ATTR_CONTROL: 326 /* Save control pipe handle */ 327 ehcip->ehci_root_hub.rh_ctrl_pipe_handle = ph; 328 329 /* Set state of the root hub control pipe as idle */ 330 ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_IDLE; 331 332 ehcip->ehci_root_hub.rh_curr_ctrl_reqp = NULL; 333 334 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 335 "ehci_handle_root_hub_pipe_open: Root hub control " 336 "pipe open succeeded"); 337 338 break; 339 case USB_EP_ATTR_INTR: 340 /* Save interrupt pipe handle */ 341 ehcip->ehci_root_hub.rh_intr_pipe_handle = ph; 342 343 /* Set state of the root hub interrupt pipe as idle */ 344 ehcip->ehci_root_hub.rh_intr_pipe_state = EHCI_PIPE_STATE_IDLE; 345 346 ehcip->ehci_root_hub.rh_client_intr_reqp = NULL; 347 348 ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL; 349 350 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 351 "ehci_handle_root_hub_pipe_open: Root hub interrupt " 352 "pipe open succeeded"); 353 354 break; 355 default: 356 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 357 "ehci_handle_root_hub_pipe_open: Root hub pipe open" 358 "failed"); 359 360 return (USB_FAILURE); 361 } 362 363 ehcip->ehci_open_pipe_count++; 364 365 return (USB_SUCCESS); 366 } 367 368 369 /* 370 * ehci_handle_root_hub_pipe_close: 371 * 372 * Handle closing of control and interrupt pipes on root hub. 373 */ 374 /* ARGSUSED */ 375 int 376 ehci_handle_root_hub_pipe_close(usba_pipe_handle_data_t *ph) 377 { 378 ehci_state_t *ehcip = ehci_obtain_state( 379 ph->p_usba_device->usb_root_hub_dip); 380 usb_ep_descr_t *eptd = &ph->p_ep; 381 382 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 383 "ehci_handle_root_hub_pipe_close: Root hub pipe close"); 384 385 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 386 387 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) { 388 case USB_EP_ATTR_CONTROL: 389 ASSERT(ehcip->ehci_root_hub. 390 rh_ctrl_pipe_state != EHCI_PIPE_STATE_CLOSE); 391 392 /* Set state of the root hub control pipe as close */ 393 ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_CLOSE; 394 395 /* Set root hub control pipe handle to null */ 396 ehcip->ehci_root_hub.rh_ctrl_pipe_handle = NULL; 397 398 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 399 "ehci_handle_root_hub_pipe_close: " 400 "Root hub control pipe close succeeded"); 401 break; 402 case USB_EP_ATTR_INTR: 403 ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1); 404 405 ASSERT(ehcip->ehci_root_hub. 406 rh_intr_pipe_state != EHCI_PIPE_STATE_CLOSE); 407 408 /* Set state of the root hub interrupt pipe as close */ 409 ehcip->ehci_root_hub.rh_intr_pipe_state = EHCI_PIPE_STATE_CLOSE; 410 411 /* Do interrupt pipe cleanup */ 412 ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_PIPE_CLOSING); 413 414 /* Set root hub interrupt pipe handle to null */ 415 ehcip->ehci_root_hub.rh_intr_pipe_handle = NULL; 416 417 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 418 "ehci_handle_root_hub_pipe_close: " 419 "Root hub interrupt pipe close succeeded"); 420 421 break; 422 default: 423 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 424 "ehci_handle_root_hub_pipe_close: " 425 "Root hub pipe close failed"); 426 427 return (USB_FAILURE); 428 } 429 430 ehcip->ehci_open_pipe_count--; 431 432 return (USB_SUCCESS); 433 } 434 435 436 /* 437 * ehci_handle_root_hub_pipe_reset: 438 * 439 * Handle resetting of control and interrupt pipes on root hub. 440 */ 441 /* ARGSUSED */ 442 int 443 ehci_handle_root_hub_pipe_reset( 444 usba_pipe_handle_data_t *ph, 445 usb_flags_t usb_flags) 446 { 447 ehci_state_t *ehcip = ehci_obtain_state( 448 ph->p_usba_device->usb_root_hub_dip); 449 usb_ep_descr_t *eptd = &ph->p_ep; 450 int error = USB_SUCCESS; 451 452 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 453 "ehci_handle_root_hub_pipe_reset: Root hub pipe reset"); 454 455 mutex_enter(&ehcip->ehci_int_mutex); 456 457 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) { 458 case USB_EP_ATTR_CONTROL: 459 ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_IDLE; 460 461 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 462 "ehci_handle_root_hub_pipe_reset: Pipe reset" 463 "for the root hub control pipe successful"); 464 465 break; 466 case USB_EP_ATTR_INTR: 467 ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1); 468 469 if ((ehcip->ehci_root_hub.rh_client_intr_reqp) && 470 (ehcip->ehci_root_hub.rh_intr_pipe_state != 471 EHCI_PIPE_STATE_IDLE)) { 472 473 ehcip->ehci_root_hub. 474 rh_intr_pipe_state = EHCI_PIPE_STATE_RESET; 475 476 /* Do interrupt pipe cleanup */ 477 ehci_root_hub_intr_pipe_cleanup( 478 ehcip, USB_CR_PIPE_RESET); 479 } 480 481 ASSERT(ehcip->ehci_root_hub. 482 rh_intr_pipe_state == EHCI_PIPE_STATE_IDLE); 483 484 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 485 "ehci_handle_root_hub_pipe_reset: " 486 "Pipe reset for root hub interrupt pipe successful"); 487 488 break; 489 default: 490 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 491 "ehci_handle_root_hub_pipe_reset: " 492 "Root hub pipe reset failed"); 493 494 error = USB_FAILURE; 495 break; 496 } 497 498 mutex_exit(&ehcip->ehci_int_mutex); 499 500 return (error); 501 } 502 503 504 /* 505 * ehci_handle_root_hub_request: 506 * 507 * Intercept a root hub request. Handle the root hub request through the 508 * registers 509 */ 510 /* ARGSUSED */ 511 int 512 ehci_handle_root_hub_request( 513 ehci_state_t *ehcip, 514 usba_pipe_handle_data_t *ph, 515 usb_ctrl_req_t *ctrl_reqp) 516 { 517 uchar_t bmRequestType = ctrl_reqp->ctrl_bmRequestType; 518 uchar_t bRequest = ctrl_reqp->ctrl_bRequest; 519 uint16_t wValue = ctrl_reqp->ctrl_wValue; 520 uint16_t wIndex = ctrl_reqp->ctrl_wIndex; 521 uint16_t wLength = ctrl_reqp->ctrl_wLength; 522 mblk_t *data = ctrl_reqp->ctrl_data; 523 uint16_t port = wIndex - 1; 524 usb_cr_t completion_reason; 525 int error = USB_SUCCESS; 526 527 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 528 "ehci_handle_root_hub_request: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%p", 529 bmRequestType, bRequest, wValue, wIndex, wLength, (void *)data); 530 531 mutex_enter(&ehcip->ehci_int_mutex); 532 533 if (ehcip->ehci_root_hub. 534 rh_ctrl_pipe_state != EHCI_PIPE_STATE_IDLE) { 535 536 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 537 "ehci_handle_root_hub_request: Pipe is not idle"); 538 539 mutex_exit(&ehcip->ehci_int_mutex); 540 541 return (USB_FAILURE); 542 } 543 544 /* Save the current control request pointer */ 545 ehcip->ehci_root_hub.rh_curr_ctrl_reqp = ctrl_reqp; 546 547 /* Set pipe state to active */ 548 ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_ACTIVE; 549 550 mutex_exit(&ehcip->ehci_int_mutex); 551 552 switch (bmRequestType) { 553 case HANDLE_PORT_FEATURE: 554 error = ehci_handle_set_clear_port_feature(ehcip, 555 bRequest, wValue, port); 556 break; 557 case GET_PORT_STATUS: 558 ehci_handle_get_port_status(ehcip, port); 559 break; 560 case HUB_CLASS_REQ: 561 switch (bRequest) { 562 case USB_REQ_GET_STATUS: 563 ehci_handle_get_hub_status(ehcip); 564 break; 565 case USB_REQ_GET_DESCR: 566 ehci_handle_get_hub_descriptor(ehcip); 567 break; 568 default: 569 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 570 "ehci_handle_root_hub_request:" 571 "Unsupported request 0x%x", bRequest); 572 573 error = USB_FAILURE; 574 break; 575 } 576 break; 577 default: 578 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 579 "ehci_handle_root_hub_request: " 580 "Unsupported request 0x%x", bmRequestType); 581 582 error = USB_FAILURE; 583 break; 584 } 585 586 completion_reason = (error) ? USB_CR_NOT_SUPPORTED : USB_CR_OK; 587 588 mutex_enter(&ehcip->ehci_int_mutex); 589 ehci_root_hub_hcdi_callback(ph, completion_reason); 590 mutex_exit(&ehcip->ehci_int_mutex); 591 592 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 593 "ehci_handle_root_hub_request: error = %d", error); 594 595 return (USB_SUCCESS); 596 } 597 598 599 /* 600 * ehci_handle_set_clear_port_feature: 601 */ 602 static int 603 ehci_handle_set_clear_port_feature( 604 ehci_state_t *ehcip, 605 uchar_t bRequest, 606 uint16_t wValue, 607 uint16_t port) 608 { 609 int error = USB_SUCCESS; 610 611 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 612 "ehci_handle_set_clear_port_feature: 0x%x 0x%x 0x%x", 613 bRequest, wValue, port); 614 615 switch (bRequest) { 616 case USB_REQ_SET_FEATURE: 617 switch (wValue) { 618 case CFS_PORT_ENABLE: 619 ehci_handle_port_enable(ehcip, port, 1); 620 break; 621 case CFS_PORT_SUSPEND: 622 ehci_handle_port_suspend(ehcip, port, 1); 623 break; 624 case CFS_PORT_RESET: 625 ehci_handle_port_reset(ehcip, port); 626 break; 627 case CFS_PORT_POWER: 628 ehci_handle_port_power(ehcip, port, 1); 629 break; 630 default: 631 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 632 "ehci_handle_set_clear_port_feature: " 633 "Unsupported request 0x%x 0x%x", bRequest, wValue); 634 635 error = USB_FAILURE; 636 break; 637 } 638 break; 639 case USB_REQ_CLEAR_FEATURE: 640 switch (wValue) { 641 case CFS_PORT_ENABLE: 642 ehci_handle_port_enable(ehcip, port, 0); 643 break; 644 case CFS_C_PORT_ENABLE: 645 ehci_handle_clrchng_port_enable(ehcip, port); 646 break; 647 case CFS_PORT_SUSPEND: 648 ehci_handle_port_suspend(ehcip, port, 0); 649 break; 650 case CFS_C_PORT_SUSPEND: 651 ehci_handle_clrchng_port_suspend(ehcip, port); 652 break; 653 case CFS_C_PORT_RESET: 654 ehci_handle_complete_port_reset(ehcip, port); 655 break; 656 case CFS_PORT_POWER: 657 ehci_handle_port_power(ehcip, port, 0); 658 break; 659 case CFS_C_PORT_CONNECTION: 660 ehci_handle_clear_port_connection(ehcip, port); 661 break; 662 case CFS_C_PORT_OVER_CURRENT: 663 ehci_handle_clrchng_port_over_current(ehcip, port); 664 break; 665 default: 666 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 667 "ehci_handle_set_clear_port_feature: " 668 "Unsupported request 0x%x 0x%x", bRequest, wValue); 669 670 error = USB_FAILURE; 671 break; 672 } 673 break; 674 default: 675 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 676 "ehci_handle_set_clear_port_feature: " 677 "Unsupported request 0x%x 0x%x", bRequest, wValue); 678 679 error = USB_FAILURE; 680 break; 681 } 682 683 return (error); 684 } 685 686 687 /* 688 * ehci_handle_port_power: 689 * 690 * Turn on a root hub port. 691 */ 692 static void 693 ehci_handle_port_power( 694 ehci_state_t *ehcip, 695 uint16_t port, 696 uint_t on) 697 { 698 uint_t port_status; 699 ehci_root_hub_t *rh; 700 701 mutex_enter(&ehcip->ehci_int_mutex); 702 703 port_status = Get_OpReg(ehci_rh_port_status[port]) & 704 ~EHCI_RH_PORT_CLEAR_MASK; 705 706 rh = &ehcip->ehci_root_hub; 707 708 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 709 "ehci_handle_port_power: port = 0x%x status = 0x%x on = %d", 710 port, port_status, on); 711 712 /* Check port is owned by ehci */ 713 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 714 mutex_exit(&ehcip->ehci_int_mutex); 715 716 return; 717 } 718 719 if (on) { 720 /* See if the port power is already on */ 721 if (!(port_status & EHCI_RH_PORT_POWER)) { 722 /* Turn the port on */ 723 Set_OpReg(ehci_rh_port_status[port], 724 port_status | EHCI_RH_PORT_POWER); 725 } 726 727 rh->rh_port_status[port] = 0; 728 rh->rh_port_state[port] = DISCONNECTED; 729 } else { 730 /* See if the port power is already OFF */ 731 if (port_status & EHCI_RH_PORT_POWER) { 732 /* Turn-off the port */ 733 Set_OpReg(ehci_rh_port_status[port], 734 port_status & ~EHCI_RH_PORT_POWER); 735 } 736 737 rh->rh_port_status[port] = 0; 738 rh->rh_port_state[port] = POWERED_OFF; 739 } 740 741 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 742 "ehci_handle_port_power done: port = 0x%x status = 0x%x on = %d", 743 port, Get_OpReg(ehci_rh_port_status[port]), on); 744 745 mutex_exit(&ehcip->ehci_int_mutex); 746 } 747 748 749 /* 750 * ehci_handle_port_enable: 751 * 752 * Handle port enable request. 753 */ 754 static void 755 ehci_handle_port_enable( 756 ehci_state_t *ehcip, 757 uint16_t port, 758 uint_t on) 759 { 760 uint_t port_status; 761 762 mutex_enter(&ehcip->ehci_int_mutex); 763 764 port_status = Get_OpReg(ehci_rh_port_status[port]) & 765 ~EHCI_RH_PORT_CLEAR_MASK; 766 767 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 768 "ehci_handle_port_enable: port = 0x%x, status = 0x%x", 769 port, port_status); 770 771 /* Check port is owned by ehci */ 772 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 773 mutex_exit(&ehcip->ehci_int_mutex); 774 775 return; 776 } 777 778 if (on) { 779 /* See if the port enable is already on */ 780 if (!(port_status & EHCI_RH_PORT_ENABLE)) { 781 /* Enable the port */ 782 Set_OpReg(ehci_rh_port_status[port], 783 port_status | EHCI_RH_PORT_ENABLE); 784 } 785 } else { 786 /* See if the port enable is already off */ 787 if (port_status & EHCI_RH_PORT_ENABLE) { 788 /* Disable the port */ 789 Set_OpReg(ehci_rh_port_status[port], 790 port_status & ~EHCI_RH_PORT_ENABLE); 791 } 792 } 793 794 mutex_exit(&ehcip->ehci_int_mutex); 795 } 796 797 798 /* 799 * ehci_handle_clrchng_port_enable: 800 * 801 * Handle clear port enable change bit. 802 */ 803 static void 804 ehci_handle_clrchng_port_enable( 805 ehci_state_t *ehcip, 806 uint16_t port) 807 { 808 uint_t port_status; 809 810 mutex_enter(&ehcip->ehci_int_mutex); 811 812 port_status = Get_OpReg(ehci_rh_port_status[port]) & 813 ~EHCI_RH_PORT_CLEAR_MASK; 814 815 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 816 "ehci_handle_port_enable: port = 0x%x, status = 0x%x", 817 port, port_status); 818 819 /* Check port is owned by ehci */ 820 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 821 mutex_exit(&ehcip->ehci_int_mutex); 822 823 return; 824 } 825 826 /* Clear the PortEnableStatusChange Bit */ 827 Set_OpReg(ehci_rh_port_status[port], 828 port_status | EHCI_RH_PORT_ENABLE_CHANGE); 829 830 mutex_exit(&ehcip->ehci_int_mutex); 831 } 832 833 834 /* 835 * ehci_handle_port_suspend: 836 * 837 * Handle port suspend/resume request. 838 */ 839 static void 840 ehci_handle_port_suspend( 841 ehci_state_t *ehcip, 842 uint16_t port, 843 uint_t on) 844 { 845 uint_t port_status; 846 847 mutex_enter(&ehcip->ehci_int_mutex); 848 849 port_status = Get_OpReg(ehci_rh_port_status[port]) & 850 ~EHCI_RH_PORT_CLEAR_MASK; 851 852 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 853 "ehci_handle_port_suspend: port = 0x%x, status = 0x%x", 854 port, port_status); 855 856 /* Check port is owned by ehci */ 857 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 858 mutex_exit(&ehcip->ehci_int_mutex); 859 860 return; 861 } 862 863 if (on) { 864 /* 865 * Suspend port only if port is enabled and 866 * it is not already in suspend state. 867 */ 868 if ((port_status & EHCI_RH_PORT_ENABLE) && 869 (!(port_status & EHCI_RH_PORT_SUSPEND))) { 870 /* Suspend the port */ 871 Set_OpReg(ehci_rh_port_status[port], 872 port_status | EHCI_RH_PORT_SUSPEND); 873 874 mutex_exit(&ehcip->ehci_int_mutex); 875 876 /* Wait 10ms for port move to suspend state */ 877 delay(drv_usectohz(EHCI_PORT_SUSPEND_TIMEWAIT)); 878 879 return; 880 } 881 } else { 882 /* Perform resume only if port is in suspend state */ 883 if (port_status & EHCI_RH_PORT_SUSPEND) { 884 /* Resume the port */ 885 Set_OpReg(ehci_rh_port_status[port], 886 port_status | EHCI_RH_PORT_RESUME); 887 } 888 } 889 890 mutex_exit(&ehcip->ehci_int_mutex); 891 } 892 893 894 /* 895 * ehci_handle_clrchng_port_suspend: 896 * 897 * Handle port clear port suspend change bit. 898 */ 899 static void 900 ehci_handle_clrchng_port_suspend( 901 ehci_state_t *ehcip, 902 uint16_t port) 903 { 904 uint_t port_status; 905 906 mutex_enter(&ehcip->ehci_int_mutex); 907 908 port_status = Get_OpReg(ehci_rh_port_status[port]) & 909 ~EHCI_RH_PORT_CLEAR_MASK; 910 911 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 912 "ehci_handle_clrchng_port_suspend: port = 0x%x, " 913 "status = 0x%x", port, port_status); 914 915 /* Check port is owned by ehci */ 916 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 917 mutex_exit(&ehcip->ehci_int_mutex); 918 919 return; 920 } 921 922 /* Return if port is not in resume state */ 923 if (!(port_status & EHCI_RH_PORT_RESUME)) { 924 mutex_exit(&ehcip->ehci_int_mutex); 925 926 return; 927 } 928 929 mutex_exit(&ehcip->ehci_int_mutex); 930 931 /* Wait for 20ms to terminate resume */ 932 delay(drv_usectohz(EHCI_PORT_RESUME_TIMEWAIT)); 933 934 mutex_enter(&ehcip->ehci_int_mutex); 935 936 Set_OpReg(ehci_rh_port_status[port], 937 port_status & ~EHCI_RH_PORT_RESUME); 938 939 mutex_exit(&ehcip->ehci_int_mutex); 940 941 /* Wait 2ms for port to return to high speed mode */ 942 delay(drv_usectohz(EHCI_PORT_RESUME_COMP_TIMEWAIT)); 943 } 944 945 946 /* 947 * ehci_handle_port_reset: 948 * 949 * Perform a port reset. 950 */ 951 static void 952 ehci_handle_port_reset( 953 ehci_state_t *ehcip, 954 uint16_t port) 955 { 956 ehci_root_hub_t *rh; 957 uint_t port_status; 958 959 mutex_enter(&ehcip->ehci_int_mutex); 960 961 /* Get the root hub structure */ 962 rh = &ehcip->ehci_root_hub; 963 964 /* Get the port status information */ 965 port_status = Get_OpReg(ehci_rh_port_status[port]) & 966 ~EHCI_RH_PORT_CLEAR_MASK; 967 968 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 969 "ehci_handle_port_reset: port = 0x%x status = 0x%x", 970 port, port_status); 971 972 /* Check port is owned by ehci */ 973 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 974 mutex_exit(&ehcip->ehci_int_mutex); 975 976 return; 977 } 978 979 if (port_status & EHCI_RH_PORT_LOW_SPEED) { 980 /* Check for classic or companion host controllers */ 981 if (rh->rh_companion_controllers) { 982 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 983 "ehci_handle_port_reset: Low speed device " 984 "and handover this port to Companion controller"); 985 986 Set_OpReg(ehci_rh_port_status[port], 987 port_status | EHCI_RH_PORT_OWNER_CLASSIC); 988 } else { 989 USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 990 "Low speed device is not supported"); 991 } 992 } else { 993 Set_OpReg(ehci_rh_port_status[port], 994 ((port_status | EHCI_RH_PORT_RESET) & 995 ~EHCI_RH_PORT_ENABLE)); 996 997 mutex_exit(&ehcip->ehci_int_mutex); 998 999 /* Wait 10ms for reset to complete */ 1000 delay(drv_usectohz(EHCI_PORT_RESET_TIMEWAIT)); 1001 1002 mutex_enter(&ehcip->ehci_int_mutex); 1003 1004 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1005 ~EHCI_RH_PORT_CLEAR_MASK; 1006 1007 Set_OpReg(ehci_rh_port_status[port], 1008 (port_status & ~EHCI_RH_PORT_RESET)); 1009 1010 mutex_exit(&ehcip->ehci_int_mutex); 1011 1012 /* 1013 * Wait 2ms for hardware to enable this port 1014 * if connected usb device is high speed. 1015 */ 1016 delay(drv_usectohz(EHCI_PORT_RESET_COMP_TIMEWAIT)); 1017 1018 mutex_enter(&ehcip->ehci_int_mutex); 1019 1020 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1021 ~EHCI_RH_PORT_CLEAR_MASK; 1022 1023 /* 1024 * If port is not enabled, connected device is a 1025 * Full-speed usb device. 1026 */ 1027 if (!(port_status & EHCI_RH_PORT_ENABLE)) { 1028 /* Check for classic or companion host controllers */ 1029 if (rh->rh_companion_controllers) { 1030 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1031 ehcip->ehci_log_hdl, 1032 "ehci_handle_port_reset: Full speed device " 1033 "and handover this port to Companion host " 1034 "controller"); 1035 1036 Set_OpReg(ehci_rh_port_status[port], 1037 port_status | EHCI_RH_PORT_OWNER_CLASSIC); 1038 } else { 1039 USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB, 1040 ehcip->ehci_log_hdl, 1041 "Full speed device is not supported"); 1042 } 1043 } else { 1044 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1045 "ehci_handle_port_reset: High speed device "); 1046 1047 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1048 ~EHCI_RH_PORT_CLEAR_MASK; 1049 1050 /* 1051 * Enable over-current, connect, and disconnect 1052 * wakeup bits. 1053 */ 1054 Set_OpReg(ehci_rh_port_status[port], (port_status | 1055 EHCI_RH_PORT_OVER_CURENT_ENABLE | 1056 EHCI_RH_PORT_DISCONNECT_ENABLE | 1057 EHCI_RH_PORT_CONNECT_ENABLE)); 1058 1059 /* 1060 * The next function is only called if the interrupt 1061 * pipe is polling and the USBA is ready to receive 1062 * the data. 1063 */ 1064 ehcip->ehci_root_hub. 1065 rh_intr_pending_status |= (1 << port); 1066 1067 if (ehcip->ehci_root_hub. 1068 rh_intr_pipe_state == EHCI_PIPE_STATE_ACTIVE) { 1069 1070 ehci_root_hub_reset_occured(ehcip); 1071 } 1072 } 1073 } 1074 1075 mutex_exit(&ehcip->ehci_int_mutex); 1076 } 1077 1078 1079 /* 1080 * ehci_root_hub_reset_occured: 1081 * 1082 * Inform the upper layer that reset has occured on the port. This is 1083 * required because the upper layer is expecting a an evernt immidiately 1084 * after doing reset. In case of OHCI, the controller gets an interrupt 1085 * for the change in the root hub status but in case of EHCI, we dont. 1086 * So, send a event to the upper layer as soon as we complete the reset. 1087 */ 1088 void 1089 ehci_root_hub_reset_occured( 1090 ehci_state_t *ehcip) 1091 { 1092 usb_intr_req_t *curr_intr_reqp = 1093 ehcip->ehci_root_hub.rh_curr_intr_reqp; 1094 usb_port_mask_t port_mask; 1095 usba_pipe_handle_data_t *ph; 1096 1097 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1098 "ehci_root_hub_reset_occured: curr_intr_reqp = 0x%p data = 0x%p", 1099 curr_intr_reqp, curr_intr_reqp->intr_data); 1100 1101 /* Get the interrupt pipe handle */ 1102 ph = ehcip->ehci_root_hub.rh_intr_pipe_handle; 1103 1104 /* Get the pending status */ 1105 port_mask = ehcip->ehci_root_hub.rh_intr_pending_status << 1; 1106 1107 do { 1108 *curr_intr_reqp->intr_data->b_wptr++ = (uchar_t)port_mask; 1109 port_mask >>= 8; 1110 } while (port_mask != 0); 1111 1112 ehci_root_hub_hcdi_callback(ph, USB_CR_OK); 1113 1114 /* Reset pending status */ 1115 ehcip->ehci_root_hub.rh_intr_pending_status = 0; 1116 1117 /* If needed, allocate new interrupt request */ 1118 if ((ehci_root_hub_allocate_intr_pipe_resource( 1119 ehcip, 0)) != USB_SUCCESS) { 1120 1121 /* Do interrupt pipe cleanup */ 1122 ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_NO_RESOURCES); 1123 } 1124 } 1125 1126 1127 /* 1128 * ehci_handle_complete_port_reset: 1129 * 1130 * Perform a port reset change. 1131 */ 1132 static void 1133 ehci_handle_complete_port_reset( 1134 ehci_state_t *ehcip, 1135 uint16_t port) 1136 { 1137 uint_t port_status; 1138 1139 mutex_enter(&ehcip->ehci_int_mutex); 1140 1141 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1142 ~EHCI_RH_PORT_CLEAR_MASK; 1143 1144 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1145 "ehci_handle_complete_port_reset: port = 0x%x status = 0x%x", 1146 port, port_status); 1147 1148 /* Check port is owned by ehci */ 1149 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 1150 mutex_exit(&ehcip->ehci_int_mutex); 1151 1152 return; 1153 } 1154 1155 if (port_status & EHCI_RH_PORT_RESET) { 1156 Set_OpReg(ehci_rh_port_status[port], 1157 port_status & ~EHCI_RH_PORT_RESET); 1158 1159 } 1160 1161 mutex_exit(&ehcip->ehci_int_mutex); 1162 } 1163 1164 1165 /* 1166 * ehci_handle_clear_port_connection: 1167 * 1168 * Perform a clear port connection. 1169 */ 1170 static void 1171 ehci_handle_clear_port_connection( 1172 ehci_state_t *ehcip, 1173 uint16_t port) 1174 { 1175 uint_t port_status; 1176 1177 mutex_enter(&ehcip->ehci_int_mutex); 1178 1179 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1180 ~EHCI_RH_PORT_CLEAR_MASK; 1181 1182 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1183 "ehci_handle_clear_port_connection: port = 0x%x" 1184 "status = 0x%x", port, port_status); 1185 1186 Set_OpReg(ehci_rh_port_status[port], 1187 port_status | EHCI_RH_PORT_CONNECT_STS_CHANGE); 1188 1189 mutex_exit(&ehcip->ehci_int_mutex); 1190 } 1191 1192 1193 /* 1194 * ehci_handle_clrchng_port_over_current: 1195 * 1196 * Perform a clear port connection. 1197 */ 1198 static void 1199 ehci_handle_clrchng_port_over_current( 1200 ehci_state_t *ehcip, 1201 uint16_t port) 1202 { 1203 uint_t port_status; 1204 1205 mutex_enter(&ehcip->ehci_int_mutex); 1206 1207 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1208 ~EHCI_RH_PORT_CLEAR_MASK; 1209 1210 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1211 "ehci_handle_clrchng_port_over_current: port = 0x%x" 1212 "status = 0x%x", port, port_status); 1213 1214 Set_OpReg(ehci_rh_port_status[port], 1215 port_status | EHCI_RH_PORT_OVER_CURR_CHANGE); 1216 1217 mutex_exit(&ehcip->ehci_int_mutex); 1218 } 1219 1220 1221 /* 1222 * ehci_handle_get_port_status: 1223 * 1224 * Handle a get port status request. 1225 */ 1226 static void 1227 ehci_handle_get_port_status( 1228 ehci_state_t *ehcip, 1229 uint16_t port) 1230 { 1231 usb_ctrl_req_t *ctrl_reqp; 1232 mblk_t *message; 1233 uint_t new_port_status = 0; 1234 uint_t change_status = 0; 1235 uint_t port_status; 1236 1237 mutex_enter(&ehcip->ehci_int_mutex); 1238 1239 ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1240 1241 /* Get the root hub port status information */ 1242 port_status = ehci_get_root_hub_port_status(ehcip, port); 1243 1244 new_port_status = port_status & PORT_STATUS_MASK; 1245 change_status = (port_status >> 16) & PORT_CHANGE_MASK; 1246 1247 ehcip->ehci_root_hub.rh_port_status[port] = new_port_status; 1248 1249 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1250 "ehci_handle_get_port_status: port = %d new status = 0x%x" 1251 "change = 0x%x", port, new_port_status, change_status); 1252 1253 message = ctrl_reqp->ctrl_data; 1254 1255 ASSERT(message != NULL); 1256 1257 *message->b_wptr++ = (uchar_t)new_port_status; 1258 *message->b_wptr++ = (uchar_t)(new_port_status >> 8); 1259 *message->b_wptr++ = (uchar_t)change_status; 1260 *message->b_wptr++ = (uchar_t)(change_status >> 8); 1261 1262 /* Save the data in control request */ 1263 ctrl_reqp->ctrl_data = message; 1264 1265 mutex_exit(&ehcip->ehci_int_mutex); 1266 } 1267 1268 1269 /* 1270 * ehci_handle_get_hub_descriptor: 1271 */ 1272 static void 1273 ehci_handle_get_hub_descriptor( 1274 ehci_state_t *ehcip) 1275 { 1276 usb_ctrl_req_t *ctrl_reqp; 1277 mblk_t *message; 1278 usb_hub_descr_t *root_hub_descr; 1279 size_t length; 1280 uchar_t raw_descr[ROOT_HUB_DESCRIPTOR_LENGTH]; 1281 1282 mutex_enter(&ehcip->ehci_int_mutex); 1283 1284 ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1285 root_hub_descr = &ehcip->ehci_root_hub.rh_descr; 1286 length = ctrl_reqp->ctrl_wLength; 1287 1288 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1289 "ehci_handle_get_hub_descriptor: Ctrl Req = 0x%p", ctrl_reqp); 1290 1291 message = ctrl_reqp->ctrl_data; 1292 1293 ASSERT(message != NULL); 1294 1295 bzero(&raw_descr, ROOT_HUB_DESCRIPTOR_LENGTH); 1296 1297 raw_descr[0] = root_hub_descr->bDescLength; 1298 raw_descr[1] = root_hub_descr->bDescriptorType; 1299 raw_descr[2] = root_hub_descr->bNbrPorts; 1300 raw_descr[3] = root_hub_descr->wHubCharacteristics & 0x00FF; 1301 raw_descr[4] = (root_hub_descr->wHubCharacteristics & 0xFF00) >> 8; 1302 raw_descr[5] = root_hub_descr->bPwrOn2PwrGood; 1303 raw_descr[6] = root_hub_descr->bHubContrCurrent; 1304 raw_descr[7] = root_hub_descr->DeviceRemovable; 1305 raw_descr[8] = root_hub_descr->PortPwrCtrlMask; 1306 1307 bcopy(raw_descr, message->b_wptr, length); 1308 message->b_wptr += length; 1309 1310 /* Save the data in control request */ 1311 ctrl_reqp->ctrl_data = message; 1312 1313 mutex_exit(&ehcip->ehci_int_mutex); 1314 } 1315 1316 1317 /* 1318 * ehci_handle_get_hub_status: 1319 * 1320 * Handle a get hub status request. 1321 */ 1322 static void 1323 ehci_handle_get_hub_status( 1324 ehci_state_t *ehcip) 1325 { 1326 usb_ctrl_req_t *ctrl_reqp; 1327 mblk_t *message; 1328 uint_t new_root_hub_status; 1329 1330 mutex_enter(&ehcip->ehci_int_mutex); 1331 1332 ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1333 1334 /* 1335 * For EHCI, there is no overall hub status information. 1336 * Only individual root hub port status information is 1337 * available. So return zero for the root hub status 1338 * request. 1339 */ 1340 new_root_hub_status = 0; 1341 1342 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1343 "ehci_handle_get_hub_status: new root hub status = 0x%x", 1344 new_root_hub_status); 1345 1346 message = ctrl_reqp->ctrl_data; 1347 1348 ASSERT(message != NULL); 1349 1350 *message->b_wptr++ = (uchar_t)new_root_hub_status; 1351 *message->b_wptr++ = (uchar_t)(new_root_hub_status >> 8); 1352 *message->b_wptr++ = (uchar_t)(new_root_hub_status >> 16); 1353 *message->b_wptr++ = (uchar_t)(new_root_hub_status >> 24); 1354 1355 /* Save the data in control request */ 1356 ctrl_reqp->ctrl_data = message; 1357 1358 mutex_exit(&ehcip->ehci_int_mutex); 1359 } 1360 1361 1362 /* 1363 * ehci_handle_root_hub_pipe_start_intr_polling: 1364 * 1365 * Handle start polling on root hub interrupt pipe. 1366 */ 1367 /* ARGSUSED */ 1368 int 1369 ehci_handle_root_hub_pipe_start_intr_polling( 1370 usba_pipe_handle_data_t *ph, 1371 usb_intr_req_t *client_intr_reqp, 1372 usb_flags_t flags) 1373 { 1374 ehci_state_t *ehcip = ehci_obtain_state( 1375 ph->p_usba_device->usb_root_hub_dip); 1376 usb_ep_descr_t *eptd = &ph->p_ep; 1377 int error = USB_SUCCESS; 1378 uint_t pipe_state; 1379 1380 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1381 "ehci_handle_root_hub_pipe_start_intr_polling: " 1382 "Root hub pipe start polling"); 1383 1384 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1385 1386 ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1); 1387 1388 ASSERT((client_intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) == 0); 1389 1390 pipe_state = ehcip->ehci_root_hub.rh_intr_pipe_state; 1391 1392 switch (pipe_state) { 1393 case EHCI_PIPE_STATE_IDLE: 1394 ASSERT(ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0); 1395 1396 /* 1397 * Save the Original Client's Interrupt IN request 1398 * information. We use this for final callback 1399 */ 1400 ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp == NULL); 1401 ehcip->ehci_root_hub.rh_client_intr_reqp = client_intr_reqp; 1402 1403 error = ehci_root_hub_allocate_intr_pipe_resource(ehcip, flags); 1404 1405 if (error != USB_SUCCESS) { 1406 /* Reset client interrupt request pointer */ 1407 ehcip->ehci_root_hub.rh_client_intr_reqp = NULL; 1408 1409 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1410 "ehci_handle_root_hub_pipe_start_intr_polling: " 1411 "No Resources"); 1412 1413 return (error); 1414 } 1415 1416 /* Check whether we need to send the reset data up */ 1417 if (ehcip->ehci_root_hub.rh_intr_pending_status) { 1418 ehci_root_hub_reset_occured(ehcip); 1419 } 1420 1421 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1422 "ehci_handle_root_hub_pipe_start_intr_polling: " 1423 "Start polling for root hub successful"); 1424 1425 break; 1426 case EHCI_PIPE_STATE_ACTIVE: 1427 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1428 "ehci_handle_root_hub_pipe_start_intr_polling: " 1429 "Polling for root hub is already in progress"); 1430 1431 break; 1432 default: 1433 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1434 "ehci_handle_root_hub_pipe_start_intr_polling: " 1435 "Pipe is in error state 0x%x", pipe_state); 1436 1437 error = USB_FAILURE; 1438 1439 break; 1440 } 1441 1442 return (error); 1443 } 1444 1445 1446 /* 1447 * ehci_handle_root_hub_pipe_stop_intr_polling: 1448 * 1449 * Handle stop polling on root hub intr pipe. 1450 */ 1451 /* ARGSUSED */ 1452 void 1453 ehci_handle_root_hub_pipe_stop_intr_polling( 1454 usba_pipe_handle_data_t *ph, 1455 usb_flags_t flags) 1456 { 1457 ehci_state_t *ehcip = ehci_obtain_state( 1458 ph->p_usba_device->usb_root_hub_dip); 1459 usb_ep_descr_t *eptd = &ph->p_ep; 1460 1461 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1462 1463 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1464 "ehci_handle_root_hub_pipe_stop_intr_polling: " 1465 "Root hub pipe stop polling"); 1466 1467 ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1); 1468 1469 if (ehcip->ehci_root_hub.rh_intr_pipe_state == 1470 EHCI_PIPE_STATE_ACTIVE) { 1471 1472 ehcip->ehci_root_hub.rh_intr_pipe_state = 1473 EHCI_PIPE_STATE_STOP_POLLING; 1474 1475 /* Do interrupt pipe cleanup */ 1476 ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_STOPPED_POLLING); 1477 1478 ASSERT(ehcip->ehci_root_hub. 1479 rh_intr_pipe_state == EHCI_PIPE_STATE_IDLE); 1480 1481 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1482 "ehci_hcdi_pipe_stop_intr_polling: Stop polling for root" 1483 "hub successful"); 1484 } else { 1485 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, 1486 ehcip->ehci_log_hdl, "ehci_hcdi_pipe_stop_intr_polling: " 1487 "Polling for root hub is already stopped"); 1488 } 1489 } 1490 1491 1492 /* 1493 * ehci_get_root_hub_port_status: 1494 * 1495 * Construct root hub port status and change information 1496 */ 1497 static uint_t 1498 ehci_get_root_hub_port_status( 1499 ehci_state_t *ehcip, 1500 uint16_t port) 1501 { 1502 uint_t new_port_status = 0; 1503 uint_t change_status = 0; 1504 uint_t port_status; 1505 1506 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1507 1508 /* Read the current port status */ 1509 port_status = Get_OpReg(ehci_rh_port_status[port]); 1510 1511 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1512 "ehci_get_root_hub_port_status: port %d " 1513 "port status = 0x%x", port, port_status); 1514 1515 /* 1516 * EHCI root hub port status and control register information 1517 * format is different what Hub driver wants. So EHCI driver 1518 * needs to contruct the proper root hub port status information. 1519 * 1520 * Send all port status information only if port is owned by EHCI 1521 * host controller. 1522 */ 1523 if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_EHCI) { 1524 1525 /* First construct port change information */ 1526 if (port_status & EHCI_RH_PORT_ENABLE_CHANGE) { 1527 change_status |= PORT_CHANGE_PESC; 1528 } 1529 1530 if (port_status & EHCI_RH_PORT_RESUME) { 1531 change_status |= PORT_CHANGE_PSSC; 1532 } 1533 1534 if (port_status & EHCI_RH_PORT_OVER_CURR_CHANGE) { 1535 change_status |= PORT_CHANGE_OCIC; 1536 } 1537 1538 /* Now construct port status information */ 1539 if (port_status & EHCI_RH_PORT_CONNECT_STATUS) { 1540 new_port_status |= PORT_STATUS_CCS; 1541 } 1542 1543 if (port_status & EHCI_RH_PORT_ENABLE) { 1544 new_port_status |= 1545 (PORT_STATUS_PES | PORT_STATUS_HSDA); 1546 } 1547 1548 if (port_status & EHCI_RH_PORT_SUSPEND) { 1549 new_port_status |= PORT_STATUS_PSS; 1550 } 1551 1552 if (port_status & EHCI_RH_PORT_OVER_CURR_ACTIVE) { 1553 new_port_status |= PORT_STATUS_POCI; 1554 } 1555 1556 if (port_status & EHCI_RH_PORT_RESET) { 1557 new_port_status |= PORT_STATUS_PRS; 1558 } 1559 1560 if (port_status & EHCI_RH_PORT_INDICATOR) { 1561 new_port_status |= PORT_STATUS_PIC; 1562 } 1563 } 1564 1565 /* 1566 * Send the following port status and change information 1567 * even if port is not owned by EHCI. 1568 * 1569 * Additional port change information. 1570 */ 1571 if (port_status & EHCI_RH_PORT_CONNECT_STS_CHANGE) { 1572 change_status |= PORT_CHANGE_CSC; 1573 } 1574 1575 /* Additional port status information */ 1576 if (port_status & EHCI_RH_PORT_POWER) { 1577 new_port_status |= PORT_STATUS_PPS; 1578 } 1579 1580 if ((!(port_status & EHCI_RH_PORT_ENABLE)) && 1581 (port_status & EHCI_RH_PORT_LOW_SPEED)) { 1582 new_port_status |= PORT_STATUS_LSDA; 1583 } 1584 1585 /* 1586 * Construct complete root hub port status and change information. 1587 */ 1588 port_status = ((change_status << 16) | new_port_status); 1589 1590 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1591 "ehci_get_root_hub_port_status: port = %d new status = 0x%x " 1592 "change status = 0x%x complete port status 0x%x", port, 1593 new_port_status, change_status, port_status); 1594 1595 return (port_status); 1596 } 1597 1598 1599 /* 1600 * ehci_is_port_owner: 1601 * 1602 * Check whether given port is owned by ehci. 1603 */ 1604 static int 1605 ehci_is_port_owner( 1606 ehci_state_t *ehcip, 1607 uint16_t port) 1608 { 1609 uint_t port_status; 1610 1611 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1612 1613 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1614 ~EHCI_RH_PORT_CLEAR_MASK; 1615 1616 /* 1617 * Don't perform anything if port is owned by classis host 1618 * controller and return success. 1619 */ 1620 if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_CLASSIC) { 1621 1622 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1623 "ehci_handle_set_clear_port_feature: " 1624 "Port %d is owned by classic host controller", port); 1625 1626 return (USB_FAILURE); 1627 } 1628 1629 return (USB_SUCCESS); 1630 } 1631 1632 1633 /* 1634 * ehci_root_hub_allocate_intr_pipe_resource: 1635 * 1636 * Allocate interrupt requests and initialize them. 1637 */ 1638 static int 1639 ehci_root_hub_allocate_intr_pipe_resource( 1640 ehci_state_t *ehcip, 1641 usb_flags_t flags) 1642 { 1643 usba_pipe_handle_data_t *ph; 1644 size_t length; 1645 usb_intr_req_t *curr_intr_reqp; 1646 1647 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1648 "ehci_root_hub_allocate_intr_pipe_resource"); 1649 1650 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1651 1652 /* Get the interrupt pipe handle */ 1653 ph = ehcip->ehci_root_hub.rh_intr_pipe_handle; 1654 1655 /* Get the current interrupt request pointer */ 1656 curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp; 1657 1658 /* 1659 * If current interrupt request pointer is null, 1660 * allocate new interrupt request. 1661 */ 1662 if (curr_intr_reqp == NULL) { 1663 ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp); 1664 1665 /* Get the length of interrupt transfer */ 1666 length = ehcip->ehci_root_hub. 1667 rh_client_intr_reqp->intr_len; 1668 1669 curr_intr_reqp = usba_hcdi_dup_intr_req(ph->p_dip, 1670 ehcip->ehci_root_hub.rh_client_intr_reqp, 1671 length, flags); 1672 1673 if (curr_intr_reqp == NULL) { 1674 1675 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1676 "ehci_root_hub_allocate_intr_pipe_resource:" 1677 "Interrupt request structure allocation failed"); 1678 1679 return (USB_NO_RESOURCES); 1680 } 1681 1682 ehcip->ehci_root_hub.rh_curr_intr_reqp = curr_intr_reqp; 1683 mutex_enter(&ph->p_mutex); 1684 ph->p_req_count++; 1685 mutex_exit(&ph->p_mutex); 1686 } 1687 1688 /* Start the timer for the root hub interrupt pipe polling */ 1689 if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0) { 1690 ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 1691 timeout(ehci_handle_root_hub_status_change, 1692 (void *)ehcip, drv_usectohz(EHCI_RH_POLL_TIME)); 1693 1694 ehcip->ehci_root_hub. 1695 rh_intr_pipe_state = EHCI_PIPE_STATE_ACTIVE; 1696 } 1697 1698 return (USB_SUCCESS); 1699 } 1700 1701 1702 /* 1703 * ehci_root_hub_intr_pipe_cleanup: 1704 * 1705 * Deallocate all interrupt requests and do callback 1706 * the original client interrupt request. 1707 */ 1708 static void 1709 ehci_root_hub_intr_pipe_cleanup( 1710 ehci_state_t *ehcip, 1711 usb_cr_t completion_reason) 1712 { 1713 usb_intr_req_t *curr_intr_reqp; 1714 usb_opaque_t client_intr_reqp; 1715 timeout_id_t timer_id; 1716 usba_pipe_handle_data_t *ph; 1717 1718 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1719 "ehci_root_hub_intr_pipe_cleanup"); 1720 1721 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1722 1723 /* Get the interrupt pipe handle */ 1724 ph = ehcip->ehci_root_hub.rh_intr_pipe_handle; 1725 1726 /* Get the interrupt timerid */ 1727 timer_id = ehcip->ehci_root_hub.rh_intr_pipe_timer_id; 1728 1729 /* Stop the root hub interrupt timer */ 1730 if (timer_id) { 1731 /* Reset the timer id to zero */ 1732 ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0; 1733 1734 mutex_exit(&ehcip->ehci_int_mutex); 1735 (void) untimeout(timer_id); 1736 mutex_enter(&ehcip->ehci_int_mutex); 1737 } 1738 1739 /* Reset the current interrupt request pointer */ 1740 curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp; 1741 1742 /* Deallocate uncompleted interrupt request */ 1743 if (curr_intr_reqp) { 1744 ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL; 1745 usb_free_intr_req(curr_intr_reqp); 1746 1747 mutex_enter(&ph->p_mutex); 1748 ph->p_req_count--; 1749 mutex_exit(&ph->p_mutex); 1750 } 1751 1752 client_intr_reqp = (usb_opaque_t) 1753 ehcip->ehci_root_hub.rh_client_intr_reqp; 1754 1755 /* Callback for original client interrupt request */ 1756 if (client_intr_reqp) { 1757 ehci_root_hub_hcdi_callback(ph, completion_reason); 1758 } 1759 } 1760 1761 1762 /* 1763 * ehci_handle_root_hub_status_change: 1764 * 1765 * A root hub status change interrupt will occur any time there is a change 1766 * in the root hub status register or one of the port status registers. 1767 */ 1768 static void 1769 ehci_handle_root_hub_status_change(void *arg) 1770 { 1771 ehci_state_t *ehcip = (ehci_state_t *)arg; 1772 usb_hub_descr_t *root_hub_descr = 1773 &ehcip->ehci_root_hub.rh_descr; 1774 usb_intr_req_t *curr_intr_reqp; 1775 usb_port_mask_t port_mask = 0; 1776 uint_t new_port_status; 1777 uint_t change_status; 1778 uint_t port_status; 1779 mblk_t *message; 1780 size_t length; 1781 usb_ep_descr_t *eptd; 1782 usba_pipe_handle_data_t *ph; 1783 int i; 1784 1785 mutex_enter(&ehcip->ehci_int_mutex); 1786 1787 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1788 "ehci_handle_root_hub_status_change: state = %d", 1789 ehcip->ehci_root_hub.rh_intr_pipe_state); 1790 1791 /* Get the current interrupt request pointer */ 1792 curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp; 1793 1794 ph = ehcip->ehci_root_hub.rh_intr_pipe_handle; 1795 1796 /* Check whether timeout handler is valid */ 1797 if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id) { 1798 /* Check host controller is in operational state */ 1799 if ((ehci_state_is_operational(ehcip)) != USB_SUCCESS) { 1800 /* Reset the timer id */ 1801 ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0; 1802 1803 /* Do interrupt pipe cleanup */ 1804 ehci_root_hub_intr_pipe_cleanup( 1805 ehcip, USB_CR_HC_HARDWARE_ERR); 1806 1807 mutex_exit(&ehcip->ehci_int_mutex); 1808 1809 return; 1810 } 1811 } else { 1812 mutex_exit(&ehcip->ehci_int_mutex); 1813 1814 return; 1815 } 1816 1817 eptd = &ehcip->ehci_root_hub.rh_intr_pipe_handle->p_ep; 1818 1819 /* Check each port */ 1820 for (i = 0; i < root_hub_descr->bNbrPorts; i++) { 1821 1822 port_status = ehci_get_root_hub_port_status(ehcip, i); 1823 1824 new_port_status = port_status & PORT_STATUS_MASK; 1825 change_status = (port_status >> 16) & PORT_CHANGE_MASK; 1826 1827 /* 1828 * If there is change in the port status then set the bit in the 1829 * bitmap of changes and inform hub driver about these changes. 1830 * Hub driver will take care of these changes. 1831 */ 1832 if (change_status) { 1833 1834 /* See if a device was attached/detached */ 1835 if (change_status & PORT_CHANGE_CSC) { 1836 /* 1837 * Update the state depending on whether 1838 * the port was attached or detached. 1839 */ 1840 if (new_port_status & PORT_STATUS_CCS) { 1841 ehcip->ehci_root_hub. 1842 rh_port_state[i] = DISABLED; 1843 1844 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1845 ehcip->ehci_log_hdl, 1846 "Port %d connected", i); 1847 } else { 1848 ehcip->ehci_root_hub. 1849 rh_port_state[i] = DISCONNECTED; 1850 1851 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1852 ehcip->ehci_log_hdl, 1853 "Port %d disconnected", i); 1854 } 1855 } 1856 1857 /* See if port enable status changed */ 1858 if (change_status & PORT_CHANGE_PESC) { 1859 /* 1860 * Update the state depending on whether 1861 * the port was enabled or disabled. 1862 */ 1863 if (new_port_status & PORT_STATUS_PES) { 1864 ehcip->ehci_root_hub. 1865 rh_port_state[i] = ENABLED; 1866 1867 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1868 ehcip->ehci_log_hdl, 1869 "Port %d enabled", i); 1870 } else { 1871 ehcip->ehci_root_hub. 1872 rh_port_state[i] = DISABLED; 1873 1874 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1875 ehcip->ehci_log_hdl, 1876 "Port %d disabled", i); 1877 } 1878 } 1879 1880 port_mask |= 1 << (i + 1); 1881 1882 /* Update the status */ 1883 ehcip->ehci_root_hub. 1884 rh_port_status[i] = new_port_status; 1885 } 1886 } 1887 1888 if (ph && port_mask && curr_intr_reqp) { 1889 length = eptd->wMaxPacketSize; 1890 1891 ASSERT(length != 0); 1892 1893 /* Get the message block */ 1894 message = curr_intr_reqp->intr_data; 1895 1896 ASSERT(message != NULL); 1897 1898 do { 1899 *message->b_wptr++ = (uchar_t)port_mask; 1900 port_mask >>= 8; 1901 } while (port_mask != 0); 1902 1903 ehci_root_hub_hcdi_callback(ph, USB_CR_OK); 1904 } 1905 1906 /* Reset the timer id */ 1907 ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0; 1908 1909 if (ehcip->ehci_root_hub.rh_intr_pipe_state == 1910 EHCI_PIPE_STATE_ACTIVE) { 1911 /* 1912 * If needed, allocate new interrupt request. Also 1913 * start the timer for the root hub interrupt polling. 1914 */ 1915 if ((ehci_root_hub_allocate_intr_pipe_resource( 1916 ehcip, 0)) != USB_SUCCESS) { 1917 1918 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1919 "ehci_handle_root_hub_status_change: No Resources"); 1920 1921 /* Do interrupt pipe cleanup */ 1922 ehci_root_hub_intr_pipe_cleanup( 1923 ehcip, USB_CR_NO_RESOURCES); 1924 } 1925 } 1926 1927 mutex_exit(&ehcip->ehci_int_mutex); 1928 } 1929 1930 1931 /* 1932 * ehci_root_hub_hcdi_callback() 1933 * 1934 * Convenience wrapper around usba_hcdi_cb() for the root hub. 1935 */ 1936 static void 1937 ehci_root_hub_hcdi_callback( 1938 usba_pipe_handle_data_t *ph, 1939 usb_cr_t completion_reason) 1940 { 1941 ehci_state_t *ehcip = ehci_obtain_state( 1942 ph->p_usba_device->usb_root_hub_dip); 1943 uchar_t attributes = ph->p_ep.bmAttributes & 1944 USB_EP_ATTR_MASK; 1945 usb_opaque_t curr_xfer_reqp; 1946 uint_t pipe_state = 0; 1947 1948 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1949 "ehci_root_hub_hcdi_callback: ph = 0x%p, cr = 0x%x", 1950 ph, completion_reason); 1951 1952 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1953 1954 /* Set the pipe state as per completion reason */ 1955 switch (completion_reason) { 1956 case USB_CR_OK: 1957 switch (attributes) { 1958 case USB_EP_ATTR_CONTROL: 1959 pipe_state = EHCI_PIPE_STATE_IDLE; 1960 break; 1961 case USB_EP_ATTR_INTR: 1962 pipe_state = ehcip->ehci_root_hub. 1963 rh_intr_pipe_state; 1964 break; 1965 } 1966 break; 1967 case USB_CR_NO_RESOURCES: 1968 case USB_CR_NOT_SUPPORTED: 1969 case USB_CR_STOPPED_POLLING: 1970 case USB_CR_PIPE_RESET: 1971 case USB_CR_HC_HARDWARE_ERR: 1972 /* Set pipe state to idle */ 1973 pipe_state = EHCI_PIPE_STATE_IDLE; 1974 break; 1975 case USB_CR_PIPE_CLOSING: 1976 break; 1977 default: 1978 /* Set pipe state to error */ 1979 pipe_state = EHCI_PIPE_STATE_ERROR; 1980 break; 1981 } 1982 1983 switch (attributes) { 1984 case USB_EP_ATTR_CONTROL: 1985 curr_xfer_reqp = (usb_opaque_t) 1986 ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1987 1988 ehcip->ehci_root_hub.rh_curr_ctrl_reqp = NULL; 1989 ehcip->ehci_root_hub.rh_ctrl_pipe_state = pipe_state; 1990 break; 1991 case USB_EP_ATTR_INTR: 1992 /* if curr_intr_reqp available then use this request */ 1993 if (ehcip->ehci_root_hub.rh_curr_intr_reqp) { 1994 curr_xfer_reqp = (usb_opaque_t)ehcip-> 1995 ehci_root_hub.rh_curr_intr_reqp; 1996 1997 ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL; 1998 } else { 1999 /* no current request, use client's request */ 2000 curr_xfer_reqp = (usb_opaque_t) 2001 ehcip->ehci_root_hub.rh_client_intr_reqp; 2002 2003 ehcip->ehci_root_hub.rh_client_intr_reqp = NULL; 2004 } 2005 ehcip->ehci_root_hub.rh_intr_pipe_state = pipe_state; 2006 break; 2007 } 2008 2009 ASSERT(curr_xfer_reqp != NULL); 2010 2011 mutex_exit(&ehcip->ehci_int_mutex); 2012 usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason); 2013 mutex_enter(&ehcip->ehci_int_mutex); 2014 } 2015