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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * EHCI Host Controller Driver (EHCI) 30 * 31 * The EHCI driver is a software driver which interfaces to the Universal 32 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to 33 * the Host Controller is defined by the EHCI Host Controller Interface. 34 * 35 * This module contains the code for root hub related functions. 36 * 37 * NOTE: 38 * 39 * ONE_XFER is not supported on root hub interrupt polling 40 */ 41 42 #include <sys/usb/hcd/ehci/ehcid.h> 43 #include <sys/usb/hcd/ehci/ehci_util.h> 44 #include <sys/usb/usba/usba_types.h> 45 46 /* Static function prototypes */ 47 static int ehci_handle_set_clear_port_feature( 48 ehci_state_t *ehcip, 49 uchar_t bRequest, 50 uint16_t wValue, 51 uint16_t port); 52 static void ehci_handle_port_power( 53 ehci_state_t *ehcip, 54 uint16_t port, 55 uint_t on); 56 static void ehci_handle_port_enable( 57 ehci_state_t *ehcip, 58 uint16_t port, 59 uint_t on); 60 static void ehci_handle_clrchng_port_enable( 61 ehci_state_t *ehcip, 62 uint16_t port); 63 static void ehci_handle_port_suspend( 64 ehci_state_t *ehcip, 65 uint16_t port, 66 uint_t on); 67 static void ehci_handle_clrchng_port_suspend( 68 ehci_state_t *ehcip, 69 uint16_t port); 70 static void ehci_handle_port_reset( 71 ehci_state_t *ehcip, 72 uint16_t port); 73 static void ehci_root_hub_reset_occured( 74 ehci_state_t *ehcip); 75 static void ehci_handle_complete_port_reset( 76 ehci_state_t *ehcip, 77 uint16_t port); 78 static void ehci_handle_clear_port_connection( 79 ehci_state_t *ehcip, 80 uint16_t port); 81 static void ehci_handle_clrchng_port_over_current( 82 ehci_state_t *ehcip, 83 uint16_t port); 84 static void ehci_handle_get_port_status( 85 ehci_state_t *ehcip, 86 uint16_t port); 87 static void ehci_handle_get_hub_descriptor( 88 ehci_state_t *ehcip); 89 static void ehci_handle_get_hub_status( 90 ehci_state_t *ehcip); 91 static void ehci_handle_get_device_status( 92 ehci_state_t *ehcip); 93 static uint_t ehci_get_root_hub_port_status( 94 ehci_state_t *ehcip, 95 uint16_t port); 96 static int ehci_is_port_owner( 97 ehci_state_t *ehcip, 98 uint16_t port); 99 static int ehci_root_hub_allocate_intr_pipe_resource( 100 ehci_state_t *ehcip, 101 usb_flags_t flags); 102 static void ehci_root_hub_intr_pipe_cleanup( 103 ehci_state_t *ehcip, 104 usb_cr_t completion_reason); 105 static void ehci_handle_root_hub_status_change(void *arg); 106 static void ehci_root_hub_hcdi_callback( 107 usba_pipe_handle_data_t *ph, 108 usb_cr_t completion_reason); 109 110 111 /* 112 * ehci_init_root_hub: 113 * 114 * Initialize the root hub 115 */ 116 int 117 ehci_init_root_hub(ehci_state_t *ehcip) 118 { 119 usb_hub_descr_t *root_hub_descr = 120 &ehcip->ehci_root_hub.rh_descr; 121 uint_t i, length, port_state; 122 uint32_t capability; 123 124 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 125 "ehci_init_root_hub:"); 126 127 /* Read the EHCI capability register */ 128 capability = Get_Cap(ehci_hcs_params); 129 130 /* 131 * Build the Root hub descriptor by looking EHCI capability 132 * and operational registers. 133 */ 134 root_hub_descr->bDescriptorType = ROOT_HUB_DESCRIPTOR_TYPE; 135 136 if ((capability & EHCI_HCS_NUM_PORTS) > EHCI_MAX_RH_PORTS) { 137 138 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 139 "ehci_init_root_hub: Invalid no of root hub ports 0x%x", 140 capability & EHCI_HCS_NUM_PORTS); 141 142 return (USB_FAILURE); 143 } 144 145 /* Obtain the number of downstream ports */ 146 root_hub_descr->bNbrPorts = capability & EHCI_HCS_NUM_PORTS; 147 148 length = root_hub_descr->bNbrPorts / 8; 149 150 if (length) { 151 root_hub_descr->bDescLength = 7 + (2 * (length + 1)); 152 } else { 153 root_hub_descr->bDescLength = ROOT_HUB_DESCRIPTOR_LENGTH; 154 } 155 156 /* 157 * Obtain the number of Classic or Companion USB 1.1 (OHCI/UHCI) 158 * Host Controllers information. 159 */ 160 ehcip->ehci_root_hub.rh_companion_controllers = (capability & 161 EHCI_HCS_NUM_COMP_CTRLS) >> EHCI_HCS_NUM_COMP_CTRL_SHIFT; 162 163 /* 164 * Determine the Power Switching Mode 165 * 166 * EHCI Specification, root hub supports either no power switching 167 * individual port power switching. Also determine the Over-current 168 * Protection Mode. 169 */ 170 if (capability & EHCI_HCS_PORT_POWER_CONTROL) { 171 /* Each port is powered individually */ 172 root_hub_descr-> wHubCharacteristics = 173 HUB_CHARS_INDIVIDUAL_PORT_POWER; 174 175 /* Assume individual overcurrent reporting */ 176 root_hub_descr->wHubCharacteristics |= 177 HUB_CHARS_INDIV_OVER_CURRENT; 178 179 /* Each port will start off in the POWERED_OFF mode */ 180 port_state = POWERED_OFF; 181 } else { 182 /* The ports are powered when the ctlr is powered */ 183 root_hub_descr-> 184 wHubCharacteristics = HUB_CHARS_NO_POWER_SWITCHING; 185 186 /* Assume no overcurrent reporting */ 187 root_hub_descr->wHubCharacteristics |= 188 HUB_CHARS_NO_OVER_CURRENT; 189 190 port_state = DISCONNECTED; 191 } 192 193 /* Look at the port indicator information */ 194 if (capability & EHCI_HCS_PORT_INDICATOR) { 195 root_hub_descr->wHubCharacteristics |= HUB_CHARS_PORT_INDICATOR; 196 } 197 198 /* 199 * Obtain the power on to power good time of the ports. 200 * 201 * Assume: Zero for this field. 202 */ 203 root_hub_descr->bPwrOn2PwrGood = 2; 204 205 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 206 "Power on to power good %d", root_hub_descr->bPwrOn2PwrGood); 207 208 /* Indicate if the device is removable */ 209 root_hub_descr->DeviceRemovable = 0; 210 211 /* Set PortPowerControlMask to zero */ 212 root_hub_descr->PortPwrCtrlMask = 0; 213 214 /* Set the state of each port and initialize the status */ 215 for (i = 0; i < root_hub_descr->bNbrPorts; i++) { 216 217 /* Initilize state/status of each root hub port */ 218 ehcip->ehci_root_hub.rh_port_state[i] = port_state; 219 ehcip->ehci_root_hub.rh_port_status[i] = 0; 220 } 221 222 return (USB_SUCCESS); 223 } 224 225 226 /* 227 * ehci_load_root_hub_driver: 228 * 229 * Attach the root hub 230 */ 231 static usb_dev_descr_t ehci_root_hub_device_descriptor = { 232 0x12, /* bLength */ 233 0x01, /* bDescriptorType, Device */ 234 0x200, /* bcdUSB, v2.0 */ 235 0x09, /* bDeviceClass */ 236 0x00, /* bDeviceSubClass */ 237 0x01, /* bDeviceProtocol */ 238 0x40, /* bMaxPacketSize0 */ 239 0x00, /* idVendor */ 240 0x00, /* idProduct */ 241 0x00, /* bcdDevice */ 242 0x00, /* iManufacturer */ 243 0x00, /* iProduct */ 244 0x00, /* iSerialNumber */ 245 0x01 /* bNumConfigurations */ 246 }; 247 248 static uchar_t ehci_root_hub_config_descriptor[] = { 249 /* One configuartion */ 250 0x09, /* bLength */ 251 0x02, /* bDescriptorType, Configuartion */ 252 0x19, 0x00, /* wTotalLength */ 253 0x01, /* bNumInterfaces */ 254 0x01, /* bConfigurationValue */ 255 0x00, /* iConfiguration */ 256 0x40, /* bmAttributes */ 257 0x00, /* MaxPower */ 258 259 /* One Interface */ 260 0x09, /* bLength */ 261 0x04, /* bDescriptorType, Interface */ 262 0x00, /* bInterfaceNumber */ 263 0x00, /* bAlternateSetting */ 264 0x01, /* bNumEndpoints */ 265 0x09, /* bInterfaceClass */ 266 0x01, /* bInterfaceSubClass */ 267 0x00, /* bInterfaceProtocol */ 268 0x00, /* iInterface */ 269 270 /* One Endpoint (status change endpoint) */ 271 0x07, /* bLength */ 272 0x05, /* bDescriptorType, Endpoint */ 273 0x81, /* bEndpointAddress */ 274 0x03, /* bmAttributes */ 275 0x01, 0x00, /* wMaxPacketSize, 1 + (EHCI_MAX_RH_PORTS / 8) */ 276 0xff /* bInterval */ 277 }; 278 279 int 280 ehci_load_root_hub_driver(ehci_state_t *ehcip) 281 { 282 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 283 "ehci_load_root_hub_driver:"); 284 285 return (usba_hubdi_bind_root_hub(ehcip->ehci_dip, 286 ehci_root_hub_config_descriptor, 287 sizeof (ehci_root_hub_config_descriptor), 288 &ehci_root_hub_device_descriptor)); 289 } 290 291 292 /* 293 * ehci_unload_root_hub_driver: 294 */ 295 int 296 ehci_unload_root_hub_driver(ehci_state_t *ehcip) 297 { 298 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 299 "ehci_unload_root_hub_driver:"); 300 301 return (usba_hubdi_unbind_root_hub(ehcip->ehci_dip)); 302 } 303 304 305 /* 306 * ehci_handle_root_hub_pipe_open: 307 * 308 * Handle opening of control and interrupt pipes on root hub. 309 */ 310 /* ARGSUSED */ 311 int 312 ehci_handle_root_hub_pipe_open( 313 usba_pipe_handle_data_t *ph, 314 usb_flags_t usb_flags) 315 { 316 ehci_state_t *ehcip = ehci_obtain_state( 317 ph->p_usba_device->usb_root_hub_dip); 318 usb_ep_descr_t *eptd = &ph->p_ep; 319 320 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 321 "ehci_handle_root_hub_pipe_open: Root hub pipe open"); 322 323 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 324 325 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) { 326 case USB_EP_ATTR_CONTROL: 327 /* Save control pipe handle */ 328 ehcip->ehci_root_hub.rh_ctrl_pipe_handle = ph; 329 330 /* Set state of the root hub control pipe as idle */ 331 ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_IDLE; 332 333 ehcip->ehci_root_hub.rh_curr_ctrl_reqp = NULL; 334 335 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 336 "ehci_handle_root_hub_pipe_open: Root hub control " 337 "pipe open succeeded"); 338 339 break; 340 case USB_EP_ATTR_INTR: 341 /* Save interrupt pipe handle */ 342 ehcip->ehci_root_hub.rh_intr_pipe_handle = ph; 343 344 /* Set state of the root hub interrupt pipe as idle */ 345 ehcip->ehci_root_hub.rh_intr_pipe_state = EHCI_PIPE_STATE_IDLE; 346 347 ehcip->ehci_root_hub.rh_client_intr_reqp = NULL; 348 349 ehcip->ehci_root_hub.rh_curr_intr_reqp = NULL; 350 351 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 352 "ehci_handle_root_hub_pipe_open: Root hub interrupt " 353 "pipe open succeeded"); 354 355 break; 356 default: 357 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 358 "ehci_handle_root_hub_pipe_open: Root hub pipe open" 359 "failed"); 360 361 return (USB_FAILURE); 362 } 363 364 ehcip->ehci_open_pipe_count++; 365 366 return (USB_SUCCESS); 367 } 368 369 370 /* 371 * ehci_handle_root_hub_pipe_close: 372 * 373 * Handle closing of control and interrupt pipes on root hub. 374 */ 375 /* ARGSUSED */ 376 int 377 ehci_handle_root_hub_pipe_close(usba_pipe_handle_data_t *ph) 378 { 379 ehci_state_t *ehcip = ehci_obtain_state( 380 ph->p_usba_device->usb_root_hub_dip); 381 usb_ep_descr_t *eptd = &ph->p_ep; 382 383 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 384 "ehci_handle_root_hub_pipe_close: Root hub pipe close"); 385 386 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 387 388 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) { 389 case USB_EP_ATTR_CONTROL: 390 ASSERT(ehcip->ehci_root_hub. 391 rh_ctrl_pipe_state != EHCI_PIPE_STATE_CLOSE); 392 393 /* Set state of the root hub control pipe as close */ 394 ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_CLOSE; 395 396 /* Set root hub control pipe handle to null */ 397 ehcip->ehci_root_hub.rh_ctrl_pipe_handle = NULL; 398 399 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 400 "ehci_handle_root_hub_pipe_close: " 401 "Root hub control pipe close succeeded"); 402 break; 403 case USB_EP_ATTR_INTR: 404 ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1); 405 406 ASSERT(ehcip->ehci_root_hub. 407 rh_intr_pipe_state != EHCI_PIPE_STATE_CLOSE); 408 409 /* Set state of the root hub interrupt pipe as close */ 410 ehcip->ehci_root_hub.rh_intr_pipe_state = EHCI_PIPE_STATE_CLOSE; 411 412 /* Do interrupt pipe cleanup */ 413 ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_PIPE_CLOSING); 414 415 /* Set root hub interrupt pipe handle to null */ 416 ehcip->ehci_root_hub.rh_intr_pipe_handle = NULL; 417 418 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 419 "ehci_handle_root_hub_pipe_close: " 420 "Root hub interrupt pipe close succeeded"); 421 422 break; 423 default: 424 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 425 "ehci_handle_root_hub_pipe_close: " 426 "Root hub pipe close failed"); 427 428 return (USB_FAILURE); 429 } 430 431 ehcip->ehci_open_pipe_count--; 432 433 return (USB_SUCCESS); 434 } 435 436 437 /* 438 * ehci_handle_root_hub_pipe_reset: 439 * 440 * Handle resetting of control and interrupt pipes on root hub. 441 */ 442 /* ARGSUSED */ 443 int 444 ehci_handle_root_hub_pipe_reset( 445 usba_pipe_handle_data_t *ph, 446 usb_flags_t usb_flags) 447 { 448 ehci_state_t *ehcip = ehci_obtain_state( 449 ph->p_usba_device->usb_root_hub_dip); 450 usb_ep_descr_t *eptd = &ph->p_ep; 451 int error = USB_SUCCESS; 452 453 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 454 "ehci_handle_root_hub_pipe_reset: Root hub pipe reset"); 455 456 mutex_enter(&ehcip->ehci_int_mutex); 457 458 switch (eptd->bmAttributes & USB_EP_ATTR_MASK) { 459 case USB_EP_ATTR_CONTROL: 460 ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_IDLE; 461 462 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 463 "ehci_handle_root_hub_pipe_reset: Pipe reset" 464 "for the root hub control pipe successful"); 465 466 break; 467 case USB_EP_ATTR_INTR: 468 ASSERT((eptd->bEndpointAddress & USB_EP_NUM_MASK) == 1); 469 470 if ((ehcip->ehci_root_hub.rh_client_intr_reqp) && 471 (ehcip->ehci_root_hub.rh_intr_pipe_state != 472 EHCI_PIPE_STATE_IDLE)) { 473 474 ehcip->ehci_root_hub. 475 rh_intr_pipe_state = EHCI_PIPE_STATE_RESET; 476 477 /* Do interrupt pipe cleanup */ 478 ehci_root_hub_intr_pipe_cleanup( 479 ehcip, USB_CR_PIPE_RESET); 480 } 481 482 ASSERT(ehcip->ehci_root_hub. 483 rh_intr_pipe_state == EHCI_PIPE_STATE_IDLE); 484 485 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 486 "ehci_handle_root_hub_pipe_reset: " 487 "Pipe reset for root hub interrupt pipe successful"); 488 489 break; 490 default: 491 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 492 "ehci_handle_root_hub_pipe_reset: " 493 "Root hub pipe reset failed"); 494 495 error = USB_FAILURE; 496 break; 497 } 498 499 mutex_exit(&ehcip->ehci_int_mutex); 500 501 return (error); 502 } 503 504 505 /* 506 * ehci_handle_root_hub_request: 507 * 508 * Intercept a root hub request. Handle the root hub request through the 509 * registers 510 */ 511 /* ARGSUSED */ 512 int 513 ehci_handle_root_hub_request( 514 ehci_state_t *ehcip, 515 usba_pipe_handle_data_t *ph, 516 usb_ctrl_req_t *ctrl_reqp) 517 { 518 uchar_t bmRequestType = ctrl_reqp->ctrl_bmRequestType; 519 uchar_t bRequest = ctrl_reqp->ctrl_bRequest; 520 uint16_t wValue = ctrl_reqp->ctrl_wValue; 521 uint16_t wIndex = ctrl_reqp->ctrl_wIndex; 522 uint16_t wLength = ctrl_reqp->ctrl_wLength; 523 mblk_t *data = ctrl_reqp->ctrl_data; 524 uint16_t port = wIndex - 1; 525 usb_cr_t completion_reason; 526 int error = USB_SUCCESS; 527 528 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 529 "ehci_handle_root_hub_request: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%p", 530 bmRequestType, bRequest, wValue, wIndex, wLength, (void *)data); 531 532 mutex_enter(&ehcip->ehci_int_mutex); 533 534 if (ehcip->ehci_root_hub. 535 rh_ctrl_pipe_state != EHCI_PIPE_STATE_IDLE) { 536 537 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 538 "ehci_handle_root_hub_request: Pipe is not idle"); 539 540 mutex_exit(&ehcip->ehci_int_mutex); 541 542 return (USB_FAILURE); 543 } 544 545 /* Save the current control request pointer */ 546 ehcip->ehci_root_hub.rh_curr_ctrl_reqp = ctrl_reqp; 547 548 /* Set pipe state to active */ 549 ehcip->ehci_root_hub.rh_ctrl_pipe_state = EHCI_PIPE_STATE_ACTIVE; 550 551 mutex_exit(&ehcip->ehci_int_mutex); 552 553 switch (bmRequestType) { 554 case HUB_GET_DEVICE_STATUS_TYPE: 555 ehci_handle_get_device_status(ehcip); 556 break; 557 case HUB_HANDLE_PORT_FEATURE_TYPE: 558 error = ehci_handle_set_clear_port_feature(ehcip, 559 bRequest, wValue, port); 560 break; 561 case HUB_GET_PORT_STATUS_TYPE: 562 ehci_handle_get_port_status(ehcip, port); 563 break; 564 case HUB_CLASS_REQ_TYPE: 565 switch (bRequest) { 566 case USB_REQ_GET_STATUS: 567 ehci_handle_get_hub_status(ehcip); 568 break; 569 case USB_REQ_GET_DESCR: 570 ehci_handle_get_hub_descriptor(ehcip); 571 break; 572 default: 573 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 574 "ehci_handle_root_hub_request:" 575 "Unsupported request 0x%x", bRequest); 576 577 error = USB_FAILURE; 578 break; 579 } 580 break; 581 default: 582 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 583 "ehci_handle_root_hub_request: " 584 "Unsupported request 0x%x", bmRequestType); 585 586 error = USB_FAILURE; 587 break; 588 } 589 590 completion_reason = (error) ? USB_CR_NOT_SUPPORTED : USB_CR_OK; 591 592 mutex_enter(&ehcip->ehci_int_mutex); 593 ehci_root_hub_hcdi_callback(ph, completion_reason); 594 mutex_exit(&ehcip->ehci_int_mutex); 595 596 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 597 "ehci_handle_root_hub_request: error = %d", error); 598 599 return (USB_SUCCESS); 600 } 601 602 603 /* 604 * ehci_handle_set_clear_port_feature: 605 */ 606 static int 607 ehci_handle_set_clear_port_feature( 608 ehci_state_t *ehcip, 609 uchar_t bRequest, 610 uint16_t wValue, 611 uint16_t port) 612 { 613 int error = USB_SUCCESS; 614 615 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 616 "ehci_handle_set_clear_port_feature: 0x%x 0x%x 0x%x", 617 bRequest, wValue, port); 618 619 switch (bRequest) { 620 case USB_REQ_SET_FEATURE: 621 switch (wValue) { 622 case CFS_PORT_ENABLE: 623 ehci_handle_port_enable(ehcip, port, 1); 624 break; 625 case CFS_PORT_SUSPEND: 626 ehci_handle_port_suspend(ehcip, port, 1); 627 break; 628 case CFS_PORT_RESET: 629 ehci_handle_port_reset(ehcip, port); 630 break; 631 case CFS_PORT_POWER: 632 ehci_handle_port_power(ehcip, port, 1); 633 break; 634 default: 635 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 636 "ehci_handle_set_clear_port_feature: " 637 "Unsupported request 0x%x 0x%x", bRequest, wValue); 638 639 error = USB_FAILURE; 640 break; 641 } 642 break; 643 case USB_REQ_CLEAR_FEATURE: 644 switch (wValue) { 645 case CFS_PORT_ENABLE: 646 ehci_handle_port_enable(ehcip, port, 0); 647 break; 648 case CFS_C_PORT_ENABLE: 649 ehci_handle_clrchng_port_enable(ehcip, port); 650 break; 651 case CFS_PORT_SUSPEND: 652 ehci_handle_port_suspend(ehcip, port, 0); 653 break; 654 case CFS_C_PORT_SUSPEND: 655 ehci_handle_clrchng_port_suspend(ehcip, port); 656 break; 657 case CFS_C_PORT_RESET: 658 ehci_handle_complete_port_reset(ehcip, port); 659 break; 660 case CFS_PORT_POWER: 661 ehci_handle_port_power(ehcip, port, 0); 662 break; 663 case CFS_C_PORT_CONNECTION: 664 ehci_handle_clear_port_connection(ehcip, port); 665 break; 666 case CFS_C_PORT_OVER_CURRENT: 667 ehci_handle_clrchng_port_over_current(ehcip, port); 668 break; 669 default: 670 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 671 "ehci_handle_set_clear_port_feature: " 672 "Unsupported request 0x%x 0x%x", bRequest, wValue); 673 674 error = USB_FAILURE; 675 break; 676 } 677 break; 678 default: 679 USB_DPRINTF_L2(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 680 "ehci_handle_set_clear_port_feature: " 681 "Unsupported request 0x%x 0x%x", bRequest, wValue); 682 683 error = USB_FAILURE; 684 break; 685 } 686 687 return (error); 688 } 689 690 691 /* 692 * ehci_handle_port_power: 693 * 694 * Turn on a root hub port. 695 */ 696 static void 697 ehci_handle_port_power( 698 ehci_state_t *ehcip, 699 uint16_t port, 700 uint_t on) 701 { 702 uint_t port_status; 703 ehci_root_hub_t *rh; 704 705 mutex_enter(&ehcip->ehci_int_mutex); 706 707 port_status = Get_OpReg(ehci_rh_port_status[port]) & 708 ~EHCI_RH_PORT_CLEAR_MASK; 709 710 rh = &ehcip->ehci_root_hub; 711 712 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 713 "ehci_handle_port_power: port = 0x%x status = 0x%x on = %d", 714 port, port_status, on); 715 716 /* Check port is owned by ehci */ 717 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 718 mutex_exit(&ehcip->ehci_int_mutex); 719 720 return; 721 } 722 723 if (on) { 724 /* See if the port power is already on */ 725 if (!(port_status & EHCI_RH_PORT_POWER)) { 726 /* Turn the port on */ 727 Set_OpReg(ehci_rh_port_status[port], 728 port_status | EHCI_RH_PORT_POWER); 729 } 730 731 rh->rh_port_status[port] = 0; 732 rh->rh_port_state[port] = DISCONNECTED; 733 } else { 734 /* See if the port power is already OFF */ 735 if (port_status & EHCI_RH_PORT_POWER) { 736 /* Turn-off the port */ 737 Set_OpReg(ehci_rh_port_status[port], 738 port_status & ~EHCI_RH_PORT_POWER); 739 } 740 741 rh->rh_port_status[port] = 0; 742 rh->rh_port_state[port] = POWERED_OFF; 743 } 744 745 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 746 "ehci_handle_port_power done: port = 0x%x status = 0x%x on = %d", 747 port, Get_OpReg(ehci_rh_port_status[port]), on); 748 749 mutex_exit(&ehcip->ehci_int_mutex); 750 } 751 752 753 /* 754 * ehci_handle_port_enable: 755 * 756 * Handle port enable request. 757 */ 758 static void 759 ehci_handle_port_enable( 760 ehci_state_t *ehcip, 761 uint16_t port, 762 uint_t on) 763 { 764 uint_t port_status; 765 766 mutex_enter(&ehcip->ehci_int_mutex); 767 768 port_status = Get_OpReg(ehci_rh_port_status[port]) & 769 ~EHCI_RH_PORT_CLEAR_MASK; 770 771 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 772 "ehci_handle_port_enable: port = 0x%x, status = 0x%x", 773 port, port_status); 774 775 /* Check port is owned by ehci */ 776 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 777 mutex_exit(&ehcip->ehci_int_mutex); 778 779 return; 780 } 781 782 if (on) { 783 /* See if the port enable is already on */ 784 if (!(port_status & EHCI_RH_PORT_ENABLE)) { 785 /* Enable the port */ 786 Set_OpReg(ehci_rh_port_status[port], 787 port_status | EHCI_RH_PORT_ENABLE); 788 } 789 } else { 790 /* See if the port enable is already off */ 791 if (port_status & EHCI_RH_PORT_ENABLE) { 792 /* Disable the port */ 793 Set_OpReg(ehci_rh_port_status[port], 794 port_status & ~EHCI_RH_PORT_ENABLE); 795 } 796 } 797 798 mutex_exit(&ehcip->ehci_int_mutex); 799 } 800 801 802 /* 803 * ehci_handle_clrchng_port_enable: 804 * 805 * Handle clear port enable change bit. 806 */ 807 static void 808 ehci_handle_clrchng_port_enable( 809 ehci_state_t *ehcip, 810 uint16_t port) 811 { 812 uint_t port_status; 813 814 mutex_enter(&ehcip->ehci_int_mutex); 815 816 port_status = Get_OpReg(ehci_rh_port_status[port]) & 817 ~EHCI_RH_PORT_CLEAR_MASK; 818 819 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 820 "ehci_handle_port_enable: port = 0x%x, status = 0x%x", 821 port, port_status); 822 823 /* Check port is owned by ehci */ 824 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 825 mutex_exit(&ehcip->ehci_int_mutex); 826 827 return; 828 } 829 830 /* Clear the PortEnableStatusChange Bit */ 831 Set_OpReg(ehci_rh_port_status[port], 832 port_status | EHCI_RH_PORT_ENABLE_CHANGE); 833 834 mutex_exit(&ehcip->ehci_int_mutex); 835 } 836 837 838 /* 839 * ehci_handle_port_suspend: 840 * 841 * Handle port suspend/resume request. 842 */ 843 static void 844 ehci_handle_port_suspend( 845 ehci_state_t *ehcip, 846 uint16_t port, 847 uint_t on) 848 { 849 uint_t port_status; 850 851 mutex_enter(&ehcip->ehci_int_mutex); 852 853 port_status = Get_OpReg(ehci_rh_port_status[port]) & 854 ~EHCI_RH_PORT_CLEAR_MASK; 855 856 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 857 "ehci_handle_port_suspend: port = 0x%x, status = 0x%x", 858 port, port_status); 859 860 /* Check port is owned by ehci */ 861 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 862 mutex_exit(&ehcip->ehci_int_mutex); 863 864 return; 865 } 866 867 if (on) { 868 /* 869 * Suspend port only if port is enabled and 870 * it is not already in suspend state. 871 */ 872 if ((port_status & EHCI_RH_PORT_ENABLE) && 873 (!(port_status & EHCI_RH_PORT_SUSPEND))) { 874 /* Suspend the port */ 875 Set_OpReg(ehci_rh_port_status[port], 876 port_status | EHCI_RH_PORT_SUSPEND); 877 878 mutex_exit(&ehcip->ehci_int_mutex); 879 880 /* Wait 10ms for port move to suspend state */ 881 delay(drv_usectohz(EHCI_PORT_SUSPEND_TIMEWAIT)); 882 883 return; 884 } 885 } else { 886 /* Perform resume only if port is in suspend state */ 887 if (port_status & EHCI_RH_PORT_SUSPEND) { 888 /* Resume the port */ 889 Set_OpReg(ehci_rh_port_status[port], 890 port_status | EHCI_RH_PORT_RESUME); 891 } 892 } 893 894 mutex_exit(&ehcip->ehci_int_mutex); 895 } 896 897 898 /* 899 * ehci_handle_clrchng_port_suspend: 900 * 901 * Handle port clear port suspend change bit. 902 */ 903 static void 904 ehci_handle_clrchng_port_suspend( 905 ehci_state_t *ehcip, 906 uint16_t port) 907 { 908 uint_t port_status; 909 910 mutex_enter(&ehcip->ehci_int_mutex); 911 912 port_status = Get_OpReg(ehci_rh_port_status[port]) & 913 ~EHCI_RH_PORT_CLEAR_MASK; 914 915 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 916 "ehci_handle_clrchng_port_suspend: port = 0x%x, " 917 "status = 0x%x", port, port_status); 918 919 /* Check port is owned by ehci */ 920 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 921 mutex_exit(&ehcip->ehci_int_mutex); 922 923 return; 924 } 925 926 /* Return if port is not in resume state */ 927 if (!(port_status & EHCI_RH_PORT_RESUME)) { 928 mutex_exit(&ehcip->ehci_int_mutex); 929 930 return; 931 } 932 933 mutex_exit(&ehcip->ehci_int_mutex); 934 935 /* Wait for 20ms to terminate resume */ 936 delay(drv_usectohz(EHCI_PORT_RESUME_TIMEWAIT)); 937 938 mutex_enter(&ehcip->ehci_int_mutex); 939 940 Set_OpReg(ehci_rh_port_status[port], 941 port_status & ~EHCI_RH_PORT_RESUME); 942 943 mutex_exit(&ehcip->ehci_int_mutex); 944 945 /* Wait 2ms for port to return to high speed mode */ 946 delay(drv_usectohz(EHCI_PORT_RESUME_COMP_TIMEWAIT)); 947 } 948 949 950 /* 951 * ehci_handle_port_reset: 952 * 953 * Perform a port reset. 954 */ 955 static void 956 ehci_handle_port_reset( 957 ehci_state_t *ehcip, 958 uint16_t port) 959 { 960 ehci_root_hub_t *rh; 961 uint_t port_status; 962 963 mutex_enter(&ehcip->ehci_int_mutex); 964 965 /* Get the root hub structure */ 966 rh = &ehcip->ehci_root_hub; 967 968 /* Get the port status information */ 969 port_status = Get_OpReg(ehci_rh_port_status[port]) & 970 ~EHCI_RH_PORT_CLEAR_MASK; 971 972 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 973 "ehci_handle_port_reset: port = 0x%x status = 0x%x", 974 port, port_status); 975 976 /* Check port is owned by ehci */ 977 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 978 mutex_exit(&ehcip->ehci_int_mutex); 979 980 return; 981 } 982 983 if (port_status & EHCI_RH_PORT_LOW_SPEED) { 984 /* Check for classic or companion host controllers */ 985 if (rh->rh_companion_controllers) { 986 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 987 "ehci_handle_port_reset: Low speed device " 988 "and handover this port to Companion controller"); 989 990 Set_OpReg(ehci_rh_port_status[port], 991 port_status | EHCI_RH_PORT_OWNER_CLASSIC); 992 } else { 993 USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 994 "Low speed device is not supported"); 995 } 996 } else { 997 Set_OpReg(ehci_rh_port_status[port], 998 ((port_status | EHCI_RH_PORT_RESET) & 999 ~EHCI_RH_PORT_ENABLE)); 1000 1001 mutex_exit(&ehcip->ehci_int_mutex); 1002 1003 /* Wait 20ms for reset to complete */ 1004 delay(drv_usectohz(EHCI_PORT_RESET_TIMEWAIT)); 1005 1006 mutex_enter(&ehcip->ehci_int_mutex); 1007 1008 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1009 ~EHCI_RH_PORT_CLEAR_MASK; 1010 1011 Set_OpReg(ehci_rh_port_status[port], 1012 (port_status & ~EHCI_RH_PORT_RESET)); 1013 1014 mutex_exit(&ehcip->ehci_int_mutex); 1015 1016 /* 1017 * Wait 2ms for hardware to enable this port 1018 * if connected usb device is high speed. 1019 */ 1020 delay(drv_usectohz(EHCI_PORT_RESET_COMP_TIMEWAIT)); 1021 1022 mutex_enter(&ehcip->ehci_int_mutex); 1023 1024 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1025 ~EHCI_RH_PORT_CLEAR_MASK; 1026 1027 /* 1028 * If port is not enabled, connected device is a 1029 * Full-speed usb device. 1030 */ 1031 if (!(port_status & EHCI_RH_PORT_ENABLE)) { 1032 /* Check for classic or companion host controllers */ 1033 if (rh->rh_companion_controllers) { 1034 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, 1035 ehcip->ehci_log_hdl, 1036 "ehci_handle_port_reset: Full speed device " 1037 "and handover this port to Companion host " 1038 "controller"); 1039 1040 Set_OpReg(ehci_rh_port_status[port], 1041 port_status | EHCI_RH_PORT_OWNER_CLASSIC); 1042 } else { 1043 USB_DPRINTF_L1(PRINT_MASK_ROOT_HUB, 1044 ehcip->ehci_log_hdl, 1045 "Full speed device is not supported"); 1046 } 1047 } else { 1048 USB_DPRINTF_L3(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1049 "ehci_handle_port_reset: High speed device "); 1050 1051 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1052 ~EHCI_RH_PORT_CLEAR_MASK; 1053 1054 /* 1055 * Enable over-current, connect, and disconnect 1056 * wakeup bits. 1057 */ 1058 Set_OpReg(ehci_rh_port_status[port], (port_status | 1059 EHCI_RH_PORT_OVER_CURENT_ENABLE | 1060 EHCI_RH_PORT_DISCONNECT_ENABLE | 1061 EHCI_RH_PORT_CONNECT_ENABLE)); 1062 1063 /* 1064 * The next function is only called if the interrupt 1065 * pipe is polling and the USBA is ready to receive 1066 * the data. 1067 */ 1068 ehcip->ehci_root_hub. 1069 rh_intr_pending_status |= (1 << port); 1070 1071 if (ehcip->ehci_root_hub. 1072 rh_intr_pipe_state == EHCI_PIPE_STATE_ACTIVE) { 1073 1074 ehci_root_hub_reset_occured(ehcip); 1075 } 1076 } 1077 } 1078 1079 mutex_exit(&ehcip->ehci_int_mutex); 1080 } 1081 1082 1083 /* 1084 * ehci_root_hub_reset_occured: 1085 * 1086 * Inform the upper layer that reset has occured on the port. This is 1087 * required because the upper layer is expecting a an evernt immidiately 1088 * after doing reset. In case of OHCI, the controller gets an interrupt 1089 * for the change in the root hub status but in case of EHCI, we dont. 1090 * So, send a event to the upper layer as soon as we complete the reset. 1091 */ 1092 void 1093 ehci_root_hub_reset_occured( 1094 ehci_state_t *ehcip) 1095 { 1096 usb_intr_req_t *curr_intr_reqp = 1097 ehcip->ehci_root_hub.rh_curr_intr_reqp; 1098 usb_port_mask_t port_mask; 1099 usba_pipe_handle_data_t *ph; 1100 1101 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1102 "ehci_root_hub_reset_occured: curr_intr_reqp = 0x%p data = 0x%p", 1103 curr_intr_reqp, curr_intr_reqp->intr_data); 1104 1105 /* Get the interrupt pipe handle */ 1106 ph = ehcip->ehci_root_hub.rh_intr_pipe_handle; 1107 1108 /* Get the pending status */ 1109 port_mask = ehcip->ehci_root_hub.rh_intr_pending_status << 1; 1110 1111 do { 1112 *curr_intr_reqp->intr_data->b_wptr++ = (uchar_t)port_mask; 1113 port_mask >>= 8; 1114 } while (port_mask != 0); 1115 1116 ehci_root_hub_hcdi_callback(ph, USB_CR_OK); 1117 1118 /* Reset pending status */ 1119 ehcip->ehci_root_hub.rh_intr_pending_status = 0; 1120 1121 /* If needed, allocate new interrupt request */ 1122 if ((ehci_root_hub_allocate_intr_pipe_resource( 1123 ehcip, 0)) != USB_SUCCESS) { 1124 1125 /* Do interrupt pipe cleanup */ 1126 ehci_root_hub_intr_pipe_cleanup(ehcip, USB_CR_NO_RESOURCES); 1127 } 1128 } 1129 1130 1131 /* 1132 * ehci_handle_complete_port_reset: 1133 * 1134 * Perform a port reset change. 1135 */ 1136 static void 1137 ehci_handle_complete_port_reset( 1138 ehci_state_t *ehcip, 1139 uint16_t port) 1140 { 1141 uint_t port_status; 1142 1143 mutex_enter(&ehcip->ehci_int_mutex); 1144 1145 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1146 ~EHCI_RH_PORT_CLEAR_MASK; 1147 1148 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1149 "ehci_handle_complete_port_reset: port = 0x%x status = 0x%x", 1150 port, port_status); 1151 1152 /* Check port is owned by ehci */ 1153 if (ehci_is_port_owner(ehcip, port) != USB_SUCCESS) { 1154 mutex_exit(&ehcip->ehci_int_mutex); 1155 1156 return; 1157 } 1158 1159 if (port_status & EHCI_RH_PORT_RESET) { 1160 Set_OpReg(ehci_rh_port_status[port], 1161 port_status & ~EHCI_RH_PORT_RESET); 1162 1163 } 1164 1165 mutex_exit(&ehcip->ehci_int_mutex); 1166 } 1167 1168 1169 /* 1170 * ehci_handle_clear_port_connection: 1171 * 1172 * Perform a clear port connection. 1173 */ 1174 static void 1175 ehci_handle_clear_port_connection( 1176 ehci_state_t *ehcip, 1177 uint16_t port) 1178 { 1179 uint_t port_status; 1180 1181 mutex_enter(&ehcip->ehci_int_mutex); 1182 1183 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1184 ~EHCI_RH_PORT_CLEAR_MASK; 1185 1186 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1187 "ehci_handle_clear_port_connection: port = 0x%x" 1188 "status = 0x%x", port, port_status); 1189 1190 Set_OpReg(ehci_rh_port_status[port], 1191 port_status | EHCI_RH_PORT_CONNECT_STS_CHANGE); 1192 1193 mutex_exit(&ehcip->ehci_int_mutex); 1194 } 1195 1196 1197 /* 1198 * ehci_handle_clrchng_port_over_current: 1199 * 1200 * Perform a clear port connection. 1201 */ 1202 static void 1203 ehci_handle_clrchng_port_over_current( 1204 ehci_state_t *ehcip, 1205 uint16_t port) 1206 { 1207 uint_t port_status; 1208 1209 mutex_enter(&ehcip->ehci_int_mutex); 1210 1211 port_status = Get_OpReg(ehci_rh_port_status[port]) & 1212 ~EHCI_RH_PORT_CLEAR_MASK; 1213 1214 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1215 "ehci_handle_clrchng_port_over_current: port = 0x%x" 1216 "status = 0x%x", port, port_status); 1217 1218 Set_OpReg(ehci_rh_port_status[port], 1219 port_status | EHCI_RH_PORT_OVER_CURR_CHANGE); 1220 1221 mutex_exit(&ehcip->ehci_int_mutex); 1222 } 1223 1224 1225 /* 1226 * ehci_handle_get_port_status: 1227 * 1228 * Handle a get port status request. 1229 */ 1230 static void 1231 ehci_handle_get_port_status( 1232 ehci_state_t *ehcip, 1233 uint16_t port) 1234 { 1235 usb_ctrl_req_t *ctrl_reqp; 1236 mblk_t *message; 1237 uint_t new_port_status = 0; 1238 uint_t change_status = 0; 1239 uint_t port_status; 1240 1241 mutex_enter(&ehcip->ehci_int_mutex); 1242 1243 ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1244 1245 /* Get the root hub port status information */ 1246 port_status = ehci_get_root_hub_port_status(ehcip, port); 1247 1248 new_port_status = port_status & PORT_STATUS_MASK; 1249 change_status = (port_status >> 16) & PORT_CHANGE_MASK; 1250 1251 ehcip->ehci_root_hub.rh_port_status[port] = new_port_status; 1252 1253 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1254 "ehci_handle_get_port_status: port = %d new status = 0x%x" 1255 "change = 0x%x", port, new_port_status, change_status); 1256 1257 message = ctrl_reqp->ctrl_data; 1258 1259 ASSERT(message != NULL); 1260 1261 *message->b_wptr++ = (uchar_t)new_port_status; 1262 *message->b_wptr++ = (uchar_t)(new_port_status >> 8); 1263 *message->b_wptr++ = (uchar_t)change_status; 1264 *message->b_wptr++ = (uchar_t)(change_status >> 8); 1265 1266 /* Save the data in control request */ 1267 ctrl_reqp->ctrl_data = message; 1268 1269 mutex_exit(&ehcip->ehci_int_mutex); 1270 } 1271 1272 1273 /* 1274 * ehci_handle_get_hub_descriptor: 1275 */ 1276 static void 1277 ehci_handle_get_hub_descriptor( 1278 ehci_state_t *ehcip) 1279 { 1280 usb_ctrl_req_t *ctrl_reqp; 1281 mblk_t *message; 1282 usb_hub_descr_t *root_hub_descr; 1283 size_t length; 1284 uchar_t raw_descr[ROOT_HUB_DESCRIPTOR_LENGTH]; 1285 1286 mutex_enter(&ehcip->ehci_int_mutex); 1287 1288 ctrl_reqp = ehcip->ehci_root_hub.rh_curr_ctrl_reqp; 1289 root_hub_descr = &ehcip->ehci_root_hub.rh_descr; 1290 length = ctrl_reqp->ctrl_wLength; 1291 1292 USB_DPRINTF_L4(PRINT_MASK_ROOT_HUB, ehcip->ehci_log_hdl, 1293 "ehci_handle_get_hub_descriptor: Ctrl Req = 0x%p", 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 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