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