1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2016 Joyent, Inc. 14 */ 15 16 /* 17 * xHCI Root Hub 18 * 19 * Please see the big theory statement in xhci.c for more information. 20 */ 21 22 #include <sys/usb/hcd/xhci/xhci.h> 23 24 /* 25 * The following structure and global define the default configuration that we 26 * 'deliver' to USBA on behalf of our hub. However, it's worth noting that it's 27 * going to take this in as an array of bytes off of the wire, whereas we're 28 * declaring this as a packed C structure to make our life much, much easier. 29 * It is critical that we pay attention to the endianness of anything that is 30 * more than a single byte wide and write the value in the appropriate 31 * endian-aware form. 32 * 33 * Note, we don't use the system structures for these values because they are 34 * not packed, and we must be. Even though we define all members, we still use 35 * C99 structure initialization to make it easier for folks to see what values 36 * are what in a long array of numbers. 37 * 38 * The structure is laid out first with members that make up a usb_cfg_descr_t. 39 * Then it has a usb_if_descr_t. After that, it has a usb_ep_descr_t and finally 40 * a usb_ep_ss_comp_descr_t. Please see the original structure definitions for 41 * the meaning of each member. 42 * 43 * Many of the values used below were derived from the USB 3.1/10.15.1 'Standard 44 * Descriptors for Hub Class'. 45 */ 46 #pragma pack(1) 47 typedef struct xhci_dev_conf { 48 /* usb_cfg_descr_t */ 49 uint8_t xdc_cfg_bLength; 50 uint8_t xdc_cfg_bDescriptorType; 51 uint16_t xdc_cfg_wTotalLength; 52 uint8_t xdc_cfg_bNumInterfaces; 53 uint8_t xdc_cfg_bConfigurationValue; 54 uint8_t xdc_cfg_iConfiguration; 55 uint8_t xdc_cfg_bmAttributes; 56 uint8_t xdc_cfg_bMaxPower; 57 /* usb_if_descr_t */ 58 uint8_t xdc_if_bLength; 59 uint8_t xdc_if_bDescriptorType; 60 uint8_t xdc_if_bInterfaceNumber; 61 uint8_t xdc_if_bAlternateSetting; 62 uint8_t xdc_if_bNumEndpoints; 63 uint8_t xdc_if_bInterfaceClass; 64 uint8_t xdc_if_bInterfaceSubClass; 65 uint8_t xdc_if_bInterfaceProtocol; 66 uint8_t xdc_if_iInterface; 67 /* usb_ep_descr_t */ 68 uint8_t xdc_ep_bLength; 69 uint8_t xdc_ep_bDescriptorType; 70 uint8_t xdc_ep_bEndpointAddress; 71 uint8_t xdc_ep_bmAttributes; 72 uint16_t xdc_ep_wMaxPacketSize; 73 uint8_t xdc_ep_bInterval; 74 /* usb_ep_ss_comp_descr_t */ 75 uint8_t xdc_epssc_bLength; 76 uint8_t xdc_epssc_bDescriptorType; 77 uint8_t xdc_epssc_bMaxBurst; 78 uint8_t xdc_epssc_bmAttributes; 79 uint16_t xdc_epssc_wBytesPerInterval; 80 } xhci_dev_conf_t; 81 #pragma pack() 82 83 #if MAX_PORTS != 31 84 #error "MAX_PORTS has changed, update xdc_ep_wMaxPacketSize" 85 #endif 86 87 xhci_dev_conf_t xhci_hcdi_conf = { 88 .xdc_cfg_bLength = 0x9, 89 .xdc_cfg_bDescriptorType = USB_DESCR_TYPE_CFG, 90 #if defined(_BIG_ENDIAN) 91 .xdc_cfg_wTotalLength = 0x1f00, 92 #elif defined(_LITTLE_ENDIAN) 93 .xdc_cfg_wTotalLength = 0x001f, 94 #else /* !_BIG_ENDIAN && !_LITTLE_ENDIAN */ 95 #error "Unknown endianness" 96 #endif /* _BIG_ENDIAN */ 97 .xdc_cfg_bNumInterfaces = 0x1, 98 .xdc_cfg_bConfigurationValue = 0x1, 99 .xdc_cfg_iConfiguration = 0x0, 100 .xdc_cfg_bmAttributes = 0x40, 101 .xdc_cfg_bMaxPower = 0x0, 102 103 .xdc_if_bLength = 0x9, 104 .xdc_if_bDescriptorType = USB_DESCR_TYPE_IF, 105 .xdc_if_bInterfaceNumber = 0x0, 106 .xdc_if_bAlternateSetting = 0x0, 107 .xdc_if_bNumEndpoints = 0x1, 108 .xdc_if_bInterfaceClass = USB_CLASS_HUB, 109 .xdc_if_bInterfaceSubClass = 0x0, 110 .xdc_if_bInterfaceProtocol = 0x0, 111 .xdc_if_iInterface = 0x0, 112 113 .xdc_ep_bLength = 0x7, 114 .xdc_ep_bDescriptorType = USB_DESCR_TYPE_EP, 115 .xdc_ep_bEndpointAddress = USB_EP_DIR_IN | ROOT_HUB_ADDR, 116 .xdc_ep_bmAttributes = USB_EP_ATTR_INTR, 117 118 /* 119 * We size the endpoint's maximum packet size based on the total number 120 * of ports that exist. This allows us to ensure that we can always 121 * deliver a status bit for every port, even if we're not strictly 122 * playing by the rules and have more than 16 ports. The system defines 123 * MAX_PORTS to be 31, therefore we set this to four, so we cover it 124 * all. 125 */ 126 #if defined(_BIG_ENDIAN) 127 .xdc_ep_wMaxPacketSize = 0x0400, 128 #elif defined(_LITTLE_ENDIAN) 129 .xdc_ep_wMaxPacketSize = 0x0004, 130 #else /* !_BIG_ENDIAN && !_LITTLE_ENDIAN */ 131 #error "Unknown endianness" 132 #endif /* _BIG_ENDIAN */ 133 .xdc_ep_bInterval = 0x8, 134 135 .xdc_epssc_bLength = 0x06, 136 .xdc_epssc_bDescriptorType = USB_DESCR_TYPE_SS_EP_COMP, 137 .xdc_epssc_bMaxBurst = 0, 138 .xdc_epssc_bmAttributes = 0, 139 #if defined(_BIG_ENDIAN) 140 .xdc_epssc_wBytesPerInterval = 0x0200 141 #elif defined(_LITTLE_ENDIAN) 142 .xdc_epssc_wBytesPerInterval = 0x0002 143 #else /* !_BIG_ENDIAN && !_LITTLE_ENDIAN */ 144 #error "Unknown endianness" 145 #endif /* _BIG_ENDIAN */ 146 }; 147 148 /* 149 * This is a standard device request as defined in USB 3.1 / 9.4.5. 150 */ 151 static int 152 xhci_root_hub_get_device_status(xhci_t *xhcip, usb_ctrl_req_t *ucrp) 153 { 154 uint16_t stand; 155 uint32_t psm; 156 uint8_t len; 157 mblk_t *mp; 158 159 ASSERT(MUTEX_HELD(&xhcip->xhci_lock)); 160 161 mp = ucrp->ctrl_data; 162 163 /* 164 * In the case where the request write length doesn't match what we 165 * expect, we still return that this is 'OK'; however, we don't 166 * increment the length, allowing the caller to basically see that we 167 * have no data / failed it. The behavior in this case is defined to be 168 * undefined and unfortuantely there's no great return value here for 169 * EINVAL. 170 */ 171 switch (ucrp->ctrl_wValue) { 172 case USB_GET_STATUS_STANDARD: 173 if (ucrp->ctrl_wLength != USB_GET_STATUS_LEN) 174 return (USB_CR_UNSPECIFIED_ERR); 175 len = USB_GET_STATUS_LEN; 176 stand = LE_16(USB_DEV_SLF_PWRD_STATUS); 177 bcopy(&stand, mp->b_wptr, sizeof (stand)); 178 break; 179 case USB_GET_STATUS_PTM: 180 if (ucrp->ctrl_wLength != USB_GET_STATUS_PTM_LEN) 181 return (USB_CR_UNSPECIFIED_ERR); 182 /* 183 * We don't support the root hub, so we always return zero. 184 */ 185 len = USB_GET_STATUS_PTM_LEN; 186 psm = 0; 187 bcopy(&psm, mp->b_wptr, sizeof (psm)); 188 break; 189 default: 190 return (USB_CR_NOT_SUPPORTED); 191 } 192 193 mp->b_wptr += len; 194 195 return (USB_CR_OK); 196 } 197 198 /* 199 * This is a hub class specific device request as defined in USB 3.1 / 200 * 11.24.2.6. 201 */ 202 static int 203 xhci_root_hub_get_status(xhci_t *xhcip, usb_ctrl_req_t *ucrp) 204 { 205 const uint32_t status = 0; 206 mblk_t *mp; 207 208 ASSERT(MUTEX_HELD(&xhcip->xhci_lock)); 209 210 if (ucrp->ctrl_wLength != HUB_GET_STATUS_LEN) 211 return (USB_CR_UNSPECIFIED_ERR); 212 mp = ucrp->ctrl_data; 213 214 bcopy(&status, mp->b_wptr, sizeof (status)); 215 mp->b_wptr += sizeof (status); 216 217 return (USB_CR_OK); 218 } 219 220 /* 221 * We've been asked to get the root hub's descriptor. According to USB 3.1 / 222 * 10.16.2.3 we return up to a maximum number of bytes based on the actual size 223 * of the request. It's not an error for it to request more or less. e.g. we 224 * only return MIN(req, sizeof (desc)). 225 */ 226 static void 227 xhci_root_hub_get_descriptor(xhci_t *xhcip, usb_ctrl_req_t *ucrp) 228 { 229 int len = MIN(sizeof (usb_ss_hub_descr_t), ucrp->ctrl_wLength); 230 231 ASSERT(MUTEX_HELD(&xhcip->xhci_lock)); 232 233 /* 234 * We maintain the root hub's description in a little-endian data format 235 * regardless of the platform. This means that we don't have to try to 236 * transform any of the data that we have inside of it when we deliver 237 * it to USBA. 238 */ 239 bcopy(&xhcip->xhci_usba.xa_hub_descr, ucrp->ctrl_data->b_wptr, len); 240 ucrp->ctrl_data->b_wptr += len; 241 } 242 243 static int 244 xhci_root_hub_handle_port_clear_feature(xhci_t *xhcip, usb_ctrl_req_t *ucrp) 245 { 246 int feat = ucrp->ctrl_wValue; 247 int port = XHCI_PS_INDPORT(ucrp->ctrl_wIndex); 248 uint32_t reg; 249 250 ASSERT(MUTEX_HELD(&xhcip->xhci_lock)); 251 252 if (port < 1 || port > xhcip->xhci_caps.xcap_max_ports) 253 return (USB_CR_UNSPECIFIED_ERR); 254 if (ucrp->ctrl_wLength != 0) 255 return (USB_CR_UNSPECIFIED_ERR); 256 257 reg = xhci_get32(xhcip, XHCI_R_OPER, XHCI_PORTSC(port)); 258 if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) { 259 xhci_error(xhcip, "failed to read port status register for " 260 "port %d: encountered fatal FM error, resetting device", 261 port); 262 xhci_fm_runtime_reset(xhcip); 263 return (USB_CR_HC_HARDWARE_ERR); 264 } 265 266 /* 267 * The port status and command register has many bits that we must 268 * preserve across writes, however, it also has bits that will be 269 * cleared when a bitwise one is written to them. As some of these 270 * write-one-to-clear bits may be set, we make sure to mask them off. 271 */ 272 reg &= ~XHCI_PS_CLEAR; 273 274 switch (feat) { 275 case CFS_PORT_ENABLE: 276 reg |= XHCI_PS_PED; 277 break; 278 case CFS_PORT_POWER: 279 reg &= ~XHCI_PS_PP; 280 break; 281 case CFS_C_PORT_CONNECTION: 282 reg |= XHCI_PS_CSC; 283 break; 284 case CFS_C_PORT_RESET: 285 reg |= XHCI_PS_PRC; 286 break; 287 case CFS_C_PORT_OVER_CURRENT: 288 reg |= XHCI_PS_OCC; 289 break; 290 case CFS_C_PORT_SUSPEND: 291 case CFS_C_PORT_LINK_STATE: 292 reg |= XHCI_PS_PLC; 293 break; 294 case CFS_C_PORT_ENABLE: 295 reg |= XHCI_PS_PEC; 296 break; 297 case CFS_C_PORT_CONFIG_ERROR: 298 reg |= XHCI_PS_CEC; 299 break; 300 case CFS_C_BH_PORT_RESET: 301 reg |= XHCI_PS_WRC; 302 break; 303 case CFS_PORT_SUSPEND: 304 default: 305 xhci_log(xhcip, "!asked to clear unsupported root hub " 306 "feature %d on port %d", feat, port); 307 return (USB_CR_NOT_SUPPORTED); 308 } 309 310 xhci_put32(xhcip, XHCI_R_OPER, XHCI_PORTSC(port), reg); 311 if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) { 312 xhci_error(xhcip, "failed to write port status register for " 313 "port %d: encountered fatal FM error, resetting device", 314 port); 315 xhci_fm_runtime_reset(xhcip); 316 return (USB_CR_HC_HARDWARE_ERR); 317 } 318 319 return (USB_CR_OK); 320 } 321 322 static int 323 xhci_root_hub_handle_port_set_feature(xhci_t *xhcip, usb_ctrl_req_t *ucrp) 324 { 325 int feat = ucrp->ctrl_wValue; 326 int port = XHCI_PS_INDPORT(ucrp->ctrl_wIndex); 327 uint32_t val = XHCI_PS_INDVAL(ucrp->ctrl_wIndex); 328 uint32_t reg; 329 uintptr_t index; 330 331 ASSERT(MUTEX_HELD(&xhcip->xhci_lock)); 332 333 if (port < 1 || port > xhcip->xhci_caps.xcap_max_ports) 334 return (USB_CR_UNSPECIFIED_ERR); 335 if (ucrp->ctrl_wLength != 0) 336 return (USB_CR_UNSPECIFIED_ERR); 337 338 index = XHCI_PORTSC(port); 339 reg = xhci_get32(xhcip, XHCI_R_OPER, index); 340 if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) { 341 xhci_error(xhcip, "failed to read port status register for " 342 "port %d: encountered fatal FM error, resetting device", 343 port); 344 xhci_fm_runtime_reset(xhcip); 345 return (USB_CR_HC_HARDWARE_ERR); 346 } 347 348 /* 349 * The port status and command register has many bits that we must 350 * preserve across writes, however, it also has bits that will be 351 * cleared when a bitwise one is written to them. As some of these 352 * write-one-to-clear bits may be set, we make sure to mask them off. 353 */ 354 reg &= ~XHCI_PS_CLEAR; 355 356 switch (feat) { 357 case CFS_PORT_U1_TIMEOUT: 358 index = XHCI_PORTPMSC(port); 359 reg = xhci_get32(xhcip, XHCI_R_OPER, index); 360 if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) { 361 xhci_error(xhcip, "failed to read port power " 362 "management register for port %d: encountered " 363 "fatal FM error, resetting device", port); 364 xhci_fm_runtime_reset(xhcip); 365 return (USB_CR_HC_HARDWARE_ERR); 366 } 367 reg &= ~XHCI_PM3_U1TO_SET(0xff); 368 reg |= XHCI_PM3_U1TO_SET(val); 369 break; 370 case CFS_PORT_U2_TIMEOUT: 371 index = XHCI_PORTPMSC(port); 372 reg = xhci_get32(xhcip, XHCI_R_OPER, index); 373 if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) { 374 xhci_error(xhcip, "failed to read port power " 375 "management register for port %d: encountered " 376 "fatal FM error, resetting device", port); 377 xhci_fm_runtime_reset(xhcip); 378 return (USB_CR_HC_HARDWARE_ERR); 379 } 380 reg &= ~XHCI_PM3_U1TO_SET(0xff); 381 reg |= XHCI_PM3_U1TO_SET(val); 382 break; 383 case CFS_PORT_LINK_STATE: 384 reg |= XHCI_PS_PLS_SET(val); 385 reg |= XHCI_PS_LWS; 386 break; 387 case CFS_PORT_REMOTE_WAKE_MASK: 388 if (val & CFS_PRWM_CONN_ENABLE) 389 reg |= XHCI_PS_WCE; 390 else 391 reg &= ~XHCI_PS_WCE; 392 393 if (val & CFS_PRWM_DISCONN_ENABLE) 394 reg |= XHCI_PS_WDE; 395 else 396 reg &= ~XHCI_PS_WDE; 397 398 if (val & CFS_PRWM_OC_ENABLE) 399 reg |= XHCI_PS_WOE; 400 else 401 reg &= ~XHCI_PS_WOE; 402 break; 403 case CFS_BH_PORT_RESET: 404 reg |= XHCI_PS_WPR; 405 break; 406 case CFS_PORT_RESET: 407 reg |= XHCI_PS_PR; 408 break; 409 case CFS_PORT_POWER: 410 reg |= XHCI_PS_PP; 411 break; 412 case CFS_PORT_ENABLE: 413 /* 414 * Enabling happens automatically for both USB 2 and USB 3. So 415 * there's nothing specific to set here. 416 */ 417 return (USB_CR_OK); 418 case CFS_PORT_SUSPEND: 419 default: 420 xhci_log(xhcip, "!asked to set unsupported root hub " 421 "feature %d on port %d", feat, port); 422 return (USB_CR_NOT_SUPPORTED); 423 } 424 425 xhci_put32(xhcip, XHCI_R_OPER, index, reg); 426 if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) { 427 xhci_error(xhcip, "failed to write port status register for " 428 "port %d: encountered fatal FM error, resetting device", 429 port); 430 xhci_fm_runtime_reset(xhcip); 431 return (USB_CR_HC_HARDWARE_ERR); 432 } 433 434 return (USB_CR_OK); 435 } 436 437 /* 438 * We've been asked to get the port's status. While there are multiple forms 439 * that the port status request can take, we only support the primary one. The 440 * enhanced version is only in USB 3.1. 441 * 442 * Note that we don't end up explicitly adding a speed value for the port, 443 * because the only valid values are zero. 444 */ 445 static int 446 xhci_root_hub_handle_port_get_status(xhci_t *xhcip, usb_ctrl_req_t *ucrp) 447 { 448 uint32_t reg; 449 uint16_t ps, cs; 450 mblk_t *mp = ucrp->ctrl_data; 451 int port = XHCI_PS_INDPORT(ucrp->ctrl_wIndex); 452 453 ASSERT(MUTEX_HELD(&xhcip->xhci_lock)); 454 455 if (port < 1 || port > xhcip->xhci_caps.xcap_max_ports) 456 return (USB_CR_UNSPECIFIED_ERR); 457 458 if (ucrp->ctrl_wValue != PORT_GET_STATUS_PORT) 459 return (USB_CR_NOT_SUPPORTED); 460 461 if (ucrp->ctrl_wLength != PORT_GET_STATUS_PORT_LEN) 462 return (USB_CR_UNSPECIFIED_ERR); 463 464 reg = xhci_get32(xhcip, XHCI_R_OPER, XHCI_PORTSC(port)); 465 if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) { 466 xhci_error(xhcip, "failed to read port status register for " 467 "port %d: encountered fatal FM error, resetting device", 468 port); 469 xhci_fm_runtime_reset(xhcip); 470 return (USB_CR_HC_HARDWARE_ERR); 471 } 472 473 ps = cs = 0; 474 if (reg & XHCI_PS_CCS) 475 ps |= PORT_STATUS_CCS; 476 if (reg & XHCI_PS_PED) 477 ps |= PORT_STATUS_PES; 478 if (reg & XHCI_PS_OCA) 479 ps |= PORT_STATUS_POCI; 480 if (reg & XHCI_PS_PR) 481 ps |= PORT_STATUS_PRS; 482 483 ps |= XHCI_PS_PLS_SET(XHCI_PS_PLS_GET(reg)); 484 485 if (reg & XHCI_PS_PP) 486 ps |= PORT_STATUS_PPS; 487 488 /* 489 * While this isn't a defined part of the status, because we're not a 490 * true USB 3 hub, this is the only primary way that we can tell USBA 491 * what the actual speed of the device is. It's a bit dirty, but there's 492 * not really a great alternative at the moment. 493 */ 494 switch (XHCI_PS_SPEED_GET(reg)) { 495 case XHCI_SPEED_FULL: 496 ps |= USBA_FULL_SPEED_DEV << PORT_STATUS_SPSHIFT_SS; 497 break; 498 case XHCI_SPEED_LOW: 499 ps |= USBA_LOW_SPEED_DEV << PORT_STATUS_SPSHIFT_SS; 500 break; 501 case XHCI_SPEED_HIGH: 502 ps |= USBA_HIGH_SPEED_DEV << PORT_STATUS_SPSHIFT_SS; 503 break; 504 case XHCI_SPEED_SUPER: 505 default: 506 /* 507 * If we encounter something we don't know, we're going to start 508 * by assuming it is SuperSpeed, as so far all additions have 509 * been purely faster than SuperSpeed and have the same external 510 * behavior. 511 */ 512 ps |= USBA_SUPER_SPEED_DEV << PORT_STATUS_SPSHIFT_SS; 513 break; 514 } 515 516 if (reg & XHCI_PS_CSC) 517 cs |= PORT_CHANGE_CSC; 518 if (reg & XHCI_PS_PEC) 519 cs |= PORT_CHANGE_PESC; 520 if (reg & XHCI_PS_OCC) 521 cs |= PORT_CHANGE_OCIC; 522 if (reg & XHCI_PS_PRC) 523 cs |= PORT_CHANGE_PRSC; 524 if (reg & XHCI_PS_WRC) 525 cs |= PORT_CHANGE_BHPR; 526 if (reg & XHCI_PS_PLC) 527 cs |= PORT_CHANGE_PLSC; 528 if (reg & XHCI_PS_CEC) 529 cs |= PORT_CHANGE_PCE; 530 531 cs = LE_16(cs); 532 ps = LE_16(ps); 533 bcopy(&ps, mp->b_wptr, sizeof (uint16_t)); 534 mp->b_wptr += sizeof (uint16_t); 535 bcopy(&cs, mp->b_wptr, sizeof (uint16_t)); 536 mp->b_wptr += sizeof (uint16_t); 537 538 return (USB_CR_OK); 539 } 540 541 /* 542 * USBA has issued a request for the root hub. We need to determine what it's 543 * asking about and then figure out how to handle it and how to respond. 544 */ 545 int 546 xhci_root_hub_ctrl_req(xhci_t *xhcip, usba_pipe_handle_data_t *ph, 547 usb_ctrl_req_t *ucrp) 548 { 549 int ret = USB_CR_OK; 550 551 ASSERT(MUTEX_HELD(&xhcip->xhci_lock)); 552 553 switch (ucrp->ctrl_bmRequestType) { 554 case HUB_GET_DEVICE_STATUS_TYPE: 555 ret = xhci_root_hub_get_device_status(xhcip, ucrp); 556 break; 557 case HUB_HANDLE_PORT_FEATURE_TYPE: 558 switch (ucrp->ctrl_bRequest) { 559 case USB_REQ_CLEAR_FEATURE: 560 ret = xhci_root_hub_handle_port_clear_feature(xhcip, 561 ucrp); 562 break; 563 case USB_REQ_SET_FEATURE: 564 ret = xhci_root_hub_handle_port_set_feature(xhcip, 565 ucrp); 566 break; 567 default: 568 ret = USB_CR_NOT_SUPPORTED; 569 break; 570 } 571 break; 572 case HUB_GET_PORT_STATUS_TYPE: 573 ret = xhci_root_hub_handle_port_get_status(xhcip, ucrp); 574 break; 575 case HUB_CLASS_REQ_TYPE: 576 switch (ucrp->ctrl_bRequest) { 577 case USB_REQ_GET_STATUS: 578 ret = xhci_root_hub_get_status(xhcip, ucrp); 579 break; 580 case USB_REQ_GET_DESCR: 581 xhci_root_hub_get_descriptor(xhcip, ucrp); 582 break; 583 default: 584 xhci_error(xhcip, "Unhandled hub request: 0x%x\n", 585 ucrp->ctrl_bRequest); 586 ret = USB_CR_NOT_SUPPORTED; 587 break; 588 } 589 break; 590 default: 591 xhci_error(xhcip, "Unhandled hub request type: %x\n", 592 ucrp->ctrl_bmRequestType); 593 ret = USB_CR_NOT_SUPPORTED; 594 break; 595 } 596 597 mutex_exit(&xhcip->xhci_lock); 598 usba_hcdi_cb(ph, (usb_opaque_t)ucrp, ret); 599 mutex_enter(&xhcip->xhci_lock); 600 601 return (USB_SUCCESS); 602 } 603 604 /* 605 * This function is invoked whenever the root HUBs interrupt endpoint is opened 606 * or we receive an port change event notification from the hardware on the 607 * event ring from an interrupt. 608 * 609 * If we have a registered interrupt callback requested, then we have to 610 * duplicate the request so we can send it back to usba and then we generate the 611 * actual status message and send it. 612 */ 613 void 614 xhci_root_hub_psc_callback(xhci_t *xhcip) 615 { 616 usb_intr_req_t *req, *new; 617 usba_pipe_handle_data_t *ph; 618 mblk_t *mp; 619 uint32_t mask; 620 unsigned i; 621 622 mask = 0; 623 for (i = 0; i <= xhcip->xhci_caps.xcap_max_ports; i++) { 624 uint32_t reg; 625 626 reg = xhci_get32(xhcip, XHCI_R_OPER, XHCI_PORTSC(i)); 627 if ((reg & XHCI_HUB_INTR_CHANGE_MASK) != 0) 628 mask |= 1UL << i; 629 } 630 631 if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) { 632 xhci_error(xhcip, "failed to read port status registers: " 633 "encountered fatal FM error, resetting device"); 634 xhci_fm_runtime_reset(xhcip); 635 return; 636 } 637 if (mask == 0) 638 return; 639 640 mask = LE_32(mask); 641 642 mutex_enter(&xhcip->xhci_lock); 643 if (xhcip->xhci_usba.xa_intr_cb_req == NULL) { 644 mutex_exit(&xhcip->xhci_lock); 645 return; 646 } 647 648 ASSERT(xhcip->xhci_usba.xa_intr_cb_ph != NULL); 649 req = xhcip->xhci_usba.xa_intr_cb_req; 650 ph = xhcip->xhci_usba.xa_intr_cb_ph; 651 652 new = usba_hcdi_dup_intr_req(ph->p_dip, req, req->intr_len, 0); 653 if (new == NULL) { 654 new = xhcip->xhci_usba.xa_intr_cb_req; 655 xhcip->xhci_usba.xa_intr_cb_req = NULL; 656 mutex_exit(&xhcip->xhci_lock); 657 usba_hcdi_cb(ph, (usb_opaque_t)new, USB_CR_NO_RESOURCES); 658 return; 659 } 660 661 /* 662 * Why yes, we do have to manually increment this for the given pipe 663 * before we deliver it. If we don't, it has no way of knowing that 664 * there's another request inbound and we'll simply blow our assertions 665 * on requests. 666 */ 667 mutex_enter(&ph->p_mutex); 668 ph->p_req_count++; 669 mutex_exit(&ph->p_mutex); 670 671 mp = new->intr_data; 672 bcopy(&mask, mp->b_wptr, sizeof (mask)); 673 mp->b_wptr += sizeof (mask); 674 675 mutex_exit(&xhcip->xhci_lock); 676 677 usba_hcdi_cb(ph, (usb_opaque_t)new, USB_CR_OK); 678 } 679 680 void 681 xhci_root_hub_intr_root_disable(xhci_t *xhcip) 682 { 683 usba_pipe_handle_data_t *ph; 684 usb_intr_req_t *uirp; 685 686 ASSERT(MUTEX_HELD(&xhcip->xhci_lock)); 687 688 ph = xhcip->xhci_usba.xa_intr_cb_ph; 689 xhcip->xhci_usba.xa_intr_cb_ph = NULL; 690 ASSERT(ph != NULL); 691 692 /* 693 * If the uirp here is NULL, it's because we ran out of resources at 694 * some point in xhci_hcdi_psc_callback(). 695 */ 696 uirp = xhcip->xhci_usba.xa_intr_cb_req; 697 xhcip->xhci_usba.xa_intr_cb_req = NULL; 698 if (uirp == NULL) { 699 return; 700 } 701 702 mutex_exit(&xhcip->xhci_lock); 703 usba_hcdi_cb(ph, (usb_opaque_t)uirp, USB_CR_STOPPED_POLLING); 704 mutex_enter(&xhcip->xhci_lock); 705 706 } 707 708 int 709 xhci_root_hub_intr_root_enable(xhci_t *xhcip, usba_pipe_handle_data_t *ph, 710 usb_intr_req_t *uirp) 711 { 712 ASSERT((ph->p_ep.bEndpointAddress & USB_EP_NUM_MASK) == 1); 713 ASSERT((uirp->intr_attributes & USB_ATTRS_ONE_XFER) == 0); 714 715 mutex_enter(&xhcip->xhci_lock); 716 if (xhcip->xhci_state & XHCI_S_ERROR) { 717 mutex_exit(&xhcip->xhci_lock); 718 return (USB_HC_HARDWARE_ERROR); 719 } 720 721 if (xhcip->xhci_usba.xa_intr_cb_ph != NULL) { 722 mutex_exit(&xhcip->xhci_lock); 723 return (USB_BUSY); 724 } 725 726 xhcip->xhci_usba.xa_intr_cb_ph = ph; 727 xhcip->xhci_usba.xa_intr_cb_req = uirp; 728 729 /* 730 * USBA is expecting us to act like a hub and therefore whenever we open 731 * up the interrupt endpoint, we need to generate an event with 732 * information about all the currently outstanding ports with changes. 733 */ 734 mutex_exit(&xhcip->xhci_lock); 735 xhci_root_hub_psc_callback(xhcip); 736 737 return (USB_SUCCESS); 738 } 739 740 int 741 xhci_root_hub_fini(xhci_t *xhcip) 742 { 743 if (usba_hubdi_unbind_root_hub(xhcip->xhci_dip) != USB_SUCCESS) 744 return (DDI_FAILURE); 745 746 return (DDI_SUCCESS); 747 } 748 749 static int 750 xhci_root_hub_fill_hub_desc(xhci_t *xhcip) 751 { 752 int i; 753 uint16_t chars; 754 usb_ss_hub_descr_t *hdp = &xhcip->xhci_usba.xa_hub_descr; 755 756 bzero(hdp, sizeof (usb_ss_hub_descr_t)); 757 758 hdp->bDescLength = sizeof (usb_ss_hub_descr_t); 759 hdp->bDescriptorType = ROOT_HUB_SS_DESCRIPTOR_TYPE; 760 hdp->bNbrPorts = xhcip->xhci_caps.xcap_max_ports; 761 762 chars = 0; 763 if (xhcip->xhci_caps.xcap_flags & XCAP_PPC) 764 chars |= HUB_CHARS_INDIVIDUAL_PORT_POWER; 765 chars |= HUB_CHARS_INDIV_OVER_CURRENT; 766 hdp->wHubCharacteristics = LE_16(chars); 767 hdp->bPwrOn2PwrGood = XHCI_POWER_GOOD; 768 hdp->bHubContrCurrent = 0; 769 770 /* 771 * There doesn't appear to be a good way to determine what the impact of 772 * the root hub on the link should be. However, one way to view it is 773 * because everything must transfer through here the impact doesn't 774 * really matter, as everyone is subject to it. 775 */ 776 hdp->bHubHdrDecLat = 0; 777 hdp->wHubDelay = 0; 778 779 for (i = 1; i < xhcip->xhci_caps.xcap_max_ports; i++) { 780 uint32_t reg; 781 782 reg = xhci_get32(xhcip, XHCI_R_OPER, XHCI_PORTSC(i)); 783 if (xhci_check_regs_acc(xhcip) != DDI_FM_OK) { 784 xhci_error(xhcip, "encountered fatal FM error while " 785 "reading port status register %d", i); 786 ddi_fm_service_impact(xhcip->xhci_dip, 787 DDI_SERVICE_LOST); 788 return (EIO); 789 } 790 791 if (reg & XHCI_PS_DR) 792 hdp->DeviceRemovable[i / 8] |= 1U << (i % 8); 793 } 794 795 return (0); 796 } 797 798 799 /* 800 * Convert the USB PCI revision which is a uint8_t with 4-bit major and 4-bit 801 * minor into a uint16_t with a 8-bit major and 8-bit minor. 802 */ 803 static uint16_t 804 xhci_root_vers_to_bcd(uint8_t vers) 805 { 806 uint8_t major, minor; 807 808 major = (vers & 0xf0) >> 4; 809 minor = (vers & 0x0f); 810 return ((major << 8) | minor); 811 } 812 813 static void 814 xhci_root_hub_fill_dev_desc(xhci_t *xhcip, usb_dev_descr_t *hub) 815 { 816 hub->bLength = sizeof (usb_dev_descr_t); 817 818 /* 819 * The descriptor type is that for a device, which is 0x1. 820 */ 821 hub->bDescriptorType = 0x01; 822 hub->bcdUSB = xhci_root_vers_to_bcd(xhcip->xhci_caps.xcap_usb_vers); 823 824 /* 825 * As we're trying to pretend we're a hub, we have a fixed device id of 826 * 0x09. Note, that the device protocol for a super-speed hub 827 * technically isn't registered as 0x3; however, a vast majority of 828 * systems out there fake this up to indicate that it's a USB 3.x era 829 * device. This is presumably due to the suggestions as made in USB 3.1 830 * / 10.5.1. 831 */ 832 hub->bDeviceClass = USB_CLASS_HUB; 833 hub->bDeviceSubClass = 0x00; 834 hub->bDeviceProtocol = 0x03; 835 836 /* 837 * The only valid value for a USB 3 device is 09h as indicated in USB 838 * 3.1 / 9.6.6. 839 */ 840 hub->bMaxPacketSize0 = 9; 841 842 /* 843 * We have no real identification information, so we set it all to 844 * zero. 845 */ 846 hub->idVendor = 0x00; 847 hub->idProduct = 0x00; 848 hub->bcdDevice = 0x00; 849 hub->iManufacturer = 0x00; 850 hub->iProduct = 0x00; 851 hub->iSerialNumber = 0x00; 852 853 /* 854 * To keep our lives simple, we only have a single piece of 855 * configuration for this device. 856 */ 857 hub->bNumConfigurations = 0x01; 858 } 859 860 /* 861 * To register a root hub with the framework, we need to fake up a bunch of 862 * information for usba, particularly we need to basically feed it the device 863 * configuration in the form that USB expects. See section 10.15.1 for more 864 * information. 865 */ 866 int 867 xhci_root_hub_init(xhci_t *xhcip) 868 { 869 usb_dev_descr_t *hub = &xhcip->xhci_usba.xa_dev_descr; 870 uchar_t *conf = (uchar_t *)&xhci_hcdi_conf; 871 872 xhci_root_hub_fill_dev_desc(xhcip, hub); 873 if (xhci_root_hub_fill_hub_desc(xhcip) != 0) 874 return (DDI_FAILURE); 875 876 if (usba_hubdi_bind_root_hub(xhcip->xhci_dip, conf, 877 sizeof (xhci_hcdi_conf), hub) != USB_SUCCESS) 878 return (DDI_FAILURE); 879 880 return (DDI_SUCCESS); 881 } 882