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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * The Data Transfer Interface driver for Host Wire Adapter device 28 * 29 * This file mainly contains the entries for HCDI interfaces. 30 */ 31 #include <sys/usb/usba/usba_impl.h> /* usba_get_dip */ 32 #include <sys/usb/hwa/hwahc/hwahc.h> 33 #include <sys/usb/hwa/hwahc/hwahc_util.h> 34 #include <sys/strsubr.h> 35 #include <sys/strsun.h> /* MBLKL */ 36 37 #define WUSB_GTK 1 38 #define WUSB_PTK 2 39 40 /* function prototypes */ 41 static int hwahc_state_is_operational(hwahc_state_t *hwahcp); 42 static hwahc_state_t *hwahc_obtain_state(dev_info_t *dip); 43 static void hwahc_wait_for_xfer_completion(hwahc_state_t *hwahcp, 44 hwahc_pipe_private_t *pp); 45 static void hwahc_traverse_requests(hwahc_state_t *hwahcp, 46 hwahc_pipe_private_t *pp); 47 static void hwahc_pipe_cleanup(hwahc_state_t *hwahcp, 48 usba_pipe_handle_data_t *ph); 49 int hwahc_set_dev_encrypt(usb_pipe_handle_t ph, uint8_t ifc, 50 usb_port_t index, wusb_secrt_data_t *secrt_data, uint8_t type); 51 52 static int hwahc_hcdi_pm_support(dev_info_t *dip); 53 static int hwahc_hcdi_pipe_open(usba_pipe_handle_data_t *ph, 54 usb_flags_t flags); 55 static int hwahc_hcdi_pipe_close(usba_pipe_handle_data_t *ph, 56 usb_flags_t flags); 57 static int hwahc_hcdi_pipe_reset(usba_pipe_handle_data_t *ph, 58 usb_flags_t flags); 59 static void hwahc_hcdi_pipe_reset_data_toggle(usba_pipe_handle_data_t *ph); 60 static int hwahc_hcdi_pipe_ctrl_xfer(usba_pipe_handle_data_t *ph, 61 usb_ctrl_req_t *ctrl_reqp, usb_flags_t usb_flags); 62 static int hwahc_hcdi_pipe_bulk_xfer(usba_pipe_handle_data_t *ph, 63 usb_bulk_req_t *bulk_reqp, usb_flags_t usb_flags); 64 static int hwahc_hcdi_pipe_intr_xfer(usba_pipe_handle_data_t *ph, 65 usb_intr_req_t *intr_reqp, usb_flags_t usb_flags); 66 static int hwahc_hcdi_pipe_isoc_xfer(usba_pipe_handle_data_t *ph, 67 usb_isoc_req_t *isoc_reqp, usb_flags_t usb_flags); 68 static int hwahc_hcdi_bulk_transfer_size(usba_device_t *usba_device, 69 size_t *size); 70 static int hwahc_hcdi_pipe_stop_intr_polling(usba_pipe_handle_data_t *ph, 71 usb_flags_t flags); 72 static int hwahc_hcdi_pipe_stop_isoc_polling(usba_pipe_handle_data_t *ph, 73 usb_flags_t flags); 74 static int hwahc_hcdi_get_current_frame_number(usba_device_t *usba_device, 75 usb_frame_number_t *frame_number); 76 static int hwahc_hcdi_get_max_isoc_pkts(usba_device_t *usba_device, 77 uint_t *max_pkts); 78 static int hwahc_hcdi_polled_input_init(usba_pipe_handle_data_t *ph, 79 uchar_t **polled_buf, usb_console_info_impl_t *console_input_info); 80 static int hwahc_hcdi_polled_input_fini(usb_console_info_impl_t *info); 81 static int hwahc_hcdi_polled_input_enter(usb_console_info_impl_t *info); 82 static int hwahc_hcdi_polled_input_exit(usb_console_info_impl_t *info); 83 static int hwahc_hcdi_polled_read(usb_console_info_impl_t *info, 84 uint_t *num_characters); 85 usba_hcdi_ops_t *hwahc_alloc_hcdi_ops(hwahc_state_t *hwahcp); 86 87 extern void *hwahc_statep; 88 89 /* Check the Host controller state and return proper values */ 90 static int 91 hwahc_state_is_operational(hwahc_state_t *hwahcp) 92 { 93 int rval; 94 95 ASSERT(mutex_owned(&hwahcp->hwahc_mutex)); 96 97 if (hwahcp->hwahc_dev_state != USB_DEV_ONLINE) { 98 99 return (USB_FAILURE); 100 } 101 102 switch (hwahcp->hwahc_hc_soft_state) { 103 case HWAHC_CTRL_INIT_STATE: 104 rval = USB_FAILURE; 105 break; 106 case HWAHC_CTRL_OPERATIONAL_STATE: 107 /* still need to check if channel is operational */ 108 if (hwahcp->hwahc_hw_state != HWAHC_HW_STARTED) { 109 rval = USB_FAILURE; 110 } else { 111 rval = USB_SUCCESS; 112 } 113 114 break; 115 case HWAHC_CTRL_ERROR_STATE: 116 rval = USB_HC_HARDWARE_ERROR; 117 break; 118 default: 119 rval = USB_FAILURE; 120 break; 121 } 122 123 return (rval); 124 } 125 126 /* get soft state pointer */ 127 hwahc_state_t * 128 hwahc_obtain_state(dev_info_t *dip) 129 { 130 int instance = ddi_get_instance(dip); 131 132 hwahc_state_t *hwahcp = ddi_get_soft_state(hwahc_statep, instance); 133 134 ASSERT(hwahcp != NULL); 135 136 return (hwahcp); 137 } 138 139 140 /* 141 * Do not support wusb bus PM now 142 */ 143 /* ARGSUSED */ 144 static int 145 hwahc_hcdi_pm_support(dev_info_t *dip) 146 { 147 return (USB_FAILURE); 148 } 149 150 static void 151 /* ARGSUSED */ 152 hwahc_hcdi_pipe_reset_data_toggle(usba_pipe_handle_data_t *ph) 153 { 154 /* don't do anything now */ 155 } 156 157 /* Wait for processing all completed transfers and to send results */ 158 static void 159 hwahc_wait_for_xfer_completion(hwahc_state_t *hwahcp, hwahc_pipe_private_t *pp) 160 { 161 wusb_wa_rpipe_hdl_t *hdl = pp->pp_rp; 162 163 mutex_enter(&hdl->rp_mutex); 164 if (hdl->rp_state != WA_RPIPE_STATE_ACTIVE) { 165 mutex_exit(&hdl->rp_mutex); 166 167 return; 168 } 169 mutex_exit(&hdl->rp_mutex); 170 171 /* wait 3s */ 172 (void) cv_reltimedwait(&pp->pp_xfer_cmpl_cv, &hwahcp->hwahc_mutex, 173 drv_usectohz(3000000), TR_CLOCK_TICK); 174 175 mutex_enter(&hdl->rp_mutex); 176 if (hdl->rp_state == WA_RPIPE_STATE_ACTIVE) { 177 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 178 "hwahc_wait_for_xfer_completion: no transfer completion " 179 "confirmation received"); 180 } 181 mutex_exit(&hdl->rp_mutex); 182 } 183 184 /* remove all the unprocessed requests and do callback */ 185 /* ARGSUSED */ 186 static void 187 hwahc_traverse_requests(hwahc_state_t *hwahcp, hwahc_pipe_private_t *pp) 188 { 189 wusb_wa_rpipe_hdl_t *hdl = pp->pp_rp; 190 wusb_wa_trans_wrapper_t *wr; 191 192 mutex_enter(&hdl->rp_mutex); 193 194 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 195 "hwahc_traverse_requests: pp = 0x%p, wr=%p", (void*)pp, 196 (void *)hdl->rp_curr_wr); 197 198 wr = hdl->rp_curr_wr; 199 if (wr != NULL) { 200 wusb_wa_stop_xfer_timer(wr); 201 hdl->rp_state = WA_RPIPE_STATE_IDLE; 202 hdl->rp_curr_wr = NULL; 203 wr->wr_state = WR_ABORTED; 204 mutex_exit(&hdl->rp_mutex); 205 206 mutex_exit(&hwahcp->hwahc_mutex); 207 208 /* 209 * This CR is to tell USBA to mark this pipe as IDLE, 210 * so that do not queue client requests at USBA. Requests 211 * sent after pipe close/reset will be handled by hwahc. 212 */ 213 wr->wr_cb(wr->wr_wa_data, wr, USB_CR_NOT_SUPPORTED, 0); 214 215 mutex_enter(&hwahcp->hwahc_mutex); 216 mutex_enter(&hdl->rp_mutex); 217 } 218 mutex_exit(&hdl->rp_mutex); 219 } 220 221 /* process periodic(INTR/ISOC) requests */ 222 static void 223 hwahc_do_client_periodic_in_req_callback(hwahc_state_t *hwahcp, 224 hwahc_pipe_private_t *pp, usb_cr_t completion_reason) 225 { 226 usb_ep_descr_t *eptd; 227 228 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 229 "hwahc_do_client_periodic_in_req_callback: enter"); 230 231 /* 232 * Check for Interrupt/Isochronous IN, whether we need to do 233 * callback for the original client's periodic IN request. 234 */ 235 eptd = &(pp->pp_pipe_handle->p_ep); 236 if (pp->pp_client_periodic_in_reqp) { 237 if (WUSB_ISOC_ENDPOINT(eptd)) { 238 /* not supported */ 239 USB_DPRINTF_L4(PRINT_MASK_HCDI, 240 hwahcp->hwahc_log_handle, 241 "hwahc_do_client_periodic_in_req_callback: " 242 "ISOC xfer not support"); 243 } else { 244 /* 245 * NULL wr to tell the function that we're done and 246 * should clear pipe's pp_client_periodic_in_reqp 247 */ 248 wusb_wa_callback(&hwahcp->hwahc_wa_data, 249 pp->pp_pipe_handle, NULL, completion_reason); 250 } 251 } 252 253 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 254 "hwahc_do_client_periodic_in_req_callback: end"); 255 } 256 257 /* 258 * clean up the pipe, called by pipe_close/pipe_reset 259 * - Abort RPipe operation 260 * - Clean pending requests queueing on this pipe 261 */ 262 static void 263 hwahc_pipe_cleanup(hwahc_state_t *hwahcp, usba_pipe_handle_data_t *ph) 264 { 265 hwahc_pipe_private_t *pp; 266 wusb_wa_rpipe_hdl_t *hdl; 267 int rval; 268 usb_ep_descr_t *eptd; 269 usb_cr_t completion_reason; 270 271 pp = (hwahc_pipe_private_t *)ph->p_hcd_private; 272 273 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 274 "hwahc_pipe_cleanup: ph = 0x%p, p_req_cnt, ep=0x%02x," 275 " state=%d", (void *) ph, ph->p_ep.bEndpointAddress, 276 pp->pp_state); 277 278 ASSERT(mutex_owned(&hwahcp->hwahc_mutex)); 279 ASSERT(!servicing_interrupt()); 280 281 hdl = pp->pp_rp; 282 283 if (hwahcp->hwahc_dev_state == USB_DEV_ONLINE) { 284 /* abort rpipe */ 285 mutex_enter(&hdl->rp_mutex); 286 287 /* if active, abort the requests */ 288 if (hdl->rp_state == WA_RPIPE_STATE_ACTIVE) { 289 mutex_exit(&hdl->rp_mutex); 290 mutex_exit(&hwahcp->hwahc_mutex); 291 rval = wusb_wa_rpipe_abort(hwahcp->hwahc_dip, 292 hwahcp->hwahc_default_pipe, hdl); 293 mutex_enter(&hwahcp->hwahc_mutex); 294 mutex_enter(&hdl->rp_mutex); 295 } 296 mutex_exit(&hdl->rp_mutex); 297 298 /* wait for transfers to complete */ 299 hwahc_wait_for_xfer_completion(hwahcp, pp); 300 } 301 302 /* remove all unprocessed requests on this pipe and do callback */ 303 hwahc_traverse_requests(hwahcp, pp); 304 305 switch (pp->pp_state) { 306 case HWAHC_PIPE_STATE_CLOSE: 307 completion_reason = USB_CR_PIPE_CLOSING; 308 309 mutex_exit(&hwahcp->hwahc_mutex); 310 (void) wusb_wa_rpipe_reset(hwahcp->hwahc_dip, ph, hdl, 0); 311 mutex_enter(&hwahcp->hwahc_mutex); 312 313 break; 314 case HWAHC_PIPE_STATE_RESET: 315 case HWAHC_PIPE_STATE_ERROR: 316 completion_reason = USB_CR_PIPE_RESET; 317 if (hwahcp->hwahc_dev_state == USB_DEV_ONLINE) { 318 mutex_exit(&hwahcp->hwahc_mutex); 319 /* 320 * reset WA's RPipe. 321 * If this pipe is not bound to the default endpoint, 322 * also send a clear_feature request to that ep. 323 */ 324 rval = wusb_wa_rpipe_reset(hwahcp->hwahc_dip, 325 ph, hdl, 1); 326 mutex_enter(&hwahcp->hwahc_mutex); 327 328 USB_DPRINTF_L4(PRINT_MASK_HCDI, 329 hwahcp->hwahc_log_handle, 330 "hwahc_pipe_cleanup: rp reset, rv=%d", 331 rval); 332 333 pp->pp_state = HWAHC_PIPE_STATE_IDLE; 334 } 335 336 break; 337 case HWAHC_PIPE_STATE_STOP_POLLING: 338 completion_reason = USB_CR_STOPPED_POLLING; 339 pp->pp_state = HWAHC_PIPE_STATE_IDLE; 340 341 break; 342 } 343 344 /* 345 * Do the callback for the original client 346 * periodic IN request. 347 */ 348 eptd = &ph->p_ep; 349 350 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 351 "hwahc_pipe_cleanup: end"); 352 353 if ((WUSB_PERIODIC_ENDPOINT(eptd)) && 354 ((ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK) == 355 USB_EP_DIR_IN)) { 356 mutex_exit(&hwahcp->hwahc_mutex); 357 358 hwahc_do_client_periodic_in_req_callback( 359 hwahcp, pp, completion_reason); 360 361 mutex_enter(&hwahcp->hwahc_mutex); 362 } 363 } 364 365 /* 366 * set the pipe's parent device information 367 */ 368 static int 369 hwahc_set_pipe_dev_info(hwahc_state_t *hwahcp, 370 usba_pipe_handle_data_t *ph, hwahc_pipe_private_t *pp) 371 { 372 dev_info_t *dip = NULL; 373 wusb_hc_data_t *hc_data; 374 int i; 375 376 dip = usba_get_dip((usb_pipe_handle_t)ph->p_ph_impl); 377 if (dip == NULL) { 378 379 return (USB_FAILURE); 380 } 381 382 hc_data = &hwahcp->hwahc_hc_data; 383 384 mutex_enter(&hc_data->hc_mutex); 385 for (i = 1; i <= hc_data->hc_num_ports; i++) { 386 if ((dip == hc_data->hc_children_dips[i])) { 387 pp->pp_wdev = hc_data->hc_dev_infos[i]; 388 389 USB_DPRINTF_L3(DPRINT_MASK_HCDI, 390 hwahcp->hwahc_log_handle, 391 "hwahc_set_pipe_dev_info: pp(%p) device(%p) set", 392 (void *) pp, (void *) pp->pp_wdev); 393 394 break; 395 } 396 } 397 398 mutex_exit(&hc_data->hc_mutex); 399 400 if (pp->pp_wdev) { 401 return (USB_SUCCESS); 402 } else { 403 return (USB_FAILURE); 404 } 405 } 406 407 /* 408 * HWA HCDI entry points 409 * 410 * The Host Controller Driver Interfaces (HCDI) are the software interfaces 411 * between the Universal Serial Bus Layer (USBA) and the Host Controller 412 * Driver (HCD). The HCDI interfaces or entry points are subject to change. 413 */ 414 415 /* 416 * hwahc_hcdi_pipe_open: 417 * Member of HCD Ops structure and called during client specific pipe open. 418 * Assign rpipe for wireless transaction to work. 419 * The rpipe is assigned to an endpoint until the endpoint is closed. 420 */ 421 static int 422 hwahc_hcdi_pipe_open( 423 usba_pipe_handle_data_t *ph, 424 usb_flags_t flags) 425 { 426 int rval; 427 hwahc_state_t *hwahcp; 428 int kmflag; 429 hwahc_pipe_private_t *pp; 430 usb_ep_descr_t *epdt = &ph->p_ep; 431 uint8_t type; 432 wusb_wa_data_t *wa; 433 434 hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip); 435 wa = &hwahcp->hwahc_wa_data; 436 437 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 438 "hwahc_hcdi_pipe_open: hwahc=0x%p, ph=0x%p," 439 " addr = 0x%x, ep=0x%02X", (void *) hwahcp, (void *) ph, 440 ph->p_usba_device->usb_addr, epdt->bEndpointAddress); 441 442 kmflag = (flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP; 443 444 if (ph->p_hcd_private) { 445 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 446 "hwahc_hcdi_pipe_open: Pipe is already opened"); 447 448 return (USB_FAILURE); 449 } 450 451 pp = kmem_zalloc(sizeof (hwahc_pipe_private_t), kmflag); 452 if (pp == NULL) { 453 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 454 "hwahc_hcdi_pipe_open: alloc pp failed"); 455 456 return (USB_NO_RESOURCES); 457 } 458 459 mutex_enter(&hwahcp->hwahc_mutex); 460 461 if (hwahc_set_pipe_dev_info(hwahcp, ph, pp) < 0) { 462 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 463 "hwahc_hcdi_pipe_open: set pipe dev_info failed"); 464 mutex_exit(&hwahcp->hwahc_mutex); 465 466 return (USB_FAILURE); 467 } 468 469 rval = hwahc_state_is_operational(hwahcp); 470 if (rval != USB_SUCCESS) { 471 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 472 "hwahc_hcdi_pipe_open: state error: %d", rval); 473 kmem_free(pp, sizeof (hwahc_pipe_private_t)); 474 mutex_exit(&hwahcp->hwahc_mutex); 475 476 return (rval); 477 } 478 479 /* assign rpipe to the endpoint */ 480 type = epdt->bmAttributes & USB_EP_ATTR_MASK; 481 rval = wusb_wa_get_rpipe(&hwahcp->hwahc_wa_data, 482 hwahcp->hwahc_default_pipe, type, &pp->pp_rp, 483 PRINT_MASK_HCDI, hwahcp->hwahc_log_handle); 484 if (rval != USB_SUCCESS) { 485 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 486 "hwahc_hcdi_pipe_open: getting rpipe failed"); 487 kmem_free(pp, sizeof (hwahc_pipe_private_t)); 488 mutex_exit(&hwahcp->hwahc_mutex); 489 490 return (USB_NO_RESOURCES); 491 } 492 493 mutex_exit(&hwahcp->hwahc_mutex); 494 /* target the rpipe to the endpoint */ 495 rval = wusb_wa_set_rpipe_target(hwahcp->hwahc_dip, wa, 496 hwahcp->hwahc_default_pipe, ph, pp->pp_rp); 497 mutex_enter(&hwahcp->hwahc_mutex); 498 499 if (rval != USB_SUCCESS) { 500 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 501 "hwahc_hcdi_pipe_open: set target for rpipe failed"); 502 (void) wusb_wa_release_rpipe(wa, pp->pp_rp); 503 kmem_free(pp, sizeof (hwahc_pipe_private_t)); 504 mutex_exit(&hwahcp->hwahc_mutex); 505 506 return (USB_FAILURE); 507 } 508 509 pp->pp_pipe_handle = ph; 510 cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL); 511 512 mutex_enter(&ph->p_mutex); 513 ph->p_hcd_private = (usb_opaque_t)pp; 514 bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t)); 515 mutex_exit(&ph->p_mutex); 516 517 pp->pp_state = HWAHC_PIPE_STATE_IDLE; 518 hwahcp->hwahc_open_pipe_count++; 519 mutex_exit(&hwahcp->hwahc_mutex); 520 521 return (USB_SUCCESS); 522 } 523 524 525 /* 526 * hwahc_hcdi_pipe_close: 527 * Member of HCD Ops structure and called during the client specific pipe 528 * close. 529 * Remove unprocessed transfers from the pipe and free rpipe resource. 530 */ 531 /* ARGSUSED */ 532 static int 533 hwahc_hcdi_pipe_close( 534 usba_pipe_handle_data_t *ph, 535 usb_flags_t flags) 536 { 537 hwahc_state_t *hwahcp; 538 hwahc_pipe_private_t *pp; 539 usb_ep_descr_t *epdt = &ph->p_ep; 540 541 hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip); 542 543 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 544 "hwahc_hcdi_pipe_close:ph=0x%p addr = 0x%x, ep = 0x%x", 545 (void *) ph, ph->p_usba_device->usb_addr, 546 epdt->bEndpointAddress); 547 548 ASSERT(ph->p_hcd_private != NULL); 549 pp = (hwahc_pipe_private_t *)ph->p_hcd_private; 550 551 mutex_enter(&hwahcp->hwahc_mutex); 552 553 pp->pp_state = HWAHC_PIPE_STATE_CLOSE; 554 555 hwahc_pipe_cleanup(hwahcp, ph); 556 557 mutex_exit(&hwahcp->hwahc_mutex); 558 559 wusb_wa_clear_dev_ep(ph); /* clear the remote dev's endpoint */ 560 mutex_enter(&hwahcp->hwahc_mutex); 561 562 (void) wusb_wa_release_rpipe(&hwahcp->hwahc_wa_data, pp->pp_rp); 563 564 mutex_enter(&ph->p_mutex); 565 cv_destroy(&pp->pp_xfer_cmpl_cv); 566 kmem_free(pp, sizeof (hwahc_pipe_private_t)); 567 ph->p_hcd_private = NULL; 568 mutex_exit(&ph->p_mutex); 569 hwahcp->hwahc_open_pipe_count--; 570 mutex_exit(&hwahcp->hwahc_mutex); 571 572 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 573 "hwahc_hcdi_pipe_close: end"); 574 575 return (USB_SUCCESS); 576 } 577 578 579 /* 580 * hwahc_hcdi_pipe_reset: 581 * - clean up this pipe and change its state 582 */ 583 /* ARGSUSED */ 584 static int 585 hwahc_hcdi_pipe_reset( 586 usba_pipe_handle_data_t *ph, 587 usb_flags_t flags) 588 { 589 hwahc_state_t *hwahcp; 590 hwahc_pipe_private_t *pp; 591 592 hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip); 593 594 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 595 "hwahc_hcdi_pipe_reset: ph = 0x%p, ep=0x%02x", 596 (void *) ph, ph->p_ep.bEndpointAddress); 597 598 ASSERT(ph->p_hcd_private != NULL); 599 pp = (hwahc_pipe_private_t *)ph->p_hcd_private; 600 601 mutex_enter(&hwahcp->hwahc_mutex); 602 pp->pp_state = HWAHC_PIPE_STATE_RESET; 603 hwahc_pipe_cleanup(hwahcp, ph); 604 mutex_exit(&hwahcp->hwahc_mutex); 605 606 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 607 "hwahc_hcdi_pipe_reset: end"); 608 609 return (USB_SUCCESS); 610 } 611 612 613 /* 614 * hwahc_hcdi_pipe_ctrl_xfer: 615 * - usba_hcdi_pipe_ctrl_xfer entry 616 * - check pipe state 617 * - call wa_xfer to do this request 618 */ 619 static int 620 hwahc_hcdi_pipe_ctrl_xfer( 621 usba_pipe_handle_data_t *ph, 622 usb_ctrl_req_t *ctrl_reqp, 623 usb_flags_t usb_flags) 624 { 625 hwahc_state_t *hwahcp; 626 hwahc_pipe_private_t *pp; 627 int rval; 628 uint8_t ep_addr = ph->p_ep.bEndpointAddress; 629 630 hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip); 631 632 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 633 "hwahc_hcdi_pipe_ctrl_xfer: hwahcp=0x%p ph = 0x%p" 634 " reqp = 0x%p flags = %x", (void *) hwahcp, (void *) ph, 635 (void *) ctrl_reqp, usb_flags); 636 637 ASSERT(ph->p_hcd_private != NULL); 638 pp = (hwahc_pipe_private_t *)ph->p_hcd_private; 639 640 mutex_enter(&hwahcp->hwahc_mutex); 641 rval = hwahc_state_is_operational(hwahcp); 642 if (rval != USB_SUCCESS) { 643 mutex_exit(&hwahcp->hwahc_mutex); 644 645 return (rval); 646 } 647 648 /* 649 * if doing ctrl transfer on non-zero pipe and its state is error 650 * The default endpoint is critical for any other operations. 651 * We should not depend on upper layer to reset it. 652 */ 653 if ((pp->pp_state == HWAHC_PIPE_STATE_ERROR)) { 654 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 655 "hwahc_hcdi_pipe_ctrl_xfer: Pipe(%d) is in error" 656 " state, need pipe reset to continue", ep_addr); 657 658 if (ep_addr == 0) { 659 /* 660 * some error with the RPipe of EP 0, 661 * we need to reset this RPipe by ourself 662 */ 663 mutex_exit(&hwahcp->hwahc_mutex); 664 (void) wusb_wa_rpipe_reset(hwahcp->hwahc_dip, ph, 665 pp->pp_rp, 1); 666 mutex_enter(&hwahcp->hwahc_mutex); 667 pp->pp_state = 0; 668 } else { 669 /* client driver should clear non-default endpoint's state */ 670 mutex_exit(&hwahcp->hwahc_mutex); 671 672 return (USB_FAILURE); 673 } 674 } else if ((pp->pp_state != HWAHC_PIPE_STATE_IDLE) && 675 (pp->pp_state != HWAHC_PIPE_STATE_ERROR)) { 676 mutex_exit(&hwahcp->hwahc_mutex); 677 678 return (USB_PIPE_ERROR); 679 } 680 681 mutex_exit(&hwahcp->hwahc_mutex); 682 683 rval = wusb_wa_ctrl_xfer(&hwahcp->hwahc_wa_data, pp->pp_rp, ph, 684 ctrl_reqp, usb_flags); 685 if (rval != USB_SUCCESS) { 686 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 687 "hwahc_hcdi_pipe_ctrl_xfer failed, rval = %d", rval); 688 } 689 690 691 return (rval); 692 } 693 694 695 /* 696 * hwahc_hcdi_pipe_bulk_xfer: 697 * - usba_hcid_pipe_bulk_xfer entry 698 * - check the target pipe status first 699 * - process this request 700 */ 701 static int 702 hwahc_hcdi_pipe_bulk_xfer( 703 usba_pipe_handle_data_t *ph, 704 usb_bulk_req_t *bulk_reqp, 705 usb_flags_t usb_flags) 706 { 707 hwahc_state_t *hwahcp; 708 hwahc_pipe_private_t *pp; 709 int rval; 710 711 hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip); 712 713 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 714 "hwahc_hcdi_pipe_bulk_xfer: hwahcp=0x%p ph = 0x%p reqp = 0x%p" 715 " flags = %x", (void *) hwahcp, (void *) ph, 716 (void *) bulk_reqp, usb_flags); 717 718 ASSERT(ph->p_hcd_private != NULL); 719 720 pp = (hwahc_pipe_private_t *)ph->p_hcd_private; 721 722 mutex_enter(&hwahcp->hwahc_mutex); 723 rval = hwahc_state_is_operational(hwahcp); 724 if (rval != USB_SUCCESS) { 725 mutex_exit(&hwahcp->hwahc_mutex); 726 727 return (rval); 728 } 729 730 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 731 "hwahc_hcdi_pipe_bulk_xfer: pp = 0x%p state= %x", (void *) pp, 732 pp->pp_state); 733 734 if (pp->pp_state == HWAHC_PIPE_STATE_ERROR) { 735 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 736 "hwahc_hcdi_pipe_bulk_xfer: " 737 "Pipe is in error state, need pipe reset to continue"); 738 739 mutex_exit(&hwahcp->hwahc_mutex); 740 741 return (USB_FAILURE); 742 } 743 744 mutex_exit(&hwahcp->hwahc_mutex); 745 rval = wusb_wa_bulk_xfer(&hwahcp->hwahc_wa_data, pp->pp_rp, ph, 746 bulk_reqp, usb_flags); 747 mutex_enter(&hwahcp->hwahc_mutex); 748 if (rval != USB_SUCCESS) { 749 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 750 "hwahc_hcdi_pipe_bulk_xfer failed, rval = %d", rval); 751 } 752 mutex_exit(&hwahcp->hwahc_mutex); 753 754 return (rval); 755 } 756 757 /* 758 * hwahc_hcdi_pipe_intr_xfer: 759 * - usba_hcdi_pipe_intr_xfer entry 760 * - check pipe state 761 * - process this request 762 */ 763 static int 764 hwahc_hcdi_pipe_intr_xfer( 765 usba_pipe_handle_data_t *ph, 766 usb_intr_req_t *intr_reqp, 767 usb_flags_t usb_flags) 768 { 769 hwahc_state_t *hwahcp; 770 hwahc_pipe_private_t *pp; 771 int rval, pipe_dir; 772 773 hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip); 774 775 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 776 "hwahc_hcdi_pipe_intr_xfer: hwahcp=0x%p ph = 0x%p" 777 " reqp = 0x%p flags = %x", (void *) hwahcp, (void *) ph, 778 (void *) intr_reqp, usb_flags); 779 780 ASSERT(ph->p_hcd_private != NULL); 781 pp = (hwahc_pipe_private_t *)ph->p_hcd_private; 782 783 mutex_enter(&hwahcp->hwahc_mutex); 784 rval = hwahc_state_is_operational(hwahcp); 785 if (rval != USB_SUCCESS) { 786 mutex_exit(&hwahcp->hwahc_mutex); 787 788 return (rval); 789 } 790 791 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 792 "hwahc_hcdi_pipe_intr_xfer: pp = 0x%p state= %x", (void *) pp, 793 pp->pp_state); 794 795 if (pp->pp_state == HWAHC_PIPE_STATE_ERROR) { 796 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 797 "hwahc_hcdi_pipe_intr_xfer: " 798 "Pipe is in error state, need pipe reset to continue"); 799 800 mutex_exit(&hwahcp->hwahc_mutex); 801 802 return (USB_FAILURE); 803 } 804 805 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 806 807 808 mutex_exit(&hwahcp->hwahc_mutex); 809 rval = wusb_wa_intr_xfer(&hwahcp->hwahc_wa_data, pp->pp_rp, ph, 810 intr_reqp, usb_flags); 811 mutex_enter(&hwahcp->hwahc_mutex); 812 if (rval != USB_SUCCESS) { 813 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 814 "hwahc_hcdi_pipe_intr_xfer failed, rval = %d", rval); 815 } 816 817 if ((pipe_dir == USB_EP_DIR_IN) &&(rval == USB_SUCCESS)) { 818 /* 819 * the request has been submitted successfully, 820 * save the original one; free this request when polling 821 * stopped 822 */ 823 pp->pp_client_periodic_in_reqp = (usb_opaque_t)intr_reqp; 824 pp->pp_state = HWAHC_PIPE_STATE_ACTIVE; 825 } 826 827 mutex_exit(&hwahcp->hwahc_mutex); 828 829 return (rval); 830 } 831 832 /* 833 * hwahc_hcdi_pipe_isoc_xfer: 834 */ 835 /* ARGSUSED */ 836 static int 837 hwahc_hcdi_pipe_isoc_xfer( 838 usba_pipe_handle_data_t *ph, 839 usb_isoc_req_t *isoc_reqp, 840 usb_flags_t usb_flags) 841 { 842 return (USB_NOT_SUPPORTED); 843 } 844 845 846 /* 847 * hwahc_hcdi_bulk_transfer_size: 848 * 849 * Return maximum bulk transfer size 850 */ 851 /* ARGSUSED */ 852 static int 853 hwahc_hcdi_bulk_transfer_size( 854 usba_device_t *usba_device, 855 size_t *size) 856 { 857 hwahc_state_t *hwahcp; 858 int rval; 859 860 hwahcp = hwahc_obtain_state(usba_device->usb_root_hub_dip); 861 862 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 863 "hwahc_hcdi_bulk_transfer_size:"); 864 865 mutex_enter(&hwahcp->hwahc_mutex); 866 rval = hwahc_state_is_operational(hwahcp); 867 mutex_exit(&hwahcp->hwahc_mutex); 868 869 if (rval != USB_SUCCESS) { 870 871 return (rval); 872 } 873 874 *size = WA_MAX_SEG_COUNT * 1024; 875 876 return (USB_SUCCESS); 877 } 878 879 /* 880 * hwahc_hcdi_pipe_stop_intr_polling() 881 */ 882 /* ARGSUSED */ 883 static int 884 hwahc_hcdi_pipe_stop_intr_polling( 885 usba_pipe_handle_data_t *ph, 886 usb_flags_t flags) 887 { 888 hwahc_state_t *hwahcp; 889 hwahc_pipe_private_t *pp; 890 891 hwahcp = hwahc_obtain_state(ph->p_usba_device->usb_root_hub_dip); 892 893 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 894 "hwahc_hcdi_pipe_stop_intr_polling: hwahcp=0x%p ph = 0x%p" 895 " flags = %x", (void *) hwahcp, (void *) ph, flags); 896 897 ASSERT(ph->p_hcd_private != NULL); 898 899 mutex_enter(&hwahcp->hwahc_mutex); 900 pp = (hwahc_pipe_private_t *)ph->p_hcd_private; 901 902 if (pp->pp_state != HWAHC_PIPE_STATE_ACTIVE) { 903 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 904 "hwahc_hcdi_pipe_stop_intr_polling: " 905 "Polling already stopped"); 906 mutex_exit(&hwahcp->hwahc_mutex); 907 908 return (USB_SUCCESS); 909 } 910 911 pp->pp_state = HWAHC_PIPE_STATE_STOP_POLLING; 912 913 hwahc_pipe_cleanup(hwahcp, ph); 914 915 mutex_exit(&hwahcp->hwahc_mutex); 916 917 return (USB_SUCCESS); 918 } 919 920 921 /* 922 * hwahc_hcdi_pipe_stop_isoc_polling() 923 */ 924 /*ARGSUSED*/ 925 static int 926 hwahc_hcdi_pipe_stop_isoc_polling( 927 usba_pipe_handle_data_t *ph, 928 usb_flags_t flags) 929 { 930 return (USB_NOT_SUPPORTED); 931 } 932 933 934 /* 935 * hwahc_hcdi_get_current_frame_number: 936 * 937 * Get the current usb frame number. 938 * Return whether the request is handled successfully 939 */ 940 /* ARGSUSED */ 941 static int 942 hwahc_hcdi_get_current_frame_number( 943 usba_device_t *usba_device, 944 usb_frame_number_t *frame_number) 945 { 946 return (USB_NOT_SUPPORTED); 947 } 948 949 950 /* 951 * hwahc_hcdi_get_max_isoc_pkts: 952 * 953 * Get maximum isochronous packets per usb isochronous request. 954 * Return whether the request is handled successfully 955 */ 956 /* ARGSUSED */ 957 static int 958 hwahc_hcdi_get_max_isoc_pkts( 959 usba_device_t *usba_device, 960 uint_t *max_pkts) 961 { 962 return (USB_NOT_SUPPORTED); 963 } 964 965 966 /* 967 * POLLED entry points 968 * 969 * These functions are entry points into the POLLED code. 970 */ 971 /* 972 * hwahc_hcdi_polled_input_init: 973 * 974 * This is the initialization routine for handling the USB keyboard 975 * in POLLED mode. This routine is not called from POLLED mode, so 976 * it is OK to acquire mutexes. 977 */ 978 /* ARGSUSED */ 979 static int 980 hwahc_hcdi_polled_input_init( 981 usba_pipe_handle_data_t *ph, 982 uchar_t **polled_buf, 983 usb_console_info_impl_t *console_input_info) 984 { 985 return (USB_FAILURE); 986 } 987 988 989 /* 990 * hwahc_hcdi_polled_input_fini: 991 */ 992 /* ARGSUSED */ 993 static int 994 hwahc_hcdi_polled_input_fini(usb_console_info_impl_t *info) 995 { 996 return (USB_FAILURE); 997 } 998 999 1000 /* 1001 * hwahc_hcdi_polled_input_enter: 1002 * 1003 * This is where we enter into POLLED mode. This routine sets up 1004 * everything so that calls to hwahc_hcdi_polled_read will return 1005 * characters. 1006 */ 1007 /* ARGSUSED */ 1008 static int 1009 hwahc_hcdi_polled_input_enter(usb_console_info_impl_t *info) 1010 { 1011 return (USB_FAILURE); 1012 } 1013 1014 1015 /* 1016 * hwahc_hcdi_polled_input_exit: 1017 * 1018 * This is where we exit POLLED mode. This routine restores 1019 * everything that is needed to continue operation. 1020 */ 1021 /* ARGSUSED */ 1022 static int 1023 hwahc_hcdi_polled_input_exit(usb_console_info_impl_t *info) 1024 { 1025 return (USB_FAILURE); 1026 } 1027 1028 1029 /* 1030 * hwahc_hcdi_polled_read: 1031 * 1032 * Get a key character 1033 */ 1034 /* ARGSUSED */ 1035 static int 1036 hwahc_hcdi_polled_read( 1037 usb_console_info_impl_t *info, 1038 uint_t *num_characters) 1039 { 1040 return (USB_FAILURE); 1041 } 1042 1043 1044 /* 1045 * hwahc_alloc_hcdi_ops: 1046 * 1047 * The HCDI interfaces or entry points are the software interfaces used by 1048 * the Universal Serial Bus Driver (USBA) to access the services of the 1049 * Host Controller Driver (HCD). During HCD initialization, inform USBA 1050 * about all available HCDI interfaces or entry points. 1051 */ 1052 usba_hcdi_ops_t * 1053 hwahc_alloc_hcdi_ops(hwahc_state_t *hwahcp) 1054 { 1055 usba_hcdi_ops_t *usba_hcdi_ops; 1056 1057 USB_DPRINTF_L2(PRINT_MASK_ATTA, hwahcp->hwahc_log_handle, 1058 "hwahc_alloc_hcdi_ops:"); 1059 1060 usba_hcdi_ops = usba_alloc_hcdi_ops(); 1061 1062 usba_hcdi_ops->usba_hcdi_ops_version = HCDI_OPS_VERSION; 1063 1064 usba_hcdi_ops->usba_hcdi_pm_support = hwahc_hcdi_pm_support; 1065 usba_hcdi_ops->usba_hcdi_pipe_open = hwahc_hcdi_pipe_open; 1066 usba_hcdi_ops->usba_hcdi_pipe_close = hwahc_hcdi_pipe_close; 1067 1068 usba_hcdi_ops->usba_hcdi_pipe_reset = hwahc_hcdi_pipe_reset; 1069 usba_hcdi_ops->usba_hcdi_pipe_reset_data_toggle = 1070 hwahc_hcdi_pipe_reset_data_toggle; 1071 1072 usba_hcdi_ops->usba_hcdi_pipe_ctrl_xfer = hwahc_hcdi_pipe_ctrl_xfer; 1073 usba_hcdi_ops->usba_hcdi_pipe_bulk_xfer = hwahc_hcdi_pipe_bulk_xfer; 1074 usba_hcdi_ops->usba_hcdi_pipe_intr_xfer = hwahc_hcdi_pipe_intr_xfer; 1075 usba_hcdi_ops->usba_hcdi_pipe_isoc_xfer = hwahc_hcdi_pipe_isoc_xfer; 1076 1077 usba_hcdi_ops->usba_hcdi_bulk_transfer_size = 1078 hwahc_hcdi_bulk_transfer_size; 1079 1080 usba_hcdi_ops->usba_hcdi_pipe_stop_intr_polling = 1081 hwahc_hcdi_pipe_stop_intr_polling; 1082 usba_hcdi_ops->usba_hcdi_pipe_stop_isoc_polling = 1083 hwahc_hcdi_pipe_stop_isoc_polling; 1084 1085 usba_hcdi_ops->usba_hcdi_get_current_frame_number = 1086 hwahc_hcdi_get_current_frame_number; 1087 usba_hcdi_ops->usba_hcdi_get_max_isoc_pkts = 1088 hwahc_hcdi_get_max_isoc_pkts; 1089 1090 usba_hcdi_ops->usba_hcdi_console_input_init = 1091 hwahc_hcdi_polled_input_init; 1092 usba_hcdi_ops->usba_hcdi_console_input_enter = 1093 hwahc_hcdi_polled_input_enter; 1094 usba_hcdi_ops->usba_hcdi_console_read = 1095 hwahc_hcdi_polled_read; 1096 usba_hcdi_ops->usba_hcdi_console_input_exit = 1097 hwahc_hcdi_polled_input_exit; 1098 usba_hcdi_ops->usba_hcdi_console_input_fini = 1099 hwahc_hcdi_polled_input_fini; 1100 1101 return (usba_hcdi_ops); 1102 } 1103 1104 1105 /* 1106 * Set cluster ID. 1107 * see 8.5.3.11 1108 */ 1109 int 1110 hwahc_set_cluster_id(dev_info_t *dip, uint8_t cluster_id) 1111 { 1112 usb_cr_t completion_reason; 1113 usb_cb_flags_t cb_flags; 1114 int rval; 1115 hwahc_state_t *hwahcp; 1116 1117 if (dip == NULL) { 1118 1119 return (USB_INVALID_ARGS); 1120 } 1121 1122 hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip)); 1123 if (hwahcp == NULL) { 1124 1125 return (USB_INVALID_ARGS); 1126 } 1127 1128 rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe, 1129 WUSB_CLASS_IF_REQ_OUT_TYPE, 1130 HWA_REQ_SET_CLUSTER_ID, 1131 cluster_id, 1132 hwahcp->hwahc_wa_data.wa_ifno, 1133 0, 1134 NULL, 0, 1135 &completion_reason, &cb_flags, 0); 1136 1137 if (rval != USB_SUCCESS) { 1138 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1139 "Set_Cluster_ID fails: rval=%d cr=%d cb=0x%x", 1140 rval, completion_reason, cb_flags); 1141 } 1142 1143 return (rval); 1144 } 1145 1146 /* 1147 * Set WUSB Stream Index. see 8.5.3.13 1148 */ 1149 int 1150 hwahc_set_stream_idx(dev_info_t *dip, uint8_t stream_idx) 1151 { 1152 usb_cr_t completion_reason; 1153 usb_cb_flags_t cb_flags; 1154 int rval; 1155 hwahc_state_t *hwahcp; 1156 1157 if ((dip == NULL)) { 1158 1159 return (USB_INVALID_ARGS); 1160 } 1161 1162 hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip)); 1163 if (hwahcp == NULL) { 1164 1165 return (USB_INVALID_ARGS); 1166 } 1167 1168 rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe, 1169 WUSB_CLASS_IF_REQ_OUT_TYPE, 1170 HWA_REQ_SET_STREAM_IDX, 1171 stream_idx, 1172 hwahcp->hwahc_wa_data.wa_ifno, 1173 0, NULL, 0, &completion_reason, 1174 &cb_flags, 0); 1175 1176 if (rval != USB_SUCCESS) { 1177 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1178 "Set_Stream_Idx fails: rval=%d cr=%d cb=0x%x", 1179 rval, completion_reason, cb_flags); 1180 } 1181 1182 return (rval); 1183 } 1184 1185 /* 1186 * 8.5.3.12 - Set WUSB MAS 1187 * Caller must ensure the data is WUSB_SET_WUSB_MAS_LEN long. 1188 */ 1189 int 1190 hwahc_set_wusb_mas(dev_info_t *dip, uint8_t *data) 1191 { 1192 usb_cr_t completion_reason; 1193 usb_cb_flags_t cb_flags; 1194 mblk_t *blk; 1195 int rval, i; 1196 hwahc_state_t *hwahcp; 1197 1198 if ((dip == NULL)) { 1199 1200 return (USB_INVALID_ARGS); 1201 } 1202 1203 hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip)); 1204 if (hwahcp == NULL) { 1205 1206 return (USB_INVALID_ARGS); 1207 } 1208 1209 blk = allocb_wait(WUSB_SET_WUSB_MAS_LEN, BPRI_LO, STR_NOSIG, NULL); 1210 1211 for (i = 0; i < WUSB_SET_WUSB_MAS_LEN; i++) { 1212 *blk->b_wptr++ = data[i]; 1213 } 1214 1215 rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe, 1216 WUSB_CLASS_IF_REQ_OUT_TYPE, 1217 HWA_REQ_SET_WUSB_MAS, 1218 0, 1219 hwahcp->hwahc_wa_data.wa_ifno, 1220 WUSB_SET_WUSB_MAS_LEN, 1221 &blk, 0, 1222 &completion_reason, &cb_flags, 0); 1223 1224 if (rval != USB_SUCCESS) { 1225 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1226 "Set_WUSB_MAS fails: rval=%d cr=%d cb=0x%x", 1227 rval, completion_reason, cb_flags); 1228 } 1229 freemsg(blk); 1230 1231 return (rval); 1232 } 1233 1234 /* 8.5.3.1 - Add MMC IE */ 1235 int 1236 hwahc_add_mmc_ie(dev_info_t *dip, uint8_t interval, uint8_t rcnt, 1237 uint8_t iehdl, uint16_t len, uint8_t *data) 1238 { 1239 usb_cr_t completion_reason; 1240 usb_cb_flags_t cb_flags; 1241 mblk_t *blk; 1242 int i, rval; 1243 hwahc_state_t *hwahcp; 1244 1245 if (dip == NULL) { 1246 1247 return (USB_INVALID_ARGS); 1248 } 1249 1250 hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip)); 1251 if (hwahcp == NULL) { 1252 1253 return (USB_INVALID_ARGS); 1254 } 1255 1256 blk = allocb_wait(len, BPRI_LO, STR_NOSIG, NULL); 1257 1258 for (i = 0; i < len; i++) { 1259 *blk->b_wptr++ = data[i]; 1260 } 1261 1262 rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe, 1263 WUSB_CLASS_IF_REQ_OUT_TYPE, 1264 HWA_REQ_ADD_MMC_IE, 1265 (interval << 8) | rcnt, 1266 (iehdl << 8) | hwahcp->hwahc_wa_data.wa_ifno, 1267 len, 1268 &blk, 0, 1269 &completion_reason, &cb_flags, 0); 1270 1271 if (rval != USB_SUCCESS) { 1272 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1273 "Add_MMC_IE fails: rval=%d cr=%d cb=0x%x", 1274 rval, completion_reason, cb_flags); 1275 } 1276 1277 freemsg(blk); 1278 1279 return (rval); 1280 } 1281 1282 /* 8.5.3.5 - Remove MMC IE */ 1283 int 1284 hwahc_remove_mmc_ie(dev_info_t *dip, uint8_t iehdl) 1285 { 1286 usb_cr_t completion_reason; 1287 usb_cb_flags_t cb_flags; 1288 int rval; 1289 hwahc_state_t *hwahcp; 1290 1291 if (dip == NULL) { 1292 1293 return (USB_INVALID_ARGS); 1294 } 1295 1296 hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip)); 1297 if (hwahcp == NULL) { 1298 return (USB_INVALID_ARGS); 1299 } 1300 1301 rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe, 1302 WUSB_CLASS_IF_REQ_OUT_TYPE, 1303 HWA_REQ_REMOVE_MMC_IE, 1304 0, 1305 (iehdl << 8) | hwahcp->hwahc_wa_data.wa_ifno, 1306 0, 1307 NULL, 0, 1308 &completion_reason, &cb_flags, 0); 1309 1310 if (rval != USB_SUCCESS) { 1311 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1312 "Remove_MMC_IE fails: rval=%d cr=%d cb=0x%x", 1313 rval, completion_reason, cb_flags); 1314 } 1315 1316 return (rval); 1317 } 1318 1319 /* 8.5.3.14 - WUSB Channel Stop */ 1320 int 1321 hwahc_stop_ch(dev_info_t *dip, uint32_t timeoff) 1322 { 1323 int rval; 1324 usb_cr_t completion_reason; 1325 usb_cb_flags_t cb_flags; 1326 hwahc_state_t *hwahcp; 1327 1328 if (dip == NULL) { 1329 1330 return (USB_INVALID_ARGS); 1331 } 1332 1333 hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip)); 1334 if (hwahcp == NULL) { 1335 1336 return (USB_INVALID_ARGS); 1337 } 1338 1339 rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe, 1340 WUSB_CLASS_IF_REQ_OUT_TYPE, 1341 HWA_REQ_CH_STOP, 1342 timeoff & 0x00ffffff, 1343 hwahcp->hwahc_wa_data.wa_ifno, 1344 0, 1345 NULL, 0, 1346 &completion_reason, &cb_flags, 0); 1347 1348 if (rval != USB_SUCCESS) { 1349 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1350 "WUSB_Ch_Stop fails: rval=%d cr=%d cb=0x%x", 1351 rval, completion_reason, cb_flags); 1352 } 1353 1354 return (rval); 1355 } 1356 1357 /* 8.5. 3.10 - Set Num DNTS Slots */ 1358 int 1359 hwahc_set_num_dnts(dev_info_t *dip, uint8_t interval, uint8_t nslots) 1360 { 1361 usb_cr_t completion_reason; 1362 usb_cb_flags_t cb_flags; 1363 int rval; 1364 hwahc_state_t *hwahcp; 1365 1366 if (dip == NULL) { 1367 1368 return (USB_INVALID_ARGS); 1369 } 1370 1371 hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip)); 1372 if (hwahcp == NULL) { 1373 1374 return (USB_INVALID_ARGS); 1375 } 1376 1377 rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe, 1378 WUSB_CLASS_IF_REQ_OUT_TYPE, 1379 HWA_REQ_SET_NUM_DNTS, 1380 (interval << 8) | nslots, 1381 hwahcp->hwahc_wa_data.wa_ifno, 1382 0, 1383 NULL, 0, 1384 &completion_reason, &cb_flags, 0); 1385 1386 if (rval != USB_SUCCESS) { 1387 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1388 "Set_Num_DNTS fails: rval=%d cr=%d cb=0x%x", 1389 rval, completion_reason, cb_flags); 1390 } 1391 1392 return (rval); 1393 } 1394 1395 /* set encryptiion type for host */ 1396 int 1397 hwahc_set_encrypt(dev_info_t *dip, usb_port_t port, uint8_t type) 1398 { 1399 hwahc_state_t *hwahcp; 1400 int rval; 1401 1402 if ((hwahcp = ddi_get_soft_state(hwahc_statep, 1403 ddi_get_instance(dip))) == NULL) { 1404 1405 return (USB_INVALID_ARGS); 1406 } 1407 /* DEVICE INDEX */ 1408 rval = hwahc_set_dev_encrypt(hwahcp->hwahc_default_pipe, 1409 hwahcp->hwahc_wa_data.wa_ifno, port - 1, 1410 &hwahcp->hwahc_secrt_data, type); 1411 if (rval != USB_SUCCESS) { 1412 USB_DPRINTF_L2(PRINT_MASK_CBOPS, hwahcp->hwahc_log_handle, 1413 "hwahc_set_encrypt: set device encryption for port %d " 1414 "failed", port); 1415 } 1416 1417 return (rval); 1418 } 1419 1420 1421 /* 1422 * Set Device Key for WUSB host, refer to WUSB 1.0/8.5.3.8 1423 * 1424 * Set group/device key: 1425 * devindex = actual port number - 1, so it is zero based 1426 * 1427 */ 1428 int hwahc_set_keys(hwahc_state_t *hwahcp, usb_key_descr_t *key_descr, 1429 size_t klen, uint8_t devindex, uint8_t keydex, uint8_t flag) 1430 { 1431 usb_ctrl_setup_t setup; 1432 usb_cr_t cr; 1433 usb_cb_flags_t cb_flags; 1434 mblk_t *pdata; 1435 int rval; 1436 uint8_t keyindex; 1437 1438 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1439 "hwahc_set_keys: klen = %d, devindex = %d", (int)klen, 1440 devindex); 1441 1442 /* Table 7-21 and Errata 2005/07 */ 1443 if (flag == WUSB_GTK) { 1444 if (devindex != 0) { 1445 return (USB_FAILURE); 1446 } 1447 1448 /* See 7.3.2.4 for key index format */ 1449 keyindex = (1 << 5) | keydex; 1450 } else if (flag == WUSB_PTK) { 1451 1452 keyindex = keydex; 1453 } else { 1454 1455 return (USB_FAILURE); 1456 } 1457 1458 setup.bmRequestType = USB_DEV_REQ_HOST_TO_DEV | 1459 USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_IF; 1460 setup.bRequest = USB_REQ_SET_DESCR; 1461 setup.wValue = (USB_DESCR_TYPE_KEY << 8) | keyindex; 1462 setup.wIndex = devindex << 8 | hwahcp->hwahc_wa_data.wa_ifno; 1463 setup.wLength = (uint16_t)klen; 1464 setup.attrs = USB_ATTRS_NONE; 1465 1466 if ((pdata = allocb(klen, BPRI_HI)) == NULL) { 1467 1468 return (USB_FAILURE); 1469 } 1470 bcopy(key_descr, pdata->b_wptr, klen); 1471 pdata->b_wptr += klen; 1472 1473 rval = usb_pipe_ctrl_xfer_wait(hwahcp->hwahc_default_pipe, &setup, 1474 &pdata, &cr, &cb_flags, USB_FLAGS_SLEEP); 1475 1476 if (rval != USB_SUCCESS) { 1477 USB_DPRINTF_L4(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1478 "hwahc_set_keys:fail, rv=%d,cr=%d,cb=%d", rval, cr, 1479 cb_flags); 1480 } 1481 1482 freemsg(pdata); 1483 1484 return (rval); 1485 } 1486 1487 /* set PTK for host */ 1488 int 1489 hwahc_set_ptk(dev_info_t *dip, usb_key_descr_t *key_descr, size_t klen, 1490 usb_port_t port) 1491 { 1492 hwahc_state_t *hwahcp; 1493 int rval; 1494 uint8_t keyindex = 1; 1495 1496 if ((hwahcp = ddi_get_soft_state(hwahc_statep, 1497 ddi_get_instance(dip))) == NULL) { 1498 1499 return (USB_INVALID_ARGS); 1500 } 1501 /* DEVICE INDEX */ 1502 rval = hwahc_set_keys(hwahcp, key_descr, klen, port - 1, keyindex, 1503 WUSB_PTK); 1504 if (rval != USB_SUCCESS) { 1505 USB_DPRINTF_L2(PRINT_MASK_CBOPS, hwahcp->hwahc_log_handle, 1506 "hwahc_set_ptk: set device key descr for port %d " 1507 "failed", port); 1508 } 1509 1510 return (rval); 1511 } 1512 1513 /* set GTK for host */ 1514 int 1515 hwahc_set_gtk(dev_info_t *dip, usb_key_descr_t *key_descr, size_t klen) 1516 { 1517 hwahc_state_t *hwahcp; 1518 int rval; 1519 1520 if ((hwahcp = ddi_get_soft_state(hwahc_statep, 1521 ddi_get_instance(dip))) == NULL) { 1522 1523 return (USB_INVALID_ARGS); 1524 } 1525 1526 rval = hwahc_set_keys(hwahcp, key_descr, klen, 0, 0, WUSB_GTK); 1527 if (rval != USB_SUCCESS) { 1528 USB_DPRINTF_L2(PRINT_MASK_CBOPS, hwahcp->hwahc_log_handle, 1529 "hwahc_set_gtk: set group key descr failed"); 1530 } 1531 1532 return (rval); 1533 } 1534 1535 /* 1536 * set device info for host 1537 * Section 8.5.3.7. 1538 */ 1539 int 1540 hwahc_set_device_info(dev_info_t *dip, wusb_dev_info_t *dev_info, 1541 usb_port_t port) 1542 { 1543 hwahc_state_t *hwahcp; 1544 int rval; 1545 hwa_dev_info_t info; 1546 usb_ctrl_setup_t setup; 1547 usb_cr_t cr; 1548 usb_cb_flags_t cb_flags; 1549 mblk_t *pdata; 1550 1551 if ((hwahcp = ddi_get_soft_state(hwahc_statep, 1552 ddi_get_instance(dip))) == NULL) { 1553 1554 return (USB_INVALID_ARGS); 1555 } 1556 1557 /* the device can use all the host's reserved MASes to communicate */ 1558 (void) memcpy(info.bmDeviceAvailablilityInfo, 1559 hwahcp->hwahc_hc_data.hc_mas, WUSB_SET_WUSB_MAS_LEN); 1560 1561 info.bDeviceAddress = dev_info->wdev_addr; 1562 1563 /* To tell HWA device what data rates this child device supports */ 1564 if (dev_info->wdev_uwb_descr == NULL) { 1565 /* bitmap, see7.4.1.1. Must support 53.3/106.7/200 Mbps */ 1566 info.wPHYRates[0] = WUSB_DATA_RATE_BIT_53 | 1567 WUSB_DATA_RATE_BIT_106 | WUSB_DATA_RATE_BIT_200; 1568 info.wPHYRates[1] = 0; 1569 } else { 1570 info.wPHYRates[0] = 1571 dev_info->wdev_uwb_descr->wPHYRates && 0xff; 1572 info.wPHYRates[1] = 1573 (dev_info->wdev_uwb_descr->wPHYRates >> 8) && 0xff; 1574 } 1575 info.bmDeviceAttribute = 0; 1576 1577 setup.bmRequestType = USB_DEV_REQ_HOST_TO_DEV | 1578 USB_DEV_REQ_TYPE_CLASS | USB_DEV_REQ_RCPT_IF; 1579 setup.bRequest = HWA_REQ_SET_DEVICE_INFO; 1580 setup.wValue = 0; 1581 1582 /* DEVICE INDEX */ 1583 setup.wIndex = (port - 1) << 8 | hwahcp->hwahc_wa_data.wa_ifno; 1584 setup.wLength = WUSB_SET_DEV_INFO_LEN; 1585 setup.attrs = USB_ATTRS_NONE; 1586 1587 if ((pdata = allocb(WUSB_SET_DEV_INFO_LEN, BPRI_HI)) == NULL) { 1588 1589 return (USB_FAILURE); 1590 } 1591 bcopy(&info, pdata->b_wptr, WUSB_SET_DEV_INFO_LEN); 1592 pdata->b_wptr += WUSB_SET_DEV_INFO_LEN; 1593 1594 rval = usb_pipe_ctrl_xfer_wait(hwahcp->hwahc_default_pipe, &setup, 1595 &pdata, &cr, &cb_flags, USB_FLAGS_SLEEP); 1596 1597 freemsg(pdata); 1598 1599 return (rval); 1600 } 1601 1602 /* 1603 * 8.5.3.2 - 8.5.3.4 Get Time 1604 * time_type: 1605 * WUSB_TIME_ADJ - Get BPST Adjustment 1606 * WUSB_TIME_BPST - Get BPST Time 1607 * WUSB_TIME_WUSB - Get WUSB Time 1608 */ 1609 int 1610 hwahc_get_time(dev_info_t *dip, uint8_t time_type, 1611 uint16_t len, uint32_t *time) 1612 { 1613 usb_cr_t completion_reason; 1614 usb_cb_flags_t cb_flags; 1615 mblk_t *blk = NULL; 1616 int rval; 1617 uint8_t *data; 1618 uint16_t length; 1619 hwahc_state_t *hwahcp = NULL; 1620 1621 if (dip == NULL) { 1622 1623 return (USB_INVALID_ARGS); 1624 } 1625 1626 hwahcp = ddi_get_soft_state(hwahc_statep, ddi_get_instance(dip)); 1627 if (hwahcp == NULL) { 1628 1629 return (USB_INVALID_ARGS); 1630 } 1631 1632 /* according to WUSB 8.5.3, len is 1 or 3 */ 1633 if ((len != 1) && (len != 3)) { 1634 1635 return (USB_INVALID_ARGS); 1636 } 1637 1638 rval = usb_pipe_sync_ctrl_xfer(dip, hwahcp->hwahc_default_pipe, 1639 WUSB_CLASS_IF_REQ_OUT_TYPE, HWA_REQ_GET_TIME, 1640 time_type, hwahcp->hwahc_wa_data.wa_ifno, 1641 len, &blk, 0, &completion_reason, &cb_flags, 0); 1642 1643 if (rval != USB_SUCCESS) { 1644 freemsg(blk); 1645 1646 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1647 "Get_Time fails: rval=%d cr=%d cb=0x%x", 1648 rval, completion_reason, cb_flags); 1649 1650 return (rval); 1651 } else if (blk == NULL) { 1652 USB_DPRINTF_L2(PRINT_MASK_HCDI, hwahcp->hwahc_log_handle, 1653 "Get_Time returns null data"); 1654 1655 return (USB_FAILURE); 1656 } else { 1657 length = MBLKL(blk); 1658 1659 if (length < len) { 1660 freemsg(blk); 1661 1662 USB_DPRINTF_L2(PRINT_MASK_HCDI, 1663 hwahcp->hwahc_log_handle, 1664 "Get_Time returns short length %d", length); 1665 1666 return (USB_FAILURE); 1667 } 1668 1669 data = blk->b_rptr; 1670 if (len == 1) { 1671 *time = *data; 1672 } else { 1673 *time = (data[2] << 16) | (data[1] << 8) | data[0]; 1674 } 1675 freemsg(blk); 1676 1677 return (USB_SUCCESS); 1678 } 1679 }