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