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 /* 28 * UWB HWA Radio Controller driver. 29 * 30 * 31 * The device has four states (refer to usbai.h): 32 * USB_DEV_ONLINE: In action or ready for action. 33 * USB_DEV_DISCONNECTED: Hotplug removed, or device not present/correct on 34 * resume (CPR). 35 * USB_DEV_SUSPENDED: Device has been suspended along with the system. 36 * USB_DEV_PWRED_DOWN: Device has been powered down. (Note that this 37 * driver supports only two power states, powered down and 38 * full power.) 39 * 40 * In order to avoid race conditions between driver entry points, 41 * access to the device is serialized. Race conditions are an issue in 42 * particular between disconnect event callbacks, detach, power, open 43 * and data transfer callbacks. The functions hwarc_serialize/release_access 44 * are implemented for this purpose. 45 * 46 * Mutexes should never be held when making calls into USBA or when 47 * sleeping. 48 * 49 * pm_busy_component and pm_idle_component mark the device as busy or idle to 50 * the system. These functions are paired, and are called only from code 51 * bracketed by hwarc_serialize_access and hwarc_release_access. 52 * 53 */ 54 55 #define USBDRV_MAJOR_VER 2 56 #define USBDRV_MINOR_VER 0 57 58 #include <sys/strsun.h> 59 #include <sys/usb/usba.h> 60 #include <sys/usb/clients/hwarc/hwarc.h> 61 62 63 64 uint_t hwarc_errlevel = 4; 65 static uint_t hwarc_errmask = (uint_t)PRINT_MASK_ALL; 66 static uint_t hwarc_instance_debug = (uint_t)-1; 67 68 static char *name = "hwarc"; /* Driver name, used all over */ 69 70 71 /* Function Prototypes */ 72 static int hwarc_attach(dev_info_t *, ddi_attach_cmd_t); 73 static int hwarc_detach(dev_info_t *, ddi_detach_cmd_t); 74 static int hwarc_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 75 static int hwarc_cleanup(dev_info_t *, hwarc_state_t *); 76 static int hwarc_open(dev_t *, int, int, cred_t *); 77 static int hwarc_close(dev_t, int, int, cred_t *); 78 static int hwarc_send_cmd(uwb_dev_handle_t, mblk_t *, uint16_t); 79 static int hwarc_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 80 static int hwarc_disconnect_callback(dev_info_t *); 81 static int hwarc_reconnect_callback(dev_info_t *); 82 static void hwarc_restore_device_state(dev_info_t *, hwarc_state_t *); 83 static int hwarc_cpr_suspend(dev_info_t *); 84 static void hwarc_cpr_resume(dev_info_t *); 85 static int hwarc_open_intr_pipe(hwarc_state_t *); 86 static void hwarc_close_intr_pipe(hwarc_state_t *); 87 static void hwarc_pm_busy_component(hwarc_state_t *); 88 static void hwarc_pm_idle_component(hwarc_state_t *); 89 static int hwarc_power(dev_info_t *, int, int); 90 static int hwarc_serialize_access(hwarc_state_t *, boolean_t); 91 static void hwarc_release_access(hwarc_state_t *); 92 static int hwarc_reset_device(hwarc_state_t *); 93 static int hwarc_init_phy(hwarc_state_t *); 94 95 96 static int hwarc_start_polling(hwarc_state_t *, usb_pipe_handle_t); 97 98 99 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_ctrl_req)) 100 _NOTE(SCHEME_PROTECTS_DATA("unique per call", usb_intr_req)) 101 _NOTE(SCHEME_PROTECTS_DATA("unique per call", buf)) 102 103 /* module loading stuff */ 104 struct cb_ops hwarc_cb_ops = { 105 hwarc_open, /* open */ 106 hwarc_close, /* close */ 107 nodev, /* strategy */ 108 nulldev, /* print */ 109 nulldev, /* dump */ 110 nodev, /* read */ 111 nodev, /* write */ 112 hwarc_ioctl, /* ioctl */ 113 nulldev, /* devmap */ 114 nodev, /* mmap */ 115 nodev, /* segmap */ 116 nochpoll, /* poll */ 117 ddi_prop_op, /* cb_prop_op */ 118 NULL, /* streamtab */ 119 D_MP 120 }; 121 122 static struct dev_ops hwarc_ops = { 123 DEVO_REV, /* devo_rev, */ 124 0, /* refcnt */ 125 hwarc_info, /* info */ 126 nulldev, /* identify */ 127 nulldev, /* probe */ 128 hwarc_attach, /* attach */ 129 hwarc_detach, /* detach */ 130 nodev, /* reset */ 131 &hwarc_cb_ops, /* driver operations */ 132 NULL, /* bus operations */ 133 hwarc_power, /* power */ 134 ddi_quiesce_not_needed, /* devo_quiesce */ 135 }; 136 137 static struct modldrv hwarc_modldrv = { 138 &mod_driverops, 139 "USB HWA Radio Controller driver", 140 &hwarc_ops 141 }; 142 143 static struct modlinkage modlinkage = { 144 MODREV_1, 145 &hwarc_modldrv, 146 NULL 147 }; 148 149 /* Soft state structures */ 150 #define HWARC_INITIAL_SOFT_SPACE 1 151 static void *hwarc_statep; 152 153 154 /* Module-wide initialization routine */ 155 int 156 _init(void) 157 { 158 int rval; 159 160 if ((rval = ddi_soft_state_init(&hwarc_statep, 161 sizeof (hwarc_state_t), HWARC_INITIAL_SOFT_SPACE)) != 0) { 162 163 return (rval); 164 } 165 166 if ((rval = mod_install(&modlinkage)) != 0) { 167 ddi_soft_state_fini(&hwarc_statep); 168 } 169 170 return (rval); 171 } 172 173 174 /* Module-wide tear-down routine */ 175 int 176 _fini(void) 177 { 178 int rval; 179 180 if ((rval = mod_remove(&modlinkage)) != 0) { 181 182 return (rval); 183 } 184 185 ddi_soft_state_fini(&hwarc_statep); 186 187 return (rval); 188 } 189 190 191 int 192 _info(struct modinfo *modinfop) 193 { 194 return (mod_info(&modlinkage, modinfop)); 195 } 196 197 198 /* 199 * hwarc_info: 200 * Get minor number, soft state structure, etc. 201 */ 202 /*ARGSUSED*/ 203 static int 204 hwarc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 205 void *arg, void **result) 206 { 207 hwarc_state_t *hrcp; 208 int error = DDI_FAILURE; 209 210 switch (infocmd) { 211 case DDI_INFO_DEVT2DEVINFO: 212 *result = NULL; 213 if ((hrcp = ddi_get_soft_state(hwarc_statep, 214 getminor((dev_t)arg))) != NULL) { 215 *result = hrcp->hrc_dip; 216 } 217 error = (*result)? DDI_SUCCESS:DDI_FAILURE; 218 219 break; 220 case DDI_INFO_DEVT2INSTANCE: 221 *result = (void *)(uintptr_t)getminor((dev_t)arg); 222 error = DDI_SUCCESS; 223 break; 224 default: 225 break; 226 } 227 228 return (error); 229 } 230 231 232 233 /* 234 * hwarc_init_power_mgmt: 235 * Initialize power management and remote wakeup functionality. 236 * No mutex is necessary in this function as it's called only by attach. 237 */ 238 static void 239 hwarc_init_power_mgmt(hwarc_state_t *hrcp) 240 { 241 hwarc_power_t *hrcpm = NULL; 242 uint_t pwr_states; 243 244 USB_DPRINTF_L4(PRINT_MASK_PM, hrcp->hrc_log_hdl, 245 "init_power_mgmt enter"); 246 247 /* Put online before PM init as can get power managed afterward. */ 248 hrcp->hrc_dev_state = USB_DEV_ONLINE; 249 250 /* Allocate the state structure */ 251 hrcpm = kmem_zalloc(sizeof (hwarc_power_t), KM_SLEEP); 252 253 hrcpm->hrc_state = hrcp; 254 hrcpm->hrc_pm_capabilities = 0; 255 hrcpm->hrc_current_power = USB_DEV_OS_FULL_PWR; 256 257 258 if (usb_create_pm_components(hrcp->hrc_dip, &pwr_states) == 259 USB_SUCCESS) { 260 hrcpm->hrc_pwr_states = (uint8_t)pwr_states; 261 262 if (usb_handle_remote_wakeup(hrcp->hrc_dip, 263 USB_REMOTE_WAKEUP_ENABLE) == USB_SUCCESS) { 264 hrcpm->hrc_wakeup_enabled = 1; 265 } else { 266 USB_DPRINTF_L2(PRINT_MASK_PM, 267 hrcp->hrc_log_hdl, "hwarc_init_power_mgmt:" 268 " remote wakeup not supported"); 269 } 270 271 } else { 272 USB_DPRINTF_L2(PRINT_MASK_PM, hrcp->hrc_log_hdl, 273 "hwarc_init_power_mgmt:created PM components failed"); 274 } 275 mutex_enter(&hrcp->hrc_mutex); 276 hrcp->hrc_pm = hrcpm; 277 hwarc_pm_busy_component(hrcp); 278 mutex_exit(&hrcp->hrc_mutex); 279 280 (void) pm_raise_power( 281 hrcp->hrc_dip, 0, USB_DEV_OS_FULL_PWR); 282 283 USB_DPRINTF_L4(PRINT_MASK_PM, hrcp->hrc_log_hdl, 284 "hwarc_init_power_mgmt: end"); 285 } 286 287 288 /* 289 * hwarc_destroy_power_mgmt: 290 * Shut down and destroy power management and remote wakeup functionality. 291 */ 292 static void 293 hwarc_destroy_power_mgmt(hwarc_state_t *hrcp) 294 { 295 hwarc_power_t *pm; 296 297 USB_DPRINTF_L4(PRINT_MASK_PM, hrcp->hrc_log_hdl, 298 "destroy_power_mgmt enter"); 299 300 mutex_enter(&hrcp->hrc_mutex); 301 302 if ((pm = hrcp->hrc_pm) == NULL) { 303 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 304 "hwarc_destroy_power_mgmt:pm not supported"); 305 goto done; 306 } 307 308 if (hrcp->hrc_dev_state == USB_DEV_DISCONNECTED) { 309 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 310 "hwarc_destroy_power_mgmt:device disconnected"); 311 goto done; 312 } 313 314 hwarc_pm_busy_component(hrcp); 315 316 mutex_exit(&hrcp->hrc_mutex); 317 318 if (pm->hrc_wakeup_enabled) { 319 320 /* First bring the device to full power */ 321 (void) pm_raise_power(hrcp->hrc_dip, 0, USB_DEV_OS_FULL_PWR); 322 if (usb_handle_remote_wakeup(hrcp->hrc_dip, 323 USB_REMOTE_WAKEUP_DISABLE) != USB_SUCCESS) { 324 USB_DPRINTF_L2(PRINT_MASK_PM, 325 hrcp->hrc_log_hdl, "hwarc_destroy_power_mgmt: " 326 "Error disabling rmt wakeup"); 327 } 328 329 } 330 331 /* 332 * Since remote wakeup is disabled now, 333 * no one can raise power 334 * and get to device once power is lowered here. 335 */ 336 (void) pm_lower_power(hrcp->hrc_dip, 0, USB_DEV_OS_PWR_OFF); 337 338 mutex_enter(&hrcp->hrc_mutex); 339 340 hwarc_pm_idle_component(hrcp); 341 342 done: 343 if (pm) { 344 kmem_free(pm, sizeof (hwarc_power_t)); 345 346 hrcp->hrc_pm = NULL; 347 } 348 mutex_exit(&hrcp->hrc_mutex); 349 } 350 351 352 static void 353 hwarc_pm_busy_component(hwarc_state_t *hrcp) 354 { 355 ASSERT(mutex_owned(&hrcp->hrc_mutex)); 356 357 USB_DPRINTF_L4(PRINT_MASK_PM, hrcp->hrc_log_hdl, 358 "hwarc_pm_busy_component: enter"); 359 if (hrcp->hrc_pm == NULL) { 360 USB_DPRINTF_L4(PRINT_MASK_PM, hrcp->hrc_log_hdl, 361 "hwarc_pm_busy_component: pm not supported, return"); 362 363 return; 364 } 365 366 hrcp->hrc_pm->hrc_pm_busy++; 367 368 mutex_exit(&hrcp->hrc_mutex); 369 if (pm_busy_component(hrcp->hrc_dip, 0) != 370 DDI_SUCCESS) { 371 mutex_enter(&hrcp->hrc_mutex); 372 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 373 "hwarc_pm_busy_component: pm busy fail, hrc_pm_busy=%d", 374 hrcp->hrc_pm->hrc_pm_busy); 375 376 hrcp->hrc_pm->hrc_pm_busy--; 377 mutex_exit(&hrcp->hrc_mutex); 378 } 379 mutex_enter(&hrcp->hrc_mutex); 380 381 USB_DPRINTF_L4(PRINT_MASK_PM, hrcp->hrc_log_hdl, 382 "hwarc_pm_busy_component: exit"); 383 } 384 385 386 static void 387 hwarc_pm_idle_component(hwarc_state_t *hrcp) 388 { 389 ASSERT(mutex_owned(&hrcp->hrc_mutex)); 390 USB_DPRINTF_L4(PRINT_MASK_PM, hrcp->hrc_log_hdl, 391 "hwarc_pm_idle_component: enter"); 392 393 if (hrcp->hrc_pm == NULL) { 394 USB_DPRINTF_L4(PRINT_MASK_PM, hrcp->hrc_log_hdl, 395 "hwarc_pm_idle_component: pm not supported"); 396 397 return; 398 } 399 400 mutex_exit(&hrcp->hrc_mutex); 401 if (pm_idle_component(hrcp->hrc_dip, 0) == DDI_SUCCESS) { 402 mutex_enter(&hrcp->hrc_mutex); 403 ASSERT(hrcp->hrc_pm->hrc_pm_busy > 0); 404 hrcp->hrc_pm->hrc_pm_busy--; 405 mutex_exit(&hrcp->hrc_mutex); 406 } 407 mutex_enter(&hrcp->hrc_mutex); 408 409 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 410 "hwarc_pm_idle_component: %d", hrcp->hrc_pm->hrc_pm_busy); 411 412 } 413 414 415 /* 416 * hwarc_pwrlvl0: 417 * Functions to handle power transition for OS levels 0 -> 3 418 */ 419 static int 420 hwarc_pwrlvl0(hwarc_state_t *hrcp) 421 { 422 int rval; 423 424 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 425 "hwarc_pwrlvl0, dev_state: %x", hrcp->hrc_dev_state); 426 427 switch (hrcp->hrc_dev_state) { 428 case USB_DEV_ONLINE: 429 /* Deny the powerdown request if the device is busy */ 430 if (hrcp->hrc_pm->hrc_pm_busy != 0) { 431 USB_DPRINTF_L2(PRINT_MASK_PM, hrcp->hrc_log_hdl, 432 "hwarc_pwrlvl0: hrc_pm_busy"); 433 434 return (USB_FAILURE); 435 } 436 437 /* Close the interrupt pipe */ 438 mutex_exit(&hrcp->hrc_mutex); 439 hwarc_close_intr_pipe(hrcp); 440 mutex_enter(&hrcp->hrc_mutex); 441 442 /* Issue USB D3 command to the device here */ 443 rval = usb_set_device_pwrlvl3(hrcp->hrc_dip); 444 ASSERT(rval == USB_SUCCESS); 445 446 hrcp->hrc_dev_state = USB_DEV_PWRED_DOWN; 447 hrcp->hrc_pm->hrc_current_power = USB_DEV_OS_PWR_OFF; 448 449 /* FALLTHRU */ 450 case USB_DEV_DISCONNECTED: 451 case USB_DEV_SUSPENDED: 452 453 return (USB_SUCCESS); 454 455 case USB_DEV_PWRED_DOWN: 456 default: 457 USB_DPRINTF_L2(PRINT_MASK_PM, hrcp->hrc_log_hdl, 458 "hwarc_pwrlvl0: illegal dev state"); 459 460 return (USB_FAILURE); 461 } 462 } 463 464 465 /* 466 * hwarc_pwrlvl1: 467 * Functions to handle power transition to OS levels -> 2 468 */ 469 static int 470 hwarc_pwrlvl1(hwarc_state_t *hrcp) 471 { 472 int rval; 473 474 USB_DPRINTF_L4(PRINT_MASK_PM, hrcp->hrc_log_hdl, "hwarc_pwrlvl1"); 475 476 /* Issue USB D2 command to the device here */ 477 rval = usb_set_device_pwrlvl2(hrcp->hrc_dip); 478 ASSERT(rval == USB_SUCCESS); 479 480 return (USB_FAILURE); 481 } 482 483 484 /* 485 * hwarc_pwrlvl2: 486 * Functions to handle power transition to OS levels -> 1 487 */ 488 static int 489 hwarc_pwrlvl2(hwarc_state_t *hrcp) 490 { 491 int rval; 492 493 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 494 "hwarc_pwrlvl2, dev_stat=%d", hrcp->hrc_dev_state); 495 496 /* Issue USB D1 command to the device here */ 497 rval = usb_set_device_pwrlvl1(hrcp->hrc_dip); 498 ASSERT(rval == USB_SUCCESS); 499 500 return (USB_FAILURE); 501 } 502 503 504 /* 505 * hwarc_pwrlvl3: 506 * Functions to handle power transition to OS level -> 0 507 */ 508 static int 509 hwarc_pwrlvl3(hwarc_state_t *hrcp) 510 { 511 512 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 513 "hwarc_pwrlvl3, dev_stat=%d", hrcp->hrc_dev_state); 514 515 switch (hrcp->hrc_dev_state) { 516 case USB_DEV_PWRED_DOWN: 517 /* Issue USB D0 command to the device here */ 518 (void) usb_set_device_pwrlvl0(hrcp->hrc_dip); 519 520 mutex_exit(&hrcp->hrc_mutex); 521 if (hwarc_open_intr_pipe(hrcp) != USB_SUCCESS) { 522 mutex_enter(&hrcp->hrc_mutex); 523 524 return (USB_FAILURE); 525 } 526 mutex_enter(&hrcp->hrc_mutex); 527 528 /* Todo: Reset device or not */ 529 hrcp->hrc_dev_state = USB_DEV_ONLINE; 530 hrcp->hrc_pm->hrc_current_power = USB_DEV_OS_FULL_PWR; 531 532 /* FALLTHRU */ 533 case USB_DEV_ONLINE: 534 /* we are already in full power */ 535 /* FALLTHRU */ 536 case USB_DEV_DISCONNECTED: 537 case USB_DEV_SUSPENDED: 538 /* 539 * PM framework tries to put us in full power 540 * during system shutdown. If we are disconnected/cpr'ed 541 * return success anyways 542 */ 543 544 return (USB_SUCCESS); 545 546 default: 547 USB_DPRINTF_L2(PRINT_MASK_PM, hrcp->hrc_log_hdl, 548 "hwarc_pwrlvl3: illegal dev state"); 549 550 return (USB_FAILURE); 551 } 552 } 553 554 /* Init dev inst */ 555 static void 556 hwarc_init_devinst(dev_info_t *dip, hwarc_state_t *hrcp) 557 { 558 char *devinst; 559 int devinstlen; 560 561 hrcp->hrc_dip = dip; 562 hrcp->hrc_log_hdl = usb_alloc_log_hdl(dip, 563 "hwarc", &hwarc_errlevel, 564 &hwarc_errmask, &hwarc_instance_debug, 0); 565 566 devinst = kmem_zalloc(USB_MAXSTRINGLEN, KM_SLEEP); 567 devinstlen = snprintf(devinst, USB_MAXSTRINGLEN, "%s%d: ", 568 ddi_driver_name(dip), ddi_get_instance(dip)); 569 570 hrcp->hrc_devinst = kmem_zalloc(devinstlen + 1, KM_SLEEP); 571 (void) strncpy(hrcp->hrc_devinst, devinst, devinstlen); 572 573 kmem_free(devinst, USB_MAXSTRINGLEN); 574 } 575 576 /* init endpoints */ 577 static int 578 hwarc_init_ep(dev_info_t *dip, hwarc_state_t *hrcp) 579 { 580 int status = USB_SUCCESS; 581 usb_ep_data_t *ep_datap; 582 if ((status = usb_client_attach(dip, USBDRV_VERSION, 0)) != 583 USB_SUCCESS) { 584 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 585 "hwarc_init_ep: usb_client_attach failed" 586 " error code = %d", status); 587 goto done; 588 } 589 590 if ((status = usb_get_dev_data(dip, &hrcp->hrc_reg, USB_PARSE_LVL_ALL, 591 0)) != USB_SUCCESS) { 592 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 593 "hwarc_init_ep: usb_get_dev_data failed" 594 "error code = %d", status); 595 goto done; 596 } 597 hrcp->hrc_if_descr = 598 &hrcp->hrc_reg->dev_curr_cfg->cfg_if[hrcp->hrc_reg->dev_curr_if]; 599 hrcp->hrc_default_ph = hrcp->hrc_reg->dev_default_ph; 600 601 /* 602 * Get the descriptor for an intr pipe at alt 0 of current interface. 603 * This will be used later to open the pipe. 604 */ 605 if ((ep_datap = usb_lookup_ep_data(dip, hrcp->hrc_reg, 606 hrcp->hrc_reg->dev_curr_if, 0, 0, 607 USB_EP_ATTR_INTR, USB_EP_DIR_IN)) == NULL) { 608 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 609 "hwarc_init_ep: Error getting intr endpoint descriptor"); 610 status = USB_FAILURE; 611 goto done; 612 } 613 hrcp->hrc_intr_ep_descr = ep_datap->ep_descr; 614 615 done: 616 617 return (status); 618 } 619 /* init mutex */ 620 static void 621 hwarc_init_mutex(hwarc_state_t *hrcp) { 622 mutex_init(&hrcp->hrc_mutex, NULL, MUTEX_DRIVER, 623 hrcp->hrc_reg->dev_iblock_cookie); 624 625 cv_init(&hrcp->hrc_serial_cv, NULL, CV_DRIVER, NULL); 626 hrcp->hrc_serial_inuse = B_FALSE; 627 628 hrcp->hrc_locks_initialized = B_TRUE; 629 } 630 /* 631 * hwarc_attach: 632 * Attach or resume. 633 * 634 * For attach, initialize state and device, including: 635 * state variables, locks, device node 636 * device registration with system 637 * power management, hotplugging 638 * For resume, restore device and state 639 */ 640 static int 641 hwarc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 642 { 643 int instance = ddi_get_instance(dip); 644 hwarc_state_t *hrcp = NULL; 645 646 switch (cmd) { 647 case DDI_ATTACH: 648 break; 649 650 case DDI_RESUME: 651 hwarc_cpr_resume(dip); 652 /* 653 * Always return success to work around enumeration 654 * failures.This works around an issue where devices 655 * which are present before a suspend and absent upon 656 * resume could cause a system panic on resume. 657 */ 658 659 return (DDI_SUCCESS); 660 default: 661 return (DDI_FAILURE); 662 } 663 664 if (ddi_soft_state_zalloc(hwarc_statep, instance) == DDI_SUCCESS) { 665 hrcp = ddi_get_soft_state(hwarc_statep, instance); 666 } 667 if (hrcp == NULL) { 668 USB_DPRINTF_L2(PRINT_MASK_ATTA, NULL, 669 "hwarc_attach: get soft state failed for instance %d", 670 instance); 671 672 return (DDI_FAILURE); 673 } 674 675 (void) hwarc_init_devinst(dip, hrcp); 676 677 if (hwarc_init_ep(dip, hrcp) != USB_SUCCESS) { 678 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 679 "attach: Error init usb data"); 680 goto fail; 681 } 682 hwarc_init_mutex(hrcp); 683 684 /* create minor node */ 685 if (ddi_create_minor_node(dip, name, S_IFCHR, instance, 686 NULL, 0) != DDI_SUCCESS) { 687 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 688 "attach: Error creating minor node"); 689 goto fail; 690 } 691 692 /* initialize power management */ 693 hwarc_init_power_mgmt(hrcp); 694 695 if (usb_register_hotplug_cbs(dip, hwarc_disconnect_callback, 696 hwarc_reconnect_callback) != USB_SUCCESS) { 697 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 698 "attach: Error register hotplug cbs"); 699 700 goto fail; 701 } 702 703 /* register this device to uwba */ 704 uwb_dev_attach(dip, &hrcp->hrc_dev_hdl, 0, hwarc_send_cmd); 705 706 if (hwarc_open_intr_pipe(hrcp) != USB_SUCCESS) { 707 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 708 "attach: Error open intr pipe"); 709 710 goto fail; 711 } 712 713 /* reset device */ 714 if (hwarc_reset_device(hrcp) != USB_SUCCESS) { 715 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 716 "attach: Error reset deivce"); 717 goto fail; 718 } 719 /* init phy capabilities */ 720 if (hwarc_init_phy(hrcp) != USB_SUCCESS) { 721 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 722 "attach: Error get phy ie"); 723 724 goto fail; 725 } 726 /* Report device */ 727 ddi_report_dev(dip); 728 729 mutex_enter(&hrcp->hrc_mutex); 730 hwarc_pm_idle_component(hrcp); 731 mutex_exit(&hrcp->hrc_mutex); 732 733 return (DDI_SUCCESS); 734 735 fail: 736 (void) hwarc_cleanup(dip, hrcp); 737 738 return (DDI_FAILURE); 739 } 740 741 742 /* 743 * hwarc_detach: 744 * detach or suspend driver instance 745 * 746 * Note: in detach, only contention threads is from pm and disconnnect. 747 */ 748 static int 749 hwarc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 750 { 751 int rval = USB_SUCCESS; 752 hwarc_state_t *hrcp = 753 ddi_get_soft_state(hwarc_statep, ddi_get_instance(dip)); 754 755 USB_DPRINTF_L3(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 756 "hwarc_detach: enter for detach, cmd = %d", cmd); 757 758 759 switch (cmd) { 760 case DDI_DETACH: 761 762 rval = hwarc_cleanup(dip, hrcp); 763 764 break; 765 case DDI_SUSPEND: 766 767 rval = hwarc_cpr_suspend(dip); 768 default: 769 770 break; 771 } 772 773 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 774 } 775 776 777 /* 778 * hwarc_cleanup: 779 * clean up the driver state for detach 780 */ 781 static int 782 hwarc_cleanup(dev_info_t *dip, hwarc_state_t *hrcp) 783 { 784 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, "Cleanup: enter"); 785 786 if (hrcp->hrc_locks_initialized) { 787 788 (void) uwb_stop_beacon(dip); 789 /* This must be done 1st to prevent more events from coming. */ 790 usb_unregister_hotplug_cbs(dip); 791 792 hwarc_close_intr_pipe(hrcp); 793 794 /* 795 * At this point, no new activity can be initiated. The driver 796 * has disabled hotplug callbacks. The Solaris framework has 797 * disabled new opens on a device being detached, and does not 798 * allow detaching an open device. 799 * 800 * The following ensures that all driver activity has drained. 801 */ 802 mutex_enter(&hrcp->hrc_mutex); 803 (void) hwarc_serialize_access(hrcp, HWARC_SER_NOSIG); 804 hwarc_release_access(hrcp); 805 mutex_exit(&hrcp->hrc_mutex); 806 807 /* All device activity has died down. */ 808 hwarc_destroy_power_mgmt(hrcp); 809 810 /* start dismantling */ 811 ddi_remove_minor_node(dip, NULL); 812 cv_destroy(&hrcp->hrc_serial_cv); 813 mutex_destroy(&hrcp->hrc_mutex); 814 } 815 816 usb_client_detach(dip, hrcp->hrc_reg); 817 818 USB_DPRINTF_L4(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, "Cleanup: end"); 819 820 usb_free_log_hdl(hrcp->hrc_log_hdl); 821 822 uwb_dev_detach(hrcp->hrc_dev_hdl); 823 824 kmem_free(hrcp->hrc_devinst, strlen(hrcp->hrc_devinst) + 1); 825 826 ddi_soft_state_free(hwarc_statep, ddi_get_instance(dip)); 827 ddi_prop_remove_all(dip); 828 829 return (USB_SUCCESS); 830 } 831 832 833 834 /*ARGSUSED*/ 835 static int 836 hwarc_open(dev_t *devp, int flag, int otyp, cred_t *cred_p) 837 { 838 hwarc_state_t *hrcp = NULL; 839 int rval = 0; 840 841 hrcp = ddi_get_soft_state(hwarc_statep, getminor(*devp)); 842 843 ASSERT(hrcp != NULL); 844 845 USB_DPRINTF_L4(PRINT_MASK_OPEN, hrcp->hrc_log_hdl, "hwarc_open: enter"); 846 847 /* 848 * Keep it simple: one client at a time. 849 * Exclusive open only 850 */ 851 mutex_enter(&hrcp->hrc_mutex); 852 /* exclusive open */ 853 if ((flag & FEXCL) && (hrcp->hrc_open_count > 0)) { 854 USB_DPRINTF_L2(PRINT_MASK_OPEN, hrcp->hrc_log_hdl, 855 "hwarc_open failed, open count=%d", hrcp->hrc_open_count); 856 mutex_exit(&hrcp->hrc_mutex); 857 858 return (EBUSY); 859 } 860 861 if ((hrcp->hrc_dev_state == USB_DEV_DISCONNECTED) || 862 (hrcp->hrc_dev_state == USB_DEV_SUSPENDED)) { 863 864 USB_DPRINTF_L2(PRINT_MASK_OPEN, hrcp->hrc_log_hdl, 865 "hwarc_open failed, dev_stat=%d", hrcp->hrc_dev_state); 866 mutex_exit(&hrcp->hrc_mutex); 867 868 return (EIO); 869 } 870 871 hrcp->hrc_open_count++; 872 873 USB_DPRINTF_L3(PRINT_MASK_OPEN, hrcp->hrc_log_hdl, 874 "hwarc_open, open count=%d", hrcp->hrc_open_count); 875 if (hwarc_serialize_access(hrcp, HWARC_SER_SIG) == 0) { 876 hrcp->hrc_open_count--; 877 hwarc_release_access(hrcp); 878 mutex_exit(&hrcp->hrc_mutex); 879 880 return (EINTR); 881 } 882 883 hwarc_pm_busy_component(hrcp); 884 885 mutex_exit(&hrcp->hrc_mutex); 886 (void) pm_raise_power(hrcp->hrc_dip, 0, USB_DEV_OS_FULL_PWR); 887 888 mutex_enter(&hrcp->hrc_mutex); 889 /* Fail if device is no longer ready. */ 890 if (hrcp->hrc_dev_state != USB_DEV_ONLINE) { 891 USB_DPRINTF_L2(PRINT_MASK_OPEN, hrcp->hrc_log_hdl, 892 "hwarc_open failed, dev_stat=%d", hrcp->hrc_dev_state); 893 rval = EIO; 894 } 895 hwarc_release_access(hrcp); 896 /* Device specific initialization goes here. */ 897 if (rval != 0) { 898 hrcp->hrc_open_count--; 899 hwarc_pm_idle_component(hrcp); 900 } 901 mutex_exit(&hrcp->hrc_mutex); 902 903 USB_DPRINTF_L4(PRINT_MASK_OPEN, hrcp->hrc_log_hdl, "hwarc_open: leave"); 904 905 return (0); 906 } 907 908 909 /*ARGSUSED*/ 910 static int 911 hwarc_close(dev_t dev, int flag, int otyp, cred_t *cred_p) 912 { 913 hwarc_state_t *hrcp = 914 ddi_get_soft_state(hwarc_statep, getminor(dev)); 915 916 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hrcp->hrc_log_hdl, 917 "hwarc_close: enter"); 918 919 mutex_enter(&hrcp->hrc_mutex); 920 (void) hwarc_serialize_access(hrcp, HWARC_SER_NOSIG); 921 922 hrcp->hrc_open_count--; 923 USB_DPRINTF_L3(PRINT_MASK_CLOSE, hrcp->hrc_log_hdl, 924 "hwarc_close: open count=%d", hrcp->hrc_open_count); 925 926 hwarc_release_access(hrcp); 927 hwarc_pm_idle_component(hrcp); 928 929 mutex_exit(&hrcp->hrc_mutex); 930 931 USB_DPRINTF_L4(PRINT_MASK_CLOSE, hrcp->hrc_log_hdl, 932 "hwarc_close: leave"); 933 934 return (0); 935 } 936 937 /* Send cmd to hwarc device */ 938 int 939 hwarc_send_cmd(uwb_dev_handle_t uwb_dev_hdl, mblk_t *data, uint16_t data_len) 940 { 941 usb_cb_flags_t cb_flags; 942 usb_cr_t cr; 943 usb_ctrl_setup_t setup; 944 int rval; 945 hwarc_state_t *hrcp = NULL; 946 dev_info_t *dip = uwb_get_dip(uwb_dev_hdl); 947 948 hrcp = ddi_get_soft_state(hwarc_statep, ddi_get_instance(dip)); 949 950 ASSERT((hrcp != NULL) && (data != NULL)); 951 952 setup.bmRequestType = HWARC_SET_IF; 953 setup.bRequest = HWA_EXEC_RC_CMD; 954 955 setup.wValue = 0; 956 setup.wIndex = hrcp->hrc_if_descr->if_alt->altif_descr.bInterfaceNumber; 957 958 setup.wLength = data_len; 959 setup.attrs = 0; 960 961 USB_DPRINTF_L3(PRINT_MASK_DEVCTRL, hrcp->hrc_log_hdl, 962 "hwarc_send_cmd: wLength=%d, data[0], [1], [2], [3]=%d, %d, %d, %d", 963 setup.wLength, data->b_rptr[0], data->b_rptr[1], data->b_rptr[2], 964 data->b_rptr[3]); 965 966 if ((rval = usb_pipe_ctrl_xfer_wait(hrcp->hrc_default_ph, &setup, 967 &data, &cr, &cb_flags, 0)) != USB_SUCCESS) { 968 USB_DPRINTF_L2(PRINT_MASK_DEVCTRL, hrcp->hrc_log_hdl, 969 "hwarc_send_cmd: fail, rval=%d, cr=%d, " 970 "cb_flags=%x", rval, cr, cb_flags); 971 972 } 973 974 freemsg(data); 975 976 return (rval); 977 } 978 979 /* ioctl, call uwb ioctl */ 980 /*ARGSUSED*/ 981 static int 982 hwarc_ioctl(dev_t dev, int cmd, intptr_t arg, 983 int mode, cred_t *cred_p, int *rval_p) 984 { 985 int rv = 0; 986 987 hwarc_state_t *hrcp = 988 ddi_get_soft_state(hwarc_statep, getminor(dev)); 989 if (hrcp == NULL) { 990 991 return (ENXIO); 992 } 993 994 if (drv_priv(cred_p) != 0) { 995 USB_DPRINTF_L3(PRINT_MASK_ALL, hrcp->hrc_log_hdl, 996 "hwahc_wusb_ioctl: user must have SYS_DEVICE privilege," 997 "cmd=%x", cmd); 998 999 return (EPERM); 1000 } 1001 1002 1003 1004 USB_DPRINTF_L4(PRINT_MASK_ALL, hrcp->hrc_log_hdl, "hwarc_ioctl: enter"); 1005 1006 mutex_enter(&hrcp->hrc_mutex); 1007 if (hrcp->hrc_dev_state != USB_DEV_ONLINE) { 1008 USB_DPRINTF_L2(PRINT_MASK_ALL, hrcp->hrc_log_hdl, 1009 "ioctl: Device is not online," 1010 " dev_stat=%d", hrcp->hrc_dev_state); 1011 mutex_exit(&hrcp->hrc_mutex); 1012 1013 return (EFAULT); 1014 } 1015 mutex_exit(&hrcp->hrc_mutex); 1016 1017 rv = uwb_do_ioctl(hrcp->hrc_dev_hdl, cmd, arg, mode); 1018 1019 return (rv); 1020 } 1021 1022 1023 /* 1024 * hwarc_disconnect_callback: 1025 * Called when device hotplug-removed. 1026 * Close pipes. (This does not attempt to contact device.) 1027 * Set state to DISCONNECTED 1028 */ 1029 static int 1030 hwarc_disconnect_callback(dev_info_t *dip) 1031 { 1032 hwarc_state_t *hrcp = 1033 ddi_get_soft_state(hwarc_statep, ddi_get_instance(dip)); 1034 1035 USB_DPRINTF_L4(PRINT_MASK_CB, hrcp->hrc_log_hdl, "disconnect: enter"); 1036 1037 /* Disconnect the uwb device will stop beacon and save state */ 1038 (void) uwb_dev_disconnect(dip); 1039 hwarc_close_intr_pipe(hrcp); 1040 1041 mutex_enter(&hrcp->hrc_mutex); 1042 (void) hwarc_serialize_access(hrcp, HWARC_SER_NOSIG); 1043 1044 /* 1045 * Save any state of device or IO in progress required by 1046 * hwarc_restore_device_state for proper device "thawing" later. 1047 */ 1048 hrcp->hrc_dev_state = USB_DEV_DISCONNECTED; 1049 1050 hwarc_release_access(hrcp); 1051 mutex_exit(&hrcp->hrc_mutex); 1052 1053 return (USB_SUCCESS); 1054 } 1055 1056 1057 /* 1058 * hwarc_reconnect_callback: 1059 * Called with device hotplug-inserted 1060 * Restore state 1061 */ 1062 static int 1063 hwarc_reconnect_callback(dev_info_t *dip) 1064 { 1065 int instance = ddi_get_instance(dip); 1066 hwarc_state_t *hrcp = 1067 ddi_get_soft_state(hwarc_statep, instance); 1068 1069 USB_DPRINTF_L4(PRINT_MASK_CB, hrcp->hrc_log_hdl, "reconnect: enter"); 1070 1071 mutex_enter(&hrcp->hrc_mutex); 1072 (void) hwarc_serialize_access(hrcp, HWARC_SER_NOSIG); 1073 hwarc_restore_device_state(dip, hrcp); 1074 hwarc_release_access(hrcp); 1075 mutex_exit(&hrcp->hrc_mutex); 1076 1077 /* Reconnect the uwb device will restore uwb device state */ 1078 (void) uwb_dev_reconnect(dip); 1079 return (USB_SUCCESS); 1080 } 1081 1082 1083 /* 1084 * hwarc_restore_device_state: 1085 * Called during hotplug-reconnect and resume. 1086 * reenable power management 1087 * Verify the device is the same as before the disconnect/suspend. 1088 * Restore device state 1089 * Thaw any IO which was frozen. 1090 * Quiesce device. (Other routines will activate if thawed IO.) 1091 * Set device online. 1092 * Leave device disconnected if there are problems. 1093 */ 1094 static void 1095 hwarc_restore_device_state(dev_info_t *dip, hwarc_state_t *hrcp) 1096 { 1097 1098 USB_DPRINTF_L4(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 1099 "hwarc_restore_device_state: enter"); 1100 1101 ASSERT(mutex_owned(&hrcp->hrc_mutex)); 1102 1103 ASSERT((hrcp->hrc_dev_state == USB_DEV_DISCONNECTED) || 1104 (hrcp->hrc_dev_state == USB_DEV_SUSPENDED)); 1105 1106 hwarc_pm_busy_component(hrcp); 1107 1108 mutex_exit(&hrcp->hrc_mutex); 1109 1110 (void) pm_raise_power(hrcp->hrc_dip, 0, USB_DEV_OS_FULL_PWR); 1111 1112 if (usb_check_same_device(dip, hrcp->hrc_log_hdl, USB_LOG_L2, 1113 PRINT_MASK_ALL, USB_CHK_BASIC|USB_CHK_CFG, NULL) != USB_SUCCESS) { 1114 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 1115 "hwarc_restore_device_state: check same device failed"); 1116 1117 goto fail; 1118 1119 } 1120 if (hwarc_open_intr_pipe(hrcp) != USB_SUCCESS) { 1121 1122 goto fail; 1123 } 1124 mutex_enter(&hrcp->hrc_mutex); 1125 1126 hrcp->hrc_dev_state = USB_DEV_ONLINE; 1127 1128 if (hrcp->hrc_pm && hrcp->hrc_pm->hrc_wakeup_enabled) { 1129 1130 mutex_exit(&hrcp->hrc_mutex); 1131 if (usb_handle_remote_wakeup(dip, USB_REMOTE_WAKEUP_ENABLE) != 1132 USB_SUCCESS) { 1133 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 1134 "hwarc_restore_device_state: " 1135 "fail to enable device remote wakeup"); 1136 } 1137 mutex_enter(&hrcp->hrc_mutex); 1138 1139 } 1140 1141 hwarc_pm_idle_component(hrcp); 1142 1143 USB_DPRINTF_L3(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 1144 "hwarc_restore_device_state: end"); 1145 1146 return; 1147 1148 fail: 1149 /* change the device state from suspended to disconnected */ 1150 mutex_enter(&hrcp->hrc_mutex); 1151 hrcp->hrc_dev_state = USB_DEV_DISCONNECTED; 1152 hwarc_pm_idle_component(hrcp); 1153 } 1154 1155 1156 /* 1157 * hwarc_cpr_suspend: 1158 * Clean up device. 1159 * Wait for any IO to finish, then close pipes. 1160 * Quiesce device. 1161 */ 1162 static int 1163 hwarc_cpr_suspend(dev_info_t *dip) 1164 { 1165 hwarc_state_t *hrcp = ddi_get_soft_state(hwarc_statep, 1166 ddi_get_instance(dip)); 1167 1168 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 1169 "hwarc_cpr_suspend, dev_stat=%d", hrcp->hrc_dev_state); 1170 1171 /* Disconnect the uwb device will stop beacon and save state */ 1172 (void) uwb_dev_disconnect(dip); 1173 1174 /* Serialize to prevent races with detach, open, device access. */ 1175 mutex_enter(&hrcp->hrc_mutex); 1176 (void) hwarc_serialize_access(hrcp, HWARC_SER_NOSIG); 1177 1178 hwarc_pm_busy_component(hrcp); 1179 1180 /* 1181 * Set dev_state to suspended so other driver threads don't start any 1182 * new I/O. In a real driver, there may be draining of requests done 1183 * afterwards, and we don't want the draining to compete with new 1184 * requests being queued. 1185 */ 1186 1187 /* Don't suspend if the device is open. */ 1188 if (hrcp->hrc_open_count != 0) { 1189 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 1190 "suspend: Device is open. Can't suspend"); 1191 1192 hwarc_release_access(hrcp); 1193 hwarc_pm_idle_component(hrcp); 1194 mutex_exit(&hrcp->hrc_mutex); 1195 1196 return (USB_FAILURE); 1197 } 1198 1199 /* Access device here to clean it up. */ 1200 mutex_exit(&hrcp->hrc_mutex); 1201 hwarc_close_intr_pipe(hrcp); 1202 mutex_enter(&hrcp->hrc_mutex); 1203 1204 hrcp->hrc_dev_state = USB_DEV_SUSPENDED; 1205 1206 /* 1207 * Save any state of device required by hwarc_restore_device_state 1208 * for proper device "thawing" later. 1209 */ 1210 hwarc_release_access(hrcp); 1211 hwarc_pm_idle_component(hrcp); 1212 mutex_exit(&hrcp->hrc_mutex); 1213 1214 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, "suspend: success"); 1215 1216 return (USB_SUCCESS); 1217 } 1218 1219 1220 /* 1221 * hwarc_cpr_resume: 1222 * 1223 * hwarc_restore_device_state marks success by putting device back online 1224 */ 1225 static void 1226 hwarc_cpr_resume(dev_info_t *dip) 1227 { 1228 int instance = ddi_get_instance(dip); 1229 hwarc_state_t *hrcp = ddi_get_soft_state(hwarc_statep, 1230 instance); 1231 1232 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 1233 "hwarc_cpr_resume, dev_stat=%d", hrcp->hrc_dev_state); 1234 1235 /* 1236 * NOTE: A pm_raise_power in hwarc_restore_device_state will bring 1237 * the power-up state of device into synch with the system. 1238 */ 1239 mutex_enter(&hrcp->hrc_mutex); 1240 hwarc_restore_device_state(dip, hrcp); 1241 mutex_exit(&hrcp->hrc_mutex); 1242 1243 /* Reconnect the uwb device will restore uwb device state */ 1244 (void) uwb_dev_reconnect(dip); 1245 } 1246 1247 /* 1248 * pipe callbacks 1249 * -------------- 1250 * 1251 * intr in callback for event receiving for hwarc device 1252 */ 1253 /*ARGSUSED*/ 1254 void 1255 hwarc_intr_cb(usb_pipe_handle_t pipe, usb_intr_req_t *req) 1256 { 1257 hwarc_state_t *hrcp = (hwarc_state_t *)req->intr_client_private; 1258 uwb_dev_handle_t uwb_dev_hd; 1259 mblk_t *data = req->intr_data; 1260 int data_len, parse_err; 1261 1262 uwb_dev_hd = hrcp->hrc_dev_hdl; 1263 data_len = (data) ? MBLKL(data) : 0; 1264 1265 if (data_len == 0) { 1266 1267 return; 1268 } 1269 1270 /* 1271 * Parse the event/notifications from the device, and cv_signal the 1272 * waiting cmd 1273 */ 1274 parse_err = uwb_parse_evt_notif((uint8_t *)data->b_rptr, 1275 data_len, uwb_dev_hd); 1276 if (parse_err != UWB_SUCCESS) { 1277 USB_DPRINTF_L2(PRINT_MASK_CB, hrcp->hrc_log_hdl, 1278 "hwarc_intr_cb: parse failed, no cmd result or " 1279 "notifs delivered. parse_err= %d", parse_err); 1280 if (data_len >= 5) { 1281 USB_DPRINTF_L2(PRINT_MASK_CB, hrcp->hrc_log_hdl, 1282 "hwarc_intr_cb: erro evt len=%d" 1283 " evtcode=%d %d,evt_context=%d, result-code=%d", 1284 data_len, data->b_rptr[1], data->b_rptr[2], 1285 data->b_rptr[3], data->b_rptr[4]); 1286 } 1287 } 1288 1289 usb_free_intr_req(req); 1290 } 1291 1292 /* 1293 * pipe callbacks 1294 * -------------- 1295 * 1296 * intr in exception callback 1297 */ 1298 void 1299 hwarc_intr_ex_cb(usb_pipe_handle_t pipe, usb_intr_req_t *req) 1300 { 1301 hwarc_state_t *hrcp = (hwarc_state_t *)req->intr_client_private; 1302 usb_cr_t cr = req->intr_completion_reason; 1303 1304 USB_DPRINTF_L4(PRINT_MASK_CB, hrcp->hrc_log_hdl, 1305 "hwarc_intr_ex_cb: ph = 0x%p req = 0x%p cr=%d flags=%x", 1306 (void *)pipe, (void *)req, cr, req->intr_cb_flags); 1307 1308 usb_free_intr_req(req); 1309 1310 /* restart polling */ 1311 if ((cr != USB_CR_PIPE_CLOSING) && (cr != USB_CR_STOPPED_POLLING) && 1312 (cr != USB_CR_FLUSHED) && (cr != USB_CR_DEV_NOT_RESP) && 1313 (cr != USB_CR_PIPE_RESET) && 1314 (hrcp->hrc_dev_state == USB_DEV_ONLINE)) { 1315 if (hwarc_start_polling(hrcp, hrcp->hrc_intr_ph) != 1316 USB_SUCCESS) { 1317 USB_DPRINTF_L2(PRINT_MASK_CB, hrcp->hrc_log_hdl, 1318 "hwarc_intr_ex_cb:" 1319 "Restart pollling failed."); 1320 } 1321 } else { 1322 USB_DPRINTF_L2(PRINT_MASK_CB, hrcp->hrc_log_hdl, 1323 "hwarc_intr_ex_cb:" 1324 "get events failed: cr=%d", cr); 1325 } 1326 } 1327 1328 /* 1329 * start polling on the interrupt pipe for events 1330 */ 1331 int 1332 hwarc_start_polling(hwarc_state_t *hrcp, usb_pipe_handle_t intr_ph) 1333 { 1334 usb_intr_req_t *br; 1335 int rval = USB_SUCCESS; 1336 1337 USB_DPRINTF_L3(PRINT_MASK_OPEN, hrcp->hrc_log_hdl, 1338 "hwarc_start_polling"); 1339 1340 br = usb_alloc_intr_req(hrcp->hrc_dip, 0, USB_FLAGS_SLEEP); 1341 1342 if (!br) { 1343 USB_DPRINTF_L2(PRINT_MASK_OPEN, hrcp->hrc_log_hdl, 1344 "hwarc_start_polling: alloc req failed."); 1345 1346 return (USB_FAILURE); 1347 } 1348 br->intr_attributes = USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING; 1349 br->intr_len = hrcp->hrc_intr_ep_descr.wMaxPacketSize; 1350 br->intr_client_private = (void *)hrcp; 1351 1352 br->intr_cb = hwarc_intr_cb; 1353 br->intr_exc_cb = hwarc_intr_ex_cb; 1354 1355 rval = usb_pipe_intr_xfer(intr_ph, br, USB_FLAGS_SLEEP); 1356 1357 if (rval != USB_SUCCESS) { 1358 usb_free_intr_req(br); 1359 1360 USB_DPRINTF_L2(PRINT_MASK_OPEN, hrcp->hrc_log_hdl, 1361 "hwarc_start_polling: failed (%d)", rval); 1362 } 1363 1364 return (rval); 1365 } 1366 1367 /* 1368 * hwarc_open_intr_pipe: 1369 * Open any pipes other than default pipe. 1370 * Mutex is assumed to be held. 1371 */ 1372 static int 1373 hwarc_open_intr_pipe(hwarc_state_t *hrcp) 1374 { 1375 1376 int rval = USB_SUCCESS; 1377 usb_pipe_policy_t pipe_policy; 1378 usb_pipe_handle_t pipe_handle; 1379 1380 USB_DPRINTF_L3(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, "open_pipes enter"); 1381 1382 bzero(&pipe_policy, sizeof (pipe_policy)); 1383 1384 /* 1385 * Allow that pipes can support at least two asynchronous operations 1386 * going on simultaneously. Operations include asynchronous callbacks, 1387 * resets, closures. 1388 */ 1389 pipe_policy.pp_max_async_reqs = 2; 1390 1391 if ((rval = usb_pipe_open(hrcp->hrc_dip, 1392 &hrcp->hrc_intr_ep_descr, &pipe_policy, 1393 USB_FLAGS_SLEEP, &pipe_handle)) != USB_SUCCESS) { 1394 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 1395 "hwarc_open_intr_pipe:Error opening intr pipe: status = %d", 1396 rval); 1397 goto done; 1398 } 1399 1400 mutex_enter(&hrcp->hrc_mutex); 1401 hrcp->hrc_intr_ph = pipe_handle; 1402 mutex_exit(&hrcp->hrc_mutex); 1403 1404 /* 1405 * At this point, polling could be started on the pipe by making an 1406 * asynchronous input request on the pipe. Allocate a request by 1407 * calling usb_alloc_intr_req(9F) with a zero length, initialize 1408 * attributes with USB_ATTRS_SHORT_XFER_OK | USB_ATTRS_AUTOCLEARING, 1409 * initialize length to be packetsize of the endpoint, specify the 1410 * callbacks. Pass this request to usb_pipe_intr_xfer to start polling. 1411 * Call usb_pipe_stop_intr_poling(9F) to stop polling. 1412 */ 1413 rval = hwarc_start_polling(hrcp, hrcp->hrc_intr_ph); 1414 if (rval != USB_SUCCESS) { 1415 hwarc_close_intr_pipe(hrcp); 1416 1417 USB_DPRINTF_L3(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 1418 "hwarc_open_intr_pipe: Error start " 1419 "polling intr pipe: rval = %d", rval); 1420 } 1421 1422 done: 1423 1424 return (rval); 1425 } 1426 1427 1428 /* 1429 * hwarc_close_intr_pipe: 1430 * Close pipes. Mutex is assumed to be held. 1431 */ 1432 static void 1433 hwarc_close_intr_pipe(hwarc_state_t *hrcp) 1434 { 1435 usb_pipe_handle_t pipe_handle = NULL; 1436 USB_DPRINTF_L3(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, "close_pipes enter"); 1437 1438 mutex_enter(&hrcp->hrc_mutex); 1439 if (!hrcp->hrc_intr_ph) { 1440 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 1441 "hwarc intr pipe not exist"); 1442 mutex_exit(&hrcp->hrc_mutex); 1443 return; 1444 } 1445 1446 pipe_handle = hrcp->hrc_intr_ph; 1447 hrcp->hrc_intr_ph = NULL; 1448 mutex_exit(&hrcp->hrc_mutex); 1449 1450 /* Stop polling */ 1451 usb_pipe_stop_intr_polling(pipe_handle, USB_FLAGS_SLEEP); 1452 1453 /* Close Pipe */ 1454 usb_pipe_close(hrcp->hrc_dip, pipe_handle, USB_FLAGS_SLEEP, NULL, 0); 1455 } 1456 1457 /* 1458 * hwarc_power : 1459 * Power entry point, the workhorse behind pm_raise_power, pm_lower_power, 1460 * usb_req_raise_power and usb_req_lower_power. 1461 */ 1462 /*ARGSUSED*/ 1463 static int 1464 hwarc_power(dev_info_t *dip, int comp, int level) 1465 { 1466 hwarc_state_t *hrcp; 1467 int rval = USB_FAILURE; 1468 1469 hrcp = ddi_get_soft_state(hwarc_statep, ddi_get_instance(dip)); 1470 1471 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 1472 "hwarc_power: level = %d", level); 1473 1474 mutex_enter(&hrcp->hrc_mutex); 1475 1476 ASSERT(hrcp->hrc_pm != NULL); 1477 1478 (void) hwarc_serialize_access(hrcp, HWARC_SER_NOSIG); 1479 1480 /* 1481 * If we are disconnected/suspended, return success. Note that if we 1482 * return failure, bringing down the system will hang when 1483 * PM tries to power up all devices 1484 */ 1485 if ((hrcp->hrc_dev_state == USB_DEV_DISCONNECTED) || 1486 (hrcp->hrc_dev_state == USB_DEV_SUSPENDED)) { 1487 1488 USB_DPRINTF_L3(PRINT_MASK_PM, hrcp->hrc_log_hdl, 1489 "hwarc_power: disconnected/suspended " 1490 "dev_state=%d", hrcp->hrc_dev_state); 1491 rval = USB_SUCCESS; 1492 1493 goto done; 1494 } 1495 1496 1497 /* Check if we are transitioning to a legal power level */ 1498 if (USB_DEV_PWRSTATE_OK(hrcp->hrc_pm->hrc_pwr_states, level)) { 1499 USB_DPRINTF_L2(PRINT_MASK_PM, hrcp->hrc_log_hdl, 1500 "hwarc_power: illegal power level = %d " 1501 "pwr_states: %x", level, hrcp->hrc_pm->hrc_pwr_states); 1502 1503 goto done; 1504 } 1505 1506 switch (level) { 1507 case USB_DEV_OS_PWR_OFF : 1508 rval = hwarc_pwrlvl0(hrcp); 1509 1510 break; 1511 case USB_DEV_OS_PWR_1: 1512 rval = hwarc_pwrlvl1(hrcp); 1513 1514 break; 1515 case USB_DEV_OS_PWR_2: 1516 rval = hwarc_pwrlvl2(hrcp); 1517 1518 break; 1519 case USB_DEV_OS_FULL_PWR : 1520 rval = hwarc_pwrlvl3(hrcp); 1521 1522 break; 1523 } 1524 1525 done: 1526 hwarc_release_access(hrcp); 1527 mutex_exit(&hrcp->hrc_mutex); 1528 1529 return ((rval == USB_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE); 1530 } 1531 1532 1533 /* 1534 * hwarc_serialize_access: 1535 * Get the serial synchronization object before returning. 1536 * 1537 * Arguments: 1538 * hrcp - Pointer to hwarc state structure 1539 * waitsig - Set to: 1540 * HWARC_SER_SIG - to wait such that a signal can interrupt 1541 * HWARC_SER_NOSIG - to wait such that a signal cannot interrupt 1542 */ 1543 static int 1544 hwarc_serialize_access(hwarc_state_t *hrcp, boolean_t waitsig) 1545 { 1546 int rval = 1; 1547 1548 ASSERT(mutex_owned(&hrcp->hrc_mutex)); 1549 1550 while (hrcp->hrc_serial_inuse) { 1551 if (waitsig == HWARC_SER_SIG) { 1552 rval = cv_wait_sig(&hrcp->hrc_serial_cv, 1553 &hrcp->hrc_mutex); 1554 } else { 1555 cv_wait(&hrcp->hrc_serial_cv, 1556 &hrcp->hrc_mutex); 1557 } 1558 } 1559 hrcp->hrc_serial_inuse = B_TRUE; 1560 1561 return (rval); 1562 } 1563 1564 1565 /* 1566 * hwarc_release_access: 1567 * Release the serial synchronization object. 1568 */ 1569 static void 1570 hwarc_release_access(hwarc_state_t *hrcp) 1571 { 1572 ASSERT(mutex_owned(&hrcp->hrc_mutex)); 1573 hrcp->hrc_serial_inuse = B_FALSE; 1574 cv_broadcast(&hrcp->hrc_serial_cv); 1575 } 1576 1577 1578 /* 1579 * hwarc_reset_device: 1580 * Reset the readio controller with uwb interfaces. 1581 * if the device is different. Can block. 1582 */ 1583 static int 1584 hwarc_reset_device(hwarc_state_t *hrcp) 1585 { 1586 if (uwb_reset_dev(hrcp->hrc_dip) != UWB_SUCCESS) { 1587 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 1588 "hwarc_reset_device: uwb_reset_dev failed"); 1589 1590 return (USB_FAILURE); 1591 } 1592 1593 return (USB_SUCCESS); 1594 } 1595 1596 /* 1597 * hwarc_init_phy 1598 * init the physical capabilities of the radio controller. 1599 * the band groups and phy rates will be initialized in the 1600 * uwb devices. 1601 */ 1602 static int 1603 hwarc_init_phy(hwarc_state_t *hrcp) 1604 { 1605 if (uwb_init_phy(hrcp->hrc_dip) != UWB_SUCCESS) { 1606 USB_DPRINTF_L2(PRINT_MASK_ATTA, hrcp->hrc_log_hdl, 1607 "hwarc_init_phy: uwb_init_phy failed"); 1608 1609 return (USB_FAILURE); 1610 } 1611 1612 return (USB_SUCCESS); 1613 }