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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /* 28 * EHCI Host Controller Driver (EHCI) 29 * 30 * The EHCI driver is a software driver which interfaces to the Universal 31 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to 32 * the Host Controller is defined by the EHCI Host Controller Interface. 33 * 34 * This module contains the code for root hub related functions. 35 * 36 * NOTE: 37 * 38 * ONE_XFER is not supported on root hub interrupt polling 39 */ 40 41 #include <sys/usb/hcd/ehci/ehcid.h> 42 #include <sys/usb/hcd/ehci/ehci_util.h> 43 #include <sys/usb/usba/usba_types.h> 44 45 /* Static function prototypes */ 46 static int ehci_handle_set_clear_port_feature( 47 ehci_state_t *ehcip, 48 uchar_t bRequest, 49 uint16_t wValue, 50 uint16_t port); 51 static void ehci_handle_port_power( 52 ehci_state_t *ehcip, 53 uint16_t port, 54 uint_t on); 55 static void ehci_handle_port_enable( 56 ehci_state_t *ehcip, 57 uint16_t port, 58 uint_t on); 59 static void ehci_handle_clrchng_port_enable( 60 ehci_state_t *ehcip, 61 uint16_t port); 62 static void ehci_handle_port_suspend( 63 ehci_state_t *ehcip, 64 uint16_t port, 65 uint_t on); 66 static void ehci_handle_clrchng_port_suspend( 67 ehci_state_t *ehcip, 68 uint16_t port); 69 static void ehci_handle_port_reset( 70 ehci_state_t *ehcip, 71 uint16_t port); 72 static void ehci_root_hub_reset_occured( 73 ehci_state_t *ehcip); 74 static void ehci_handle_complete_port_reset( 75 ehci_state_t *ehcip, 76 uint16_t port); 77 static void ehci_handle_clear_port_connection( 78 ehci_state_t *ehcip, 79 uint16_t port); 80 static void ehci_handle_clrchng_port_over_current( 81 ehci_state_t *ehcip, 82 uint16_t port); 83 static void ehci_handle_get_port_status( 84 ehci_state_t *ehcip, 85 uint16_t port); 86 static void ehci_handle_get_hub_descriptor( 87 ehci_state_t *ehcip); 88 static void ehci_handle_get_hub_status( 89 ehci_state_t *ehcip); 90 static void ehci_handle_get_device_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 HUB_GET_DEVICE_STATUS_TYPE: 554 ehci_handle_get_device_status(ehcip); 555 break; 556 case HUB_HANDLE_PORT_FEATURE_TYPE: 557 error = ehci_handle_set_clear_port_feature(ehcip, 558 bRequest, wValue, port); 559 break; 560 case HUB_GET_PORT_STATUS_TYPE: 561 ehci_handle_get_port_status(ehcip, port); 562 break; 563 case HUB_CLASS_REQ_TYPE: 564 switch (bRequest) { 565 case USB_REQ_GET_STATUS: 566 ehci_handle_get_hub_status(ehcip); 567 break; 568 case USB_REQ_GET_DESCR: 569 ehci_handle_get_hub_descriptor(ehcip); 570 break; 571 default: 572 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 573 "ehci_handle_root_hub_request:" 574 "Unsupported request 0x%x", bRequest); 575 576 error = USB_FAILURE; 577 break; 578 } 579 break; 580 default: 581 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 582 "ehci_handle_root_hub_request: " 583 "Unsupported request 0x%x", bmRequestType); 584 585 error = USB_FAILURE; 586 break; 587 } 588 589 completion_reason = (error) ? USB_CR_NOT_SUPPORTED : USB_CR_OK; 590 591 mutex_enter(&ehcip->ehci_int_mutex); 592 ehci_root_hub_hcdi_callback(ph, completion_reason); 593 mutex_exit(&ehcip->ehci_int_mutex); 594 595 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 596 "ehci_handle_root_hub_request: error = %d", error); 597 598 return (USB_SUCCESS); 599 } 600 601 602 /* 603 * ehci_handle_set_clear_port_feature: 604 */ 605 static int 606 ehci_handle_set_clear_port_feature( 607 ehci_state_t *ehcip, 608 uchar_t bRequest, 609 uint16_t wValue, 610 uint16_t port) 611 { 612 int error = USB_SUCCESS; 613 614 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 615 "ehci_handle_set_clear_port_feature: 0x%x 0x%x 0x%x", 616 bRequest, wValue, port); 617 618 switch (bRequest) { 619 case USB_REQ_SET_FEATURE: 620 switch (wValue) { 621 case CFS_PORT_ENABLE: 622 ehci_handle_port_enable(ehcip, port, 1); 623 break; 624 case CFS_PORT_SUSPEND: 625 ehci_handle_port_suspend(ehcip, port, 1); 626 break; 627 case CFS_PORT_RESET: 628 ehci_handle_port_reset(ehcip, port); 629 break; 630 case CFS_PORT_POWER: 631 ehci_handle_port_power(ehcip, port, 1); 632 break; 633 default: 634 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 635 "ehci_handle_set_clear_port_feature: " 636 "Unsupported request 0x%x 0x%x", bRequest, wValue); 637 638 error = USB_FAILURE; 639 break; 640 } 641 break; 642 case USB_REQ_CLEAR_FEATURE: 643 switch (wValue) { 644 case CFS_PORT_ENABLE: 645 ehci_handle_port_enable(ehcip, port, 0); 646 break; 647 case CFS_C_PORT_ENABLE: 648 ehci_handle_clrchng_port_enable(ehcip, port); 649 break; 650 case CFS_PORT_SUSPEND: 651 ehci_handle_port_suspend(ehcip, port, 0); 652 break; 653 case CFS_C_PORT_SUSPEND: 654 ehci_handle_clrchng_port_suspend(ehcip, port); 655 break; 656 case CFS_C_PORT_RESET: 657 ehci_handle_complete_port_reset(ehcip, port); 658 break; 659 case CFS_PORT_POWER: 660 ehci_handle_port_power(ehcip, port, 0); 661 break; 662 case CFS_C_PORT_CONNECTION: 663 ehci_handle_clear_port_connection(ehcip, port); 664 break; 665 case CFS_C_PORT_OVER_CURRENT: 666 ehci_handle_clrchng_port_over_current(ehcip, port); 667 break; 668 default: 669 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 670 "ehci_handle_set_clear_port_feature: " 671 "Unsupported request 0x%x 0x%x", bRequest, wValue); 672 673 error = USB_FAILURE; 674 break; 675 } 676 break; 677 default: 678 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 679 "ehci_handle_set_clear_port_feature: " 680 "Unsupported request 0x%x 0x%x", bRequest, wValue); 681 682 error = USB_FAILURE; 683 break; 684 } 685 686 return (error); 687 } 688 689 690 /* 691 * ehci_handle_port_power: 692 * 693 * Turn on a root hub port. 694 */ 695 static void 696 ehci_handle_port_power( 697 ehci_state_t *ehcip, 698 uint16_t port, 699 uint_t on) 700 { 701 uint_t port_status; 702 ehci_root_hub_t *rh; 703 704 mutex_enter(&ehcip->ehci_int_mutex); 705 706 port_status = Get_OpReg(ehci_rh_port_status[port]) & 707 ~EHCI_RH_PORT_CLEAR_MASK; 708 709 rh = &ehcip->ehci_root_hub; 710 711 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 712 "ehci_handle_port_power: port = 0x%x status = 0x%x on = %d", 713 port, port_status, on); 714 715 /* Check port is owned by ehci */ 716 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 717 mutex_exit(&ehcip->ehci_int_mutex); 718 719 return; 720 } 721 722 if (on) { 723 /* See if the port power is already on */ 724 if (!(port_status & EHCI_RH_PORT_POWER)) { 725 /* Turn the port on */ 726 Set_OpReg(ehci_rh_port_status[port], 727 port_status | EHCI_RH_PORT_POWER); 728 } 729 730 rh->rh_port_status[port] = 0; 731 rh->rh_port_state[port] = DISCONNECTED; 732 } else { 733 /* See if the port power is already OFF */ 734 if (port_status & EHCI_RH_PORT_POWER) { 735 /* Turn-off the port */ 736 Set_OpReg(ehci_rh_port_status[port], 737 port_status & ~EHCI_RH_PORT_POWER); 738 } 739 740 rh->rh_port_status[port] = 0; 741 rh->rh_port_state[port] = POWERED_OFF; 742 } 743 744 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 745 "ehci_handle_port_power done: port = 0x%x status = 0x%x on = %d", 746 port, Get_OpReg(ehci_rh_port_status[port]), on); 747 748 mutex_exit(&ehcip->ehci_int_mutex); 749 } 750 751 752 /* 753 * ehci_handle_port_enable: 754 * 755 * Handle port enable request. 756 */ 757 static void 758 ehci_handle_port_enable( 759 ehci_state_t *ehcip, 760 uint16_t port, 761 uint_t on) 762 { 763 uint_t port_status; 764 765 mutex_enter(&ehcip->ehci_int_mutex); 766 767 port_status = Get_OpReg(ehci_rh_port_status[port]) & 768 ~EHCI_RH_PORT_CLEAR_MASK; 769 770 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 771 "ehci_handle_port_enable: port = 0x%x, status = 0x%x", 772 port, port_status); 773 774 /* Check port is owned by ehci */ 775 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 776 mutex_exit(&ehcip->ehci_int_mutex); 777 778 return; 779 } 780 781 if (on) { 782 /* See if the port enable is already on */ 783 if (!(port_status & EHCI_RH_PORT_ENABLE)) { 784 /* Enable the port */ 785 Set_OpReg(ehci_rh_port_status[port], 786 port_status | EHCI_RH_PORT_ENABLE); 787 } 788 } else { 789 /* See if the port enable is already off */ 790 if (port_status & EHCI_RH_PORT_ENABLE) { 791 /* Disable the port */ 792 Set_OpReg(ehci_rh_port_status[port], 793 port_status & ~EHCI_RH_PORT_ENABLE); 794 } 795 } 796 797 mutex_exit(&ehcip->ehci_int_mutex); 798 } 799 800 801 /* 802 * ehci_handle_clrchng_port_enable: 803 * 804 * Handle clear port enable change bit. 805 */ 806 static void 807 ehci_handle_clrchng_port_enable( 808 ehci_state_t *ehcip, 809 uint16_t port) 810 { 811 uint_t port_status; 812 813 mutex_enter(&ehcip->ehci_int_mutex); 814 815 port_status = Get_OpReg(ehci_rh_port_status[port]) & 816 ~EHCI_RH_PORT_CLEAR_MASK; 817 818 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 819 "ehci_handle_port_enable: port = 0x%x, status = 0x%x", 820 port, port_status); 821 822 /* Check port is owned by ehci */ 823 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 824 mutex_exit(&ehcip->ehci_int_mutex); 825 826 return; 827 } 828 829 /* Clear the PortEnableStatusChange Bit */ 830 Set_OpReg(ehci_rh_port_status[port], 831 port_status | EHCI_RH_PORT_ENABLE_CHANGE); 832 833 mutex_exit(&ehcip->ehci_int_mutex); 834 } 835 836 837 /* 838 * ehci_handle_port_suspend: 839 * 840 * Handle port suspend/resume request. 841 */ 842 static void 843 ehci_handle_port_suspend( 844 ehci_state_t *ehcip, 845 uint16_t port, 846 uint_t on) 847 { 848 uint_t port_status; 849 850 mutex_enter(&ehcip->ehci_int_mutex); 851 852 port_status = Get_OpReg(ehci_rh_port_status[port]) & 853 ~EHCI_RH_PORT_CLEAR_MASK; 854 855 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 856 "ehci_handle_port_suspend: port = 0x%x, status = 0x%x", 857 port, port_status); 858 859 /* Check port is owned by ehci */ 860 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 861 mutex_exit(&ehcip->ehci_int_mutex); 862 863 return; 864 } 865 866 if (on) { 867 /* 868 * Suspend port only if port is enabled and 869 * it is not already in suspend state. 870 */ 871 if ((port_status & EHCI_RH_PORT_ENABLE) && 872 (!(port_status & EHCI_RH_PORT_SUSPEND))) { 873 /* Suspend the port */ 874 Set_OpReg(ehci_rh_port_status[port], 875 port_status | EHCI_RH_PORT_SUSPEND); 876 877 mutex_exit(&ehcip->ehci_int_mutex); 878 879 /* Wait 10ms for port move to suspend state */ 880 delay(drv_usectohz(EHCI_PORT_SUSPEND_TIMEWAIT)); 881 882 return; 883 } 884 } else { 885 /* Perform resume only if port is in suspend state */ 886 if (port_status & EHCI_RH_PORT_SUSPEND) { 887 /* Resume the port */ 888 Set_OpReg(ehci_rh_port_status[port], 889 port_status | EHCI_RH_PORT_RESUME); 890 } 891 } 892 893 mutex_exit(&ehcip->ehci_int_mutex); 894 } 895 896 897 /* 898 * ehci_handle_clrchng_port_suspend: 899 * 900 * Handle port clear port suspend change bit. 901 */ 902 static void 903 ehci_handle_clrchng_port_suspend( 904 ehci_state_t *ehcip, 905 uint16_t port) 906 { 907 uint_t port_status; 908 909 mutex_enter(&ehcip->ehci_int_mutex); 910 911 port_status = Get_OpReg(ehci_rh_port_status[port]) & 912 ~EHCI_RH_PORT_CLEAR_MASK; 913 914 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 915 "ehci_handle_clrchng_port_suspend: port = 0x%x, " 916 "status = 0x%x", port, port_status); 917 918 /* Check port is owned by ehci */ 919 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 920 mutex_exit(&ehcip->ehci_int_mutex); 921 922 return; 923 } 924 925 /* Return if port is not in resume state */ 926 if (!(port_status & EHCI_RH_PORT_RESUME)) { 927 mutex_exit(&ehcip->ehci_int_mutex); 928 929 return; 930 } 931 932 mutex_exit(&ehcip->ehci_int_mutex); 933 934 /* Wait for 20ms to terminate resume */ 935 delay(drv_usectohz(EHCI_PORT_RESUME_TIMEWAIT)); 936 937 mutex_enter(&ehcip->ehci_int_mutex); 938 939 Set_OpReg(ehci_rh_port_status[port], 940 port_status & ~EHCI_RH_PORT_RESUME); 941 942 mutex_exit(&ehcip->ehci_int_mutex); 943 944 /* Wait 2ms for port to return to high speed mode */ 945 delay(drv_usectohz(EHCI_PORT_RESUME_COMP_TIMEWAIT)); 946 } 947 948 949 /* 950 * ehci_handle_port_reset: 951 * 952 * Perform a port reset. 953 */ 954 static void 955 ehci_handle_port_reset( 956 ehci_state_t *ehcip, 957 uint16_t port) 958 { 959 ehci_root_hub_t *rh; 960 uint_t port_status; 961 962 mutex_enter(&ehcip->ehci_int_mutex); 963 964 /* Get the root hub structure */ 965 rh = &ehcip->ehci_root_hub; 966 967 /* Get the port status information */ 968 port_status = Get_OpReg(ehci_rh_port_status[port]) & 969 ~EHCI_RH_PORT_CLEAR_MASK; 970 971 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 972 "ehci_handle_port_reset: port = 0x%x status = 0x%x", 973 port, port_status); 974 975 /* Check port is owned by ehci */ 976 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 977 mutex_exit(&ehcip->ehci_int_mutex); 978 979 return; 980 } 981 982 if (port_status & EHCI_RH_PORT_LOW_SPEED) { 983 /* Check for classic or companion host controllers */ 984 if (rh->rh_companion_controllers) { 985 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 986 "ehci_handle_port_reset: Low speed device " 987 "and handover this port to Companion controller"); 988 989 Set_OpReg(ehci_rh_port_status[port], 990 port_status | EHCI_RH_PORT_OWNER_CLASSIC); 991 } else { 992 USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 993 "Low speed device is not supported"); 994 } 995 } else { 996 Set_OpReg(ehci_rh_port_status[port], 997 ((port_status | EHCI_RH_PORT_RESET) & 998 ~EHCI_RH_PORT_ENABLE)); 999 1000 mutex_exit(&ehcip->ehci_int_mutex); 1001 1002 /* Wait 20ms for reset to complete */ 1003 delay(drv_usectohz(EHCI_PORT_RESET_TIMEWAIT)); 1004 1005 mutex_enter(&ehcip->ehci_int_mutex); 1006 1007 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1008 ~EHCI_RH_PORT_CLEAR_MASK; 1009 1010 Set_OpReg(ehci_rh_port_status[port], 1011 (port_status & ~EHCI_RH_PORT_RESET)); 1012 1013 mutex_exit(&ehcip->ehci_int_mutex); 1014 1015 /* 1016 * Wait 2ms for hardware to enable this port 1017 * if connected usb device is high speed. 1018 */ 1019 delay(drv_usectohz(EHCI_PORT_RESET_COMP_TIMEWAIT)); 1020 1021 mutex_enter(&ehcip->ehci_int_mutex); 1022 1023 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1024 ~EHCI_RH_PORT_CLEAR_MASK; 1025 1026 /* 1027 * If port is not enabled, connected device is a 1028 * Full-speed usb device. 1029 */ 1030 if (!(port_status & EHCI_RH_PORT_ENABLE)) { 1031 /* Check for classic or companion host controllers */ 1032 if (rh->rh_companion_controllers) { 1033 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1034 ehcip->ehci_log_hdl, 1035 "ehci_handle_port_reset: Full speed device " 1036 "and handover this port to Companion host " 1037 "controller"); 1038 1039 Set_OpReg(ehci_rh_port_status[port], 1040 port_status | EHCI_RH_PORT_OWNER_CLASSIC); 1041 } else { 1042 USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB, 1043 ehcip->ehci_log_hdl, 1044 "Full speed device is not supported"); 1045 } 1046 } else { 1047 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1048 "ehci_handle_port_reset: High speed device "); 1049 1050 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1051 ~EHCI_RH_PORT_CLEAR_MASK; 1052 1053 /* 1054 * Enable over-current, connect, and disconnect 1055 * wakeup bits. 1056 */ 1057 Set_OpReg(ehci_rh_port_status[port], (port_status | 1058 EHCI_RH_PORT_OVER_CURENT_ENABLE | 1059 EHCI_RH_PORT_DISCONNECT_ENABLE | 1060 EHCI_RH_PORT_CONNECT_ENABLE)); 1061 1062 /* 1063 * The next function is only called if the interrupt 1064 * pipe is polling and the USBA is ready to receive 1065 * the data. 1066 */ 1067 ehcip->ehci_root_hub. 1068 rh_intr_pending_status |= (1 << port); 1069 1070 if (ehcip->ehci_root_hub. 1071 rh_intr_pipe_state == EHCI_PIPE_STATE_ACTIVE) { 1072 1073 ehci_root_hub_reset_occured(ehcip); 1074 } 1075 } 1076 } 1077 1078 mutex_exit(&ehcip->ehci_int_mutex); 1079 } 1080 1081 1082 /* 1083 * ehci_root_hub_reset_occured: 1084 * 1085 * Inform the upper layer that reset has occured on the port. This is 1086 * required because the upper layer is expecting a an evernt immidiately 1087 * after doing reset. In case of OHCI, the controller gets an interrupt 1088 * for the change in the root hub status but in case of EHCI, we dont. 1089 * So, send a event to the upper layer as soon as we complete the reset. 1090 */ 1091 void 1092 ehci_root_hub_reset_occured( 1093 ehci_state_t *ehcip) 1094 { 1095 usb_intr_req_t *curr_intr_reqp = 1096 ehcip->ehci_root_hub.rh_curr_intr_reqp; 1097 usb_port_mask_t port_mask; 1098 usba_pipe_handle_data_t *ph; 1099 1100 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1101 "ehci_root_hub_reset_occured: curr_intr_reqp = 0x%p data = 0x%p", 1102 (void *)curr_intr_reqp, (void *)curr_intr_reqp->intr_data); 1103 1104 /* Get the interrupt pipe handle */ 1105 ph = ehcip->ehci_root_hub.rh_intr_pipe_handle; 1106 1107 /* Get the pending status */ 1108 port_mask = ehcip->ehci_root_hub.rh_intr_pending_status << 1; 1109 1110 do { 1111 *curr_intr_reqp->intr_data->b_wptr++ = (uchar_t)port_mask; 1112 port_mask >>= 8; 1113 } while (port_mask != 0); 1114 1115 ehci_root_hub_hcdi_callback(ph, USB_CR_OK); 1116 1117 /* Reset pending status */ 1118 ehcip->ehci_root_hub.rh_intr_pending_status = 0; 1119 1120 /* If needed, allocate new interrupt request */ 1121 if ((ehci_root_hub_allocate_intr_pipe_resource( 1122 ehcip, 0)) != USB_SUCCESS) { 1123 1124 /* Do interrupt pipe cleanup */ 1125 ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_NO_RESOURCES); 1126 } 1127 } 1128 1129 1130 /* 1131 * ehci_handle_complete_port_reset: 1132 * 1133 * Perform a port reset change. 1134 */ 1135 static void 1136 ehci_handle_complete_port_reset( 1137 ehci_state_t *ehcip, 1138 uint16_t port) 1139 { 1140 uint_t port_status; 1141 1142 mutex_enter(&ehcip->ehci_int_mutex); 1143 1144 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1145 ~EHCI_RH_PORT_CLEAR_MASK; 1146 1147 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1148 "ehci_handle_complete_port_reset: port = 0x%x status = 0x%x", 1149 port, port_status); 1150 1151 /* Check port is owned by ehci */ 1152 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 1153 mutex_exit(&ehcip->ehci_int_mutex); 1154 1155 return; 1156 } 1157 1158 if (port_status & EHCI_RH_PORT_RESET) { 1159 Set_OpReg(ehci_rh_port_status[port], 1160 port_status & ~EHCI_RH_PORT_RESET); 1161 1162 } 1163 1164 mutex_exit(&ehcip->ehci_int_mutex); 1165 } 1166 1167 1168 /* 1169 * ehci_handle_clear_port_connection: 1170 * 1171 * Perform a clear port connection. 1172 */ 1173 static void 1174 ehci_handle_clear_port_connection( 1175 ehci_state_t *ehcip, 1176 uint16_t port) 1177 { 1178 uint_t port_status; 1179 1180 mutex_enter(&ehcip->ehci_int_mutex); 1181 1182 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1183 ~EHCI_RH_PORT_CLEAR_MASK; 1184 1185 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1186 "ehci_handle_clear_port_connection: port = 0x%x" 1187 "status = 0x%x", port, port_status); 1188 1189 Set_OpReg(ehci_rh_port_status[port], 1190 port_status | EHCI_RH_PORT_CONNECT_STS_CHANGE); 1191 1192 mutex_exit(&ehcip->ehci_int_mutex); 1193 } 1194 1195 1196 /* 1197 * ehci_handle_clrchng_port_over_current: 1198 * 1199 * Perform a clear port connection. 1200 */ 1201 static void 1202 ehci_handle_clrchng_port_over_current( 1203 ehci_state_t *ehcip, 1204 uint16_t port) 1205 { 1206 uint_t port_status; 1207 1208 mutex_enter(&ehcip->ehci_int_mutex); 1209 1210 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1211 ~EHCI_RH_PORT_CLEAR_MASK; 1212 1213 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1214 "ehci_handle_clrchng_port_over_current: port = 0x%x" 1215 "status = 0x%x", port, port_status); 1216 1217 Set_OpReg(ehci_rh_port_status[port], 1218 port_status | EHCI_RH_PORT_OVER_CURR_CHANGE); 1219 1220 mutex_exit(&ehcip->ehci_int_mutex); 1221 } 1222 1223 1224 /* 1225 * ehci_handle_get_port_status: 1226 * 1227 * Handle a get port status request. 1228 */ 1229 static void 1230 ehci_handle_get_port_status( 1231 ehci_state_t *ehcip, 1232 uint16_t port) 1233 { 1234 usb_ctrl_req_t *ctrl_reqp; 1235 mblk_t *message; 1236 uint_t new_port_status = 0; 1237 uint_t change_status = 0; 1238 uint_t port_status; 1239 1240 mutex_enter(&ehcip->ehci_int_mutex); 1241 1242 ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1243 1244 /* Get the root hub port status information */ 1245 port_status = ehci_get_root_hub_port_status(ehcip, port); 1246 1247 new_port_status = port_status & PORT_STATUS_MASK; 1248 change_status = (port_status >> 16) & PORT_CHANGE_MASK; 1249 1250 ehcip->ehci_root_hub.rh_port_status[port] = new_port_status; 1251 1252 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1253 "ehci_handle_get_port_status: port = %d new status = 0x%x" 1254 "change = 0x%x", port, new_port_status, change_status); 1255 1256 message = ctrl_reqp->ctrl_data; 1257 1258 ASSERT(message != NULL); 1259 1260 *message->b_wptr++ = (uchar_t)new_port_status; 1261 *message->b_wptr++ = (uchar_t)(new_port_status >> 8); 1262 *message->b_wptr++ = (uchar_t)change_status; 1263 *message->b_wptr++ = (uchar_t)(change_status >> 8); 1264 1265 /* Save the data in control request */ 1266 ctrl_reqp->ctrl_data = message; 1267 1268 mutex_exit(&ehcip->ehci_int_mutex); 1269 } 1270 1271 1272 /* 1273 * ehci_handle_get_hub_descriptor: 1274 */ 1275 static void 1276 ehci_handle_get_hub_descriptor( 1277 ehci_state_t *ehcip) 1278 { 1279 usb_ctrl_req_t *ctrl_reqp; 1280 mblk_t *message; 1281 usb_hub_descr_t *root_hub_descr; 1282 size_t length; 1283 uchar_t raw_descr[ROOT_HUB_DESCRIPTOR_LENGTH]; 1284 1285 mutex_enter(&ehcip->ehci_int_mutex); 1286 1287 ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1288 root_hub_descr = &ehcip->ehci_root_hub.rh_descr; 1289 length = ctrl_reqp->ctrl_wLength; 1290 1291 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1292 "ehci_handle_get_hub_descriptor: Ctrl Req = 0x%p", 1293 (void *)ctrl_reqp); 1294 1295 message = ctrl_reqp->ctrl_data; 1296 1297 ASSERT(message != NULL); 1298 1299 bzero(&raw_descr, ROOT_HUB_DESCRIPTOR_LENGTH); 1300 1301 raw_descr[0] = root_hub_descr->bDescLength; 1302 raw_descr[1] = root_hub_descr->bDescriptorType; 1303 raw_descr[2] = root_hub_descr->bNbrPorts; 1304 raw_descr[3] = root_hub_descr->wHubCharacteristics & 0x00FF; 1305 raw_descr[4] = (root_hub_descr->wHubCharacteristics & 0xFF00) >> 8; 1306 raw_descr[5] = root_hub_descr->bPwrOn2PwrGood; 1307 raw_descr[6] = root_hub_descr->bHubContrCurrent; 1308 raw_descr[7] = root_hub_descr->DeviceRemovable; 1309 raw_descr[8] = root_hub_descr->PortPwrCtrlMask; 1310 1311 bcopy(raw_descr, message->b_wptr, length); 1312 message->b_wptr += length; 1313 1314 /* Save the data in control request */ 1315 ctrl_reqp->ctrl_data = message; 1316 1317 mutex_exit(&ehcip->ehci_int_mutex); 1318 } 1319 1320 1321 /* 1322 * ehci_handle_get_hub_status: 1323 * 1324 * Handle a get hub status request. 1325 */ 1326 static void 1327 ehci_handle_get_hub_status( 1328 ehci_state_t *ehcip) 1329 { 1330 usb_ctrl_req_t *ctrl_reqp; 1331 mblk_t *message; 1332 uint_t new_root_hub_status; 1333 1334 mutex_enter(&ehcip->ehci_int_mutex); 1335 1336 ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1337 1338 /* 1339 * For EHCI, there is no overall hub status information. 1340 * Only individual root hub port status information is 1341 * available. So return zero for the root hub status 1342 * request. 1343 */ 1344 new_root_hub_status = 0; 1345 1346 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1347 "ehci_handle_get_hub_status: new root hub status = 0x%x", 1348 new_root_hub_status); 1349 1350 message = ctrl_reqp->ctrl_data; 1351 1352 ASSERT(message != NULL); 1353 1354 *message->b_wptr++ = (uchar_t)new_root_hub_status; 1355 *message->b_wptr++ = (uchar_t)(new_root_hub_status >> 8); 1356 *message->b_wptr++ = (uchar_t)(new_root_hub_status >> 16); 1357 *message->b_wptr++ = (uchar_t)(new_root_hub_status >> 24); 1358 1359 /* Save the data in control request */ 1360 ctrl_reqp->ctrl_data = message; 1361 1362 mutex_exit(&ehcip->ehci_int_mutex); 1363 } 1364 1365 1366 /* 1367 * ehci_handle_get_device_status: 1368 * 1369 * Handle a get device status request. 1370 */ 1371 static void 1372 ehci_handle_get_device_status( 1373 ehci_state_t *ehcip) 1374 { 1375 usb_ctrl_req_t *ctrl_reqp; 1376 mblk_t *message; 1377 uint16_t dev_status; 1378 1379 mutex_enter(&ehcip->ehci_int_mutex); 1380 1381 ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1382 1383 /* 1384 * For EHCI, there is no device status information. 1385 * Simply return what is desired for the request. 1386 */ 1387 dev_status = USB_DEV_SLF_PWRD_STATUS; 1388 1389 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1390 "ehci_handle_get_device_status: device status = 0x%x", 1391 dev_status); 1392 1393 message = ctrl_reqp->ctrl_data; 1394 1395 ASSERT(message != NULL); 1396 1397 *message->b_wptr++ = (uchar_t)dev_status; 1398 *message->b_wptr++ = (uchar_t)(dev_status >> 8); 1399 1400 /* Save the data in control request */ 1401 ctrl_reqp->ctrl_data = message; 1402 1403 mutex_exit(&ehcip->ehci_int_mutex); 1404 } 1405 1406 1407 /* 1408 * ehci_handle_root_hub_pipe_start_intr_polling: 1409 * 1410 * Handle start polling on root hub interrupt pipe. 1411 */ 1412 /* ARGSUSED */ 1413 int 1414 ehci_handle_root_hub_pipe_start_intr_polling( 1415 usba_pipe_handle_data_t *ph, 1416 usb_intr_req_t *client_intr_reqp, 1417 usb_flags_t flags) 1418 { 1419 ehci_state_t *ehcip = ehci_obtain_state( 1420 ph->p_usba_device->usb_root_hub_dip); 1421 usb_ep_descr_t *eptd = &ph->p_ep; 1422 int error = USB_SUCCESS; 1423 uint_t pipe_state; 1424 1425 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1426 "ehci_handle_root_hub_pipe_start_intr_polling: " 1427 "Root hub pipe start polling"); 1428 1429 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1430 1431 ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1); 1432 1433 ASSERT((client_intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) == 0); 1434 1435 pipe_state = ehcip->ehci_root_hub.rh_intr_pipe_state; 1436 1437 switch (pipe_state) { 1438 case EHCI_PIPE_STATE_IDLE: 1439 ASSERT(ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0); 1440 1441 /* 1442 * Save the Original Client's Interrupt IN request 1443 * information. We use this for final callback 1444 */ 1445 ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp == NULL); 1446 ehcip->ehci_root_hub.rh_client_intr_reqp = client_intr_reqp; 1447 1448 error = ehci_root_hub_allocate_intr_pipe_resource(ehcip, flags); 1449 1450 if (error != USB_SUCCESS) { 1451 /* Reset client interrupt request pointer */ 1452 ehcip->ehci_root_hub.rh_client_intr_reqp = NULL; 1453 1454 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1455 "ehci_handle_root_hub_pipe_start_intr_polling: " 1456 "No Resources"); 1457 1458 return (error); 1459 } 1460 1461 /* Check whether we need to send the reset data up */ 1462 if (ehcip->ehci_root_hub.rh_intr_pending_status) { 1463 ehci_root_hub_reset_occured(ehcip); 1464 } 1465 1466 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1467 "ehci_handle_root_hub_pipe_start_intr_polling: " 1468 "Start polling for root hub successful"); 1469 1470 break; 1471 case EHCI_PIPE_STATE_ACTIVE: 1472 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1473 "ehci_handle_root_hub_pipe_start_intr_polling: " 1474 "Polling for root hub is already in progress"); 1475 1476 break; 1477 default: 1478 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1479 "ehci_handle_root_hub_pipe_start_intr_polling: " 1480 "Pipe is in error state 0x%x", pipe_state); 1481 1482 error = USB_FAILURE; 1483 1484 break; 1485 } 1486 1487 return (error); 1488 } 1489 1490 1491 /* 1492 * ehci_handle_root_hub_pipe_stop_intr_polling: 1493 * 1494 * Handle stop polling on root hub intr pipe. 1495 */ 1496 /* ARGSUSED */ 1497 void 1498 ehci_handle_root_hub_pipe_stop_intr_polling( 1499 usba_pipe_handle_data_t *ph, 1500 usb_flags_t flags) 1501 { 1502 ehci_state_t *ehcip = ehci_obtain_state( 1503 ph->p_usba_device->usb_root_hub_dip); 1504 usb_ep_descr_t *eptd = &ph->p_ep; 1505 1506 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1507 1508 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1509 "ehci_handle_root_hub_pipe_stop_intr_polling: " 1510 "Root hub pipe stop polling"); 1511 1512 ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1); 1513 1514 if (ehcip->ehci_root_hub.rh_intr_pipe_state == 1515 EHCI_PIPE_STATE_ACTIVE) { 1516 1517 ehcip->ehci_root_hub.rh_intr_pipe_state = 1518 EHCI_PIPE_STATE_STOP_POLLING; 1519 1520 /* Do interrupt pipe cleanup */ 1521 ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_STOPPED_POLLING); 1522 1523 ASSERT(ehcip->ehci_root_hub. 1524 rh_intr_pipe_state == EHCI_PIPE_STATE_IDLE); 1525 1526 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1527 "ehci_hcdi_pipe_stop_intr_polling: Stop polling for root" 1528 "hub successful"); 1529 } else { 1530 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, 1531 ehcip->ehci_log_hdl, "ehci_hcdi_pipe_stop_intr_polling: " 1532 "Polling for root hub is already stopped"); 1533 } 1534 } 1535 1536 1537 /* 1538 * ehci_get_root_hub_port_status: 1539 * 1540 * Construct root hub port status and change information 1541 */ 1542 static uint_t 1543 ehci_get_root_hub_port_status( 1544 ehci_state_t *ehcip, 1545 uint16_t port) 1546 { 1547 uint_t new_port_status = 0; 1548 uint_t change_status = 0; 1549 uint_t port_status; 1550 1551 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1552 1553 /* Read the current port status */ 1554 port_status = Get_OpReg(ehci_rh_port_status[port]); 1555 1556 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1557 "ehci_get_root_hub_port_status: port %d " 1558 "port status = 0x%x", port, port_status); 1559 1560 /* 1561 * EHCI root hub port status and control register information 1562 * format is different what Hub driver wants. So EHCI driver 1563 * needs to contruct the proper root hub port status information. 1564 * 1565 * Send all port status information only if port is owned by EHCI 1566 * host controller. 1567 */ 1568 if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_EHCI) { 1569 1570 /* First construct port change information */ 1571 if (port_status & EHCI_RH_PORT_ENABLE_CHANGE) { 1572 change_status |= PORT_CHANGE_PESC; 1573 } 1574 1575 if (port_status & EHCI_RH_PORT_RESUME) { 1576 change_status |= PORT_CHANGE_PSSC; 1577 } 1578 1579 if (port_status & EHCI_RH_PORT_OVER_CURR_CHANGE) { 1580 change_status |= PORT_CHANGE_OCIC; 1581 } 1582 1583 /* Now construct port status information */ 1584 if (port_status & EHCI_RH_PORT_CONNECT_STATUS) { 1585 new_port_status |= PORT_STATUS_CCS; 1586 } 1587 1588 if (port_status & EHCI_RH_PORT_ENABLE) { 1589 new_port_status |= 1590 (PORT_STATUS_PES | PORT_STATUS_HSDA); 1591 } 1592 1593 if (port_status & EHCI_RH_PORT_SUSPEND) { 1594 new_port_status |= PORT_STATUS_PSS; 1595 } 1596 1597 if (port_status & EHCI_RH_PORT_OVER_CURR_ACTIVE) { 1598 new_port_status |= PORT_STATUS_POCI; 1599 } 1600 1601 if (port_status & EHCI_RH_PORT_RESET) { 1602 new_port_status |= PORT_STATUS_PRS; 1603 } 1604 1605 if (port_status & EHCI_RH_PORT_INDICATOR) { 1606 new_port_status |= PORT_STATUS_PIC; 1607 } 1608 } 1609 1610 /* 1611 * Send the following port status and change information 1612 * even if port is not owned by EHCI. 1613 * 1614 * Additional port change information. 1615 */ 1616 if (port_status & EHCI_RH_PORT_CONNECT_STS_CHANGE) { 1617 change_status |= PORT_CHANGE_CSC; 1618 } 1619 1620 /* Additional port status information */ 1621 if (port_status & EHCI_RH_PORT_POWER) { 1622 new_port_status |= PORT_STATUS_PPS; 1623 } 1624 1625 if ((!(port_status & EHCI_RH_PORT_ENABLE)) && 1626 (port_status & EHCI_RH_PORT_LOW_SPEED)) { 1627 new_port_status |= PORT_STATUS_LSDA; 1628 } 1629 1630 /* 1631 * Construct complete root hub port status and change information. 1632 */ 1633 port_status = ((change_status << 16) | new_port_status); 1634 1635 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1636 "ehci_get_root_hub_port_status: port = %d new status = 0x%x " 1637 "change status = 0x%x complete port status 0x%x", port, 1638 new_port_status, change_status, port_status); 1639 1640 return (port_status); 1641 } 1642 1643 1644 /* 1645 * ehci_is_port_owner: 1646 * 1647 * Check whether given port is owned by ehci. 1648 */ 1649 static int 1650 ehci_is_port_owner( 1651 ehci_state_t *ehcip, 1652 uint16_t port) 1653 { 1654 uint_t port_status; 1655 1656 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1657 1658 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1659 ~EHCI_RH_PORT_CLEAR_MASK; 1660 1661 /* 1662 * Don't perform anything if port is owned by classis host 1663 * controller and return success. 1664 */ 1665 if ((port_status & EHCI_RH_PORT_OWNER) == EHCI_RH_PORT_OWNER_CLASSIC) { 1666 1667 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1668 "ehci_handle_set_clear_port_feature: " 1669 "Port %d is owned by classic host controller", port); 1670 1671 return (USB_FAILURE); 1672 } 1673 1674 return (USB_SUCCESS); 1675 } 1676 1677 1678 /* 1679 * ehci_root_hub_allocate_intr_pipe_resource: 1680 * 1681 * Allocate interrupt requests and initialize them. 1682 */ 1683 static int 1684 ehci_root_hub_allocate_intr_pipe_resource( 1685 ehci_state_t *ehcip, 1686 usb_flags_t flags) 1687 { 1688 usba_pipe_handle_data_t *ph; 1689 size_t length; 1690 usb_intr_req_t *curr_intr_reqp; 1691 1692 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1693 "ehci_root_hub_allocate_intr_pipe_resource"); 1694 1695 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1696 1697 /* Get the interrupt pipe handle */ 1698 ph = ehcip->ehci_root_hub.rh_intr_pipe_handle; 1699 1700 /* Get the current interrupt request pointer */ 1701 curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp; 1702 1703 /* 1704 * If current interrupt request pointer is null, 1705 * allocate new interrupt request. 1706 */ 1707 if (curr_intr_reqp == NULL) { 1708 ASSERT(ehcip->ehci_root_hub.rh_client_intr_reqp); 1709 1710 /* Get the length of interrupt transfer */ 1711 length = ehcip->ehci_root_hub. 1712 rh_client_intr_reqp->intr_len; 1713 1714 curr_intr_reqp = usba_hcdi_dup_intr_req(ph->p_dip, 1715 ehcip->ehci_root_hub.rh_client_intr_reqp, 1716 length, flags); 1717 1718 if (curr_intr_reqp == NULL) { 1719 1720 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1721 "ehci_root_hub_allocate_intr_pipe_resource:" 1722 "Interrupt request structure allocation failed"); 1723 1724 return (USB_NO_RESOURCES); 1725 } 1726 1727 ehcip->ehci_root_hub.rh_curr_intr_reqp = curr_intr_reqp; 1728 mutex_enter(&ph->p_mutex); 1729 ph->p_req_count++; 1730 mutex_exit(&ph->p_mutex); 1731 } 1732 1733 /* Start the timer for the root hub interrupt pipe polling */ 1734 if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id == 0) { 1735 ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 1736 timeout(ehci_handle_root_hub_status_change, 1737 (void *)ehcip, drv_usectohz(EHCI_RH_POLL_TIME)); 1738 1739 ehcip->ehci_root_hub. 1740 rh_intr_pipe_state = EHCI_PIPE_STATE_ACTIVE; 1741 } 1742 1743 return (USB_SUCCESS); 1744 } 1745 1746 1747 /* 1748 * ehci_root_hub_intr_pipe_cleanup: 1749 * 1750 * Deallocate all interrupt requests and do callback 1751 * the original client interrupt request. 1752 */ 1753 static void 1754 ehci_root_hub_intr_pipe_cleanup( 1755 ehci_state_t *ehcip, 1756 usb_cr_t completion_reason) 1757 { 1758 usb_intr_req_t *curr_intr_reqp; 1759 usb_opaque_t client_intr_reqp; 1760 timeout_id_t timer_id; 1761 usba_pipe_handle_data_t *ph; 1762 1763 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1764 "ehci_root_hub_intr_pipe_cleanup"); 1765 1766 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1767 1768 /* Get the interrupt pipe handle */ 1769 ph = ehcip->ehci_root_hub.rh_intr_pipe_handle; 1770 1771 /* Get the interrupt timerid */ 1772 timer_id = ehcip->ehci_root_hub.rh_intr_pipe_timer_id; 1773 1774 /* Stop the root hub interrupt timer */ 1775 if (timer_id) { 1776 /* Reset the timer id to zero */ 1777 ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0; 1778 1779 mutex_exit(&ehcip->ehci_int_mutex); 1780 (void) untimeout(timer_id); 1781 mutex_enter(&ehcip->ehci_int_mutex); 1782 } 1783 1784 /* Reset the current interrupt request pointer */ 1785 curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp; 1786 1787 /* Deallocate uncompleted interrupt request */ 1788 if (curr_intr_reqp) { 1789 ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL; 1790 usb_free_intr_req(curr_intr_reqp); 1791 1792 mutex_enter(&ph->p_mutex); 1793 ph->p_req_count--; 1794 mutex_exit(&ph->p_mutex); 1795 } 1796 1797 client_intr_reqp = (usb_opaque_t) 1798 ehcip->ehci_root_hub.rh_client_intr_reqp; 1799 1800 /* Callback for original client interrupt request */ 1801 if (client_intr_reqp) { 1802 ehci_root_hub_hcdi_callback(ph, completion_reason); 1803 } 1804 } 1805 1806 1807 /* 1808 * ehci_handle_root_hub_status_change: 1809 * 1810 * A root hub status change interrupt will occur any time there is a change 1811 * in the root hub status register or one of the port status registers. 1812 */ 1813 static void 1814 ehci_handle_root_hub_status_change(void *arg) 1815 { 1816 ehci_state_t *ehcip = (ehci_state_t *)arg; 1817 usb_hub_descr_t *root_hub_descr = 1818 &ehcip->ehci_root_hub.rh_descr; 1819 usb_intr_req_t *curr_intr_reqp; 1820 usb_port_mask_t port_mask = 0; 1821 uint_t new_port_status; 1822 uint_t change_status; 1823 uint_t port_status; 1824 mblk_t *message; 1825 size_t length; 1826 usb_ep_descr_t *eptd; 1827 usba_pipe_handle_data_t *ph; 1828 int i; 1829 1830 mutex_enter(&ehcip->ehci_int_mutex); 1831 1832 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1833 "ehci_handle_root_hub_status_change: state = %d", 1834 ehcip->ehci_root_hub.rh_intr_pipe_state); 1835 1836 #if defined(__x86) 1837 /* 1838 * When ohci are attached in ferrari 4000, SMI will reset ehci 1839 * registers. If ehci registers have been reset, we must re-initialize 1840 * them. During booting, this function will be called 2~3 times. When 1841 * this function is called 16 times, ohci drivers have been attached 1842 * and stop checking the ehci registers. 1843 */ 1844 if (ehcip->ehci_polled_root_hub_count < 16) { 1845 1846 if (Get_OpReg(ehci_config_flag) == 0) { 1847 1848 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, 1849 ehcip->ehci_log_hdl, 1850 "ehci_handle_root_hub_status_change:" 1851 " EHCI have been reset"); 1852 1853 /* Reinitialize the controller */ 1854 if (ehci_init_ctlr(ehcip, EHCI_REINITIALIZATION) != 1855 DDI_SUCCESS) { 1856 mutex_exit(&ehcip->ehci_int_mutex); 1857 1858 return; 1859 } 1860 } 1861 1862 ehcip->ehci_polled_root_hub_count++; 1863 } 1864 #endif /* __x86 */ 1865 1866 /* Get the current interrupt request pointer */ 1867 curr_intr_reqp = ehcip->ehci_root_hub.rh_curr_intr_reqp; 1868 1869 ph = ehcip->ehci_root_hub.rh_intr_pipe_handle; 1870 1871 /* Check whether timeout handler is valid */ 1872 if (ehcip->ehci_root_hub.rh_intr_pipe_timer_id) { 1873 /* Check host controller is in operational state */ 1874 if ((ehci_state_is_operational(ehcip)) != USB_SUCCESS) { 1875 /* Reset the timer id */ 1876 ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0; 1877 1878 /* Do interrupt pipe cleanup */ 1879 ehci_root_hub_intr_pipe_cleanup( 1880 ehcip, USB_CR_HC_HARDWARE_ERR); 1881 1882 mutex_exit(&ehcip->ehci_int_mutex); 1883 1884 return; 1885 } 1886 } else { 1887 mutex_exit(&ehcip->ehci_int_mutex); 1888 1889 return; 1890 } 1891 1892 eptd = &ehcip->ehci_root_hub.rh_intr_pipe_handle->p_ep; 1893 1894 /* Check each port */ 1895 for (i = 0; i < root_hub_descr->bNbrPorts; i++) { 1896 1897 port_status = ehci_get_root_hub_port_status(ehcip, i); 1898 1899 new_port_status = port_status & PORT_STATUS_MASK; 1900 change_status = (port_status >> 16) & PORT_CHANGE_MASK; 1901 1902 /* 1903 * If there is change in the port status then set the bit in the 1904 * bitmap of changes and inform hub driver about these changes. 1905 * Hub driver will take care of these changes. 1906 */ 1907 if (change_status) { 1908 1909 /* See if a device was attached/detached */ 1910 if (change_status & PORT_CHANGE_CSC) { 1911 /* 1912 * Update the state depending on whether 1913 * the port was attached or detached. 1914 */ 1915 if (new_port_status & PORT_STATUS_CCS) { 1916 ehcip->ehci_root_hub. 1917 rh_port_state[i] = DISABLED; 1918 1919 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1920 ehcip->ehci_log_hdl, 1921 "Port %d connected", i+1); 1922 } else { 1923 ehcip->ehci_root_hub. 1924 rh_port_state[i] = DISCONNECTED; 1925 1926 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1927 ehcip->ehci_log_hdl, 1928 "Port %d disconnected", i+1); 1929 } 1930 } 1931 1932 /* See if port enable status changed */ 1933 if (change_status & PORT_CHANGE_PESC) { 1934 /* 1935 * Update the state depending on whether 1936 * the port was enabled or disabled. 1937 */ 1938 if (new_port_status & PORT_STATUS_PES) { 1939 ehcip->ehci_root_hub. 1940 rh_port_state[i] = ENABLED; 1941 1942 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1943 ehcip->ehci_log_hdl, 1944 "Port %d enabled", i+1); 1945 } else { 1946 ehcip->ehci_root_hub. 1947 rh_port_state[i] = DISABLED; 1948 1949 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1950 ehcip->ehci_log_hdl, 1951 "Port %d disabled", i+1); 1952 } 1953 } 1954 1955 port_mask |= 1 << (i + 1); 1956 1957 /* Update the status */ 1958 ehcip->ehci_root_hub. 1959 rh_port_status[i] = new_port_status; 1960 } 1961 } 1962 1963 if (ph && port_mask && curr_intr_reqp) { 1964 length = eptd->wMaxPacketSize; 1965 1966 ASSERT(length != 0); 1967 1968 /* Get the message block */ 1969 message = curr_intr_reqp->intr_data; 1970 1971 ASSERT(message != NULL); 1972 1973 do { 1974 /* 1975 * check that the mblk is big enough when we 1976 * are writing bytes into it 1977 */ 1978 if (message->b_wptr >= message->b_datap->db_lim) { 1979 1980 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, 1981 ehcip->ehci_log_hdl, 1982 "ehci_handle_root_hub_status_change" 1983 "mblk data overflow."); 1984 1985 break; 1986 } 1987 *message->b_wptr++ = (uchar_t)port_mask; 1988 port_mask >>= 8; 1989 } while (port_mask != 0); 1990 1991 ehci_root_hub_hcdi_callback(ph, USB_CR_OK); 1992 } 1993 1994 /* Reset the timer id */ 1995 ehcip->ehci_root_hub.rh_intr_pipe_timer_id = 0; 1996 1997 if (ehcip->ehci_root_hub.rh_intr_pipe_state == 1998 EHCI_PIPE_STATE_ACTIVE) { 1999 /* 2000 * If needed, allocate new interrupt request. Also 2001 * start the timer for the root hub interrupt polling. 2002 */ 2003 if ((ehci_root_hub_allocate_intr_pipe_resource( 2004 ehcip, 0)) != USB_SUCCESS) { 2005 2006 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 2007 "ehci_handle_root_hub_status_change: No Resources"); 2008 2009 /* Do interrupt pipe cleanup */ 2010 ehci_root_hub_intr_pipe_cleanup( 2011 ehcip, USB_CR_NO_RESOURCES); 2012 } 2013 } 2014 2015 mutex_exit(&ehcip->ehci_int_mutex); 2016 } 2017 2018 2019 /* 2020 * ehci_root_hub_hcdi_callback() 2021 * 2022 * Convenience wrapper around usba_hcdi_cb() for the root hub. 2023 */ 2024 static void 2025 ehci_root_hub_hcdi_callback( 2026 usba_pipe_handle_data_t *ph, 2027 usb_cr_t completion_reason) 2028 { 2029 ehci_state_t *ehcip = ehci_obtain_state( 2030 ph->p_usba_device->usb_root_hub_dip); 2031 uchar_t attributes = ph->p_ep.bmAttributes & 2032 USB_EP_ATTR_MASK; 2033 usb_opaque_t curr_xfer_reqp; 2034 uint_t pipe_state = 0; 2035 2036 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 2037 "ehci_root_hub_hcdi_callback: ph = 0x%p, cr = 0x%x", 2038 (void *)ph, completion_reason); 2039 2040 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 2041 2042 /* Set the pipe state as per completion reason */ 2043 switch (completion_reason) { 2044 case USB_CR_OK: 2045 switch (attributes) { 2046 case USB_EP_ATTR_CONTROL: 2047 pipe_state = EHCI_PIPE_STATE_IDLE; 2048 break; 2049 case USB_EP_ATTR_INTR: 2050 pipe_state = ehcip->ehci_root_hub. 2051 rh_intr_pipe_state; 2052 break; 2053 } 2054 break; 2055 case USB_CR_NO_RESOURCES: 2056 case USB_CR_NOT_SUPPORTED: 2057 case USB_CR_STOPPED_POLLING: 2058 case USB_CR_PIPE_RESET: 2059 case USB_CR_HC_HARDWARE_ERR: 2060 /* Set pipe state to idle */ 2061 pipe_state = EHCI_PIPE_STATE_IDLE; 2062 break; 2063 case USB_CR_PIPE_CLOSING: 2064 break; 2065 default: 2066 /* Set pipe state to error */ 2067 pipe_state = EHCI_PIPE_STATE_ERROR; 2068 break; 2069 } 2070 2071 switch (attributes) { 2072 case USB_EP_ATTR_CONTROL: 2073 curr_xfer_reqp = (usb_opaque_t) 2074 ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 2075 2076 ehcip->ehci_root_hub.rh_curr_ctrl_reqp = NULL; 2077 ehcip->ehci_root_hub.rh_ctrl_pipe_state = pipe_state; 2078 break; 2079 case USB_EP_ATTR_INTR: 2080 /* if curr_intr_reqp available then use this request */ 2081 if (ehcip->ehci_root_hub.rh_curr_intr_reqp) { 2082 curr_xfer_reqp = (usb_opaque_t)ehcip-> 2083 ehci_root_hub.rh_curr_intr_reqp; 2084 2085 ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL; 2086 } else { 2087 /* no current request, use client's request */ 2088 curr_xfer_reqp = (usb_opaque_t) 2089 ehcip->ehci_root_hub.rh_client_intr_reqp; 2090 2091 ehcip->ehci_root_hub.rh_client_intr_reqp = NULL; 2092 } 2093 ehcip->ehci_root_hub.rh_intr_pipe_state = pipe_state; 2094 break; 2095 } 2096 2097 ASSERT(curr_xfer_reqp != NULL); 2098 2099 mutex_exit(&ehcip->ehci_int_mutex); 2100 usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason); 2101 mutex_enter(&ehcip->ehci_int_mutex); 2102 } 2103