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