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 * Universal Host Controller Driver (UHCI) 29 * 30 * The UHCI driver is a driver which interfaces to the Universal 31 * Serial Bus Architecture (USBA) and the Host Controller (HC). The interface to 32 * the Host Controller is defined by the Universal Host Controller Interface. 33 * This file contains code for auto-configuration entry points and interrupt 34 * handling. 35 */ 36 #include <sys/usb/hcd/uhci/uhcid.h> 37 #include <sys/usb/hcd/uhci/uhcihub.h> 38 #include <sys/usb/hcd/uhci/uhciutil.h> 39 40 /* 41 * Prototype Declarations for cb_ops and dev_ops 42 */ 43 static int uhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 44 static int uhci_add_intrs(uhci_state_t *uhcip, int intr_type); 45 static int uhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 46 static void uhci_rem_intrs(uhci_state_t *uhcip); 47 static int uhci_open(dev_t *devp, int flags, int otyp, cred_t *credp); 48 static int uhci_close(dev_t dev, int flag, int otyp, cred_t *credp); 49 static int uhci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 50 cred_t *credp, int *rvalp); 51 static int uhci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd); 52 static int uhci_quiesce(dev_info_t *dip); 53 static int uhci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 54 void **result); 55 56 /* extern */ 57 int usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level); 58 59 static struct cb_ops uhci_cb_ops = { 60 uhci_open, /* Open */ 61 uhci_close, /* Close */ 62 nodev, /* Strategy */ 63 nodev, /* Print */ 64 nodev, /* Dump */ 65 nodev, /* Read */ 66 nodev, /* Write */ 67 uhci_ioctl, /* Ioctl */ 68 nodev, /* Devmap */ 69 nodev, /* Mmap */ 70 nodev, /* Segmap */ 71 nochpoll, /* Poll */ 72 ddi_prop_op, /* cb_prop_op */ 73 NULL, /* Streamtab */ 74 D_MP /* Driver compatibility flag */ 75 }; 76 77 static struct dev_ops uhci_ops = { 78 DEVO_REV, /* Devo_rev */ 79 0, /* Refcnt */ 80 uhci_info, /* Info */ 81 nulldev, /* Identify */ 82 nulldev, /* Probe */ 83 uhci_attach, /* Attach */ 84 uhci_detach, /* Detach */ 85 uhci_reset, /* Reset */ 86 &uhci_cb_ops, /* Driver operations */ 87 &usba_hubdi_busops, /* Bus operations */ 88 usba_hubdi_root_hub_power, /* Power */ 89 uhci_quiesce /* quiesce */ 90 }; 91 92 static struct modldrv modldrv = { 93 &mod_driverops, /* Type of module. This one is a driver */ 94 "USB UHCI Controller Driver", /* Name of the module. */ 95 &uhci_ops, /* Driver ops */ 96 }; 97 98 static struct modlinkage modlinkage = { 99 MODREV_1, (void *)&modldrv, NULL 100 }; 101 102 /* 103 * Globals 104 */ 105 void *uhci_statep; 106 uint_t uhci_errlevel = USB_LOG_L2; 107 uint_t uhci_errmask = PRINT_MASK_ALL; 108 uint_t uhci_instance_debug = (uint_t)-1; 109 110 uint_t uhci_td_pool_size = 256; /* Num TDs */ 111 uint_t uhci_qh_pool_size = 130; /* Num QHs */ 112 ushort_t uhci_tree_bottom_nodes[NUM_FRAME_LST_ENTRIES]; 113 114 115 /* 116 * UHCI MSI tunable: 117 * 118 * By default MSI is enabled on all supported platforms. 119 */ 120 boolean_t uhci_enable_msi = B_TRUE; 121 122 /* 123 * tunable, delay during attach in seconds 124 */ 125 int uhci_attach_wait = 0; 126 127 /* function prototypes */ 128 static void uhci_handle_intr_td_errors(uhci_state_t *uhcip, uhci_td_t *td, 129 uhci_trans_wrapper_t *tw, uhci_pipe_private_t *pp); 130 static void uhci_handle_one_xfer_completion(uhci_state_t *uhcip, 131 usb_cr_t usb_err, uhci_td_t *td); 132 static uint_t uhci_intr(caddr_t arg1, caddr_t arg2); 133 static int uhci_cleanup(uhci_state_t *uhcip); 134 static int uhci_cpr_suspend(uhci_state_t *uhcip); 135 static int uhci_cpr_resume(uhci_state_t *uhcip); 136 137 138 int 139 _init(void) 140 { 141 int error; 142 ushort_t i, j, k, *temp, num_of_nodes; 143 144 /* Initialize the soft state structures */ 145 if ((error = ddi_soft_state_init(&uhci_statep, sizeof (uhci_state_t), 146 UHCI_MAX_INSTS)) != 0) { 147 148 return (error); 149 } 150 151 /* Install the loadable module */ 152 if ((error = mod_install(&modlinkage)) != 0) { 153 ddi_soft_state_fini(&uhci_statep); 154 155 return (error); 156 } 157 158 /* 159 * Build the tree bottom shared by all instances 160 */ 161 temp = kmem_zalloc(NUM_FRAME_LST_ENTRIES * 2, KM_SLEEP); 162 163 num_of_nodes = 1; 164 for (i = 0; i < log_2(NUM_FRAME_LST_ENTRIES); i++) { 165 for (j = 0, k = 0; k < num_of_nodes; k++, j++) { 166 uhci_tree_bottom_nodes[j++] = temp[k]; 167 uhci_tree_bottom_nodes[j] = temp[k] + pow_2(i); 168 } 169 170 num_of_nodes *= 2; 171 for (k = 0; k < num_of_nodes; k++) 172 temp[k] = uhci_tree_bottom_nodes[k]; 173 174 } 175 kmem_free(temp, (NUM_FRAME_LST_ENTRIES*2)); 176 177 178 return (error); 179 } 180 181 182 int 183 _info(struct modinfo *modinfop) 184 { 185 return (mod_info(&modlinkage, modinfop)); 186 } 187 188 189 int 190 _fini(void) 191 { 192 int error; 193 194 error = mod_remove(&modlinkage); 195 196 if (error == 0) { 197 /* Release per module resources */ 198 ddi_soft_state_fini(&uhci_statep); 199 } 200 201 return (error); 202 } 203 204 /* 205 * The following simulated polling is for debugging purposes only. 206 * It is activated on x86 by setting usb-polling=true in GRUB or uhci.conf. 207 */ 208 static int 209 uhci_is_polled(dev_info_t *dip) 210 { 211 int ret; 212 char *propval; 213 214 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, 215 "usb-polling", &propval) != DDI_SUCCESS) 216 217 return (0); 218 219 ret = (strcmp(propval, "true") == 0); 220 ddi_prop_free(propval); 221 222 return (ret); 223 } 224 225 static void 226 uhci_poll_intr(void *arg) 227 { 228 /* poll every msec */ 229 for (;;) { 230 (void) uhci_intr(arg, NULL); 231 delay(drv_usectohz(1000)); 232 } 233 } 234 235 /* 236 * Host Controller Driver (HCD) Auto configuration entry points 237 */ 238 239 /* 240 * Function Name : uhci_attach: 241 * Description : Attach entry point - called by the Kernel. 242 * Allocates of per controller data structure. 243 * Initializes the controller. 244 * Output : DDI_SUCCESS / DDI_FAILURE 245 */ 246 static int 247 uhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 248 { 249 int instance, polled; 250 int i, intr_types; 251 uhci_state_t *uhcip = NULL; 252 usba_hcdi_register_args_t hcdi_args; 253 254 USB_DPRINTF_L4(PRINT_MASK_ATTA, NULL, "uhci_attach:"); 255 256 switch (cmd) { 257 case DDI_ATTACH: 258 break; 259 case DDI_RESUME: 260 uhcip = uhci_obtain_state(dip); 261 262 return (uhci_cpr_resume(uhcip)); 263 default: 264 265 return (DDI_FAILURE); 266 } 267 268 /* Get the instance and create soft state */ 269 instance = ddi_get_instance(dip); 270 271 /* Allocate the soft state structure for this instance of the driver */ 272 if (ddi_soft_state_zalloc(uhci_statep, instance) != 0) { 273 274 return (DDI_FAILURE); 275 } 276 277 if ((uhcip = ddi_get_soft_state(uhci_statep, instance)) == NULL) { 278 279 return (DDI_FAILURE); 280 } 281 282 uhcip->uhci_log_hdl = usb_alloc_log_hdl(dip, "uhci", &uhci_errlevel, 283 &uhci_errmask, &uhci_instance_debug, 0); 284 285 /* Set host controller soft state to initialization */ 286 uhcip->uhci_hc_soft_state = UHCI_CTLR_INIT_STATE; 287 288 /* Save the dip and instance */ 289 uhcip->uhci_dip = dip; 290 uhcip->uhci_instance = instance; 291 292 polled = uhci_is_polled(dip); 293 if (polled) 294 295 goto skip_intr; 296 297 /* Get supported interrupt types */ 298 if (ddi_intr_get_supported_types(uhcip->uhci_dip, 299 &intr_types) != DDI_SUCCESS) { 300 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 301 "uhci_attach: ddi_intr_get_supported_types failed"); 302 303 usb_free_log_hdl(uhcip->uhci_log_hdl); 304 ddi_soft_state_free(uhci_statep, instance); 305 306 return (DDI_FAILURE); 307 } 308 309 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 310 "uhci_attach: supported interrupt types 0x%x", intr_types); 311 312 if ((intr_types & DDI_INTR_TYPE_MSI) && uhci_enable_msi) { 313 if (uhci_add_intrs(uhcip, DDI_INTR_TYPE_MSI) 314 != DDI_SUCCESS) { 315 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 316 "uhci_attach: MSI registration failed, " 317 "trying FIXED interrupt \n"); 318 } else { 319 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 320 "uhci_attach: Using MSI interrupt type\n"); 321 322 uhcip->uhci_intr_type = DDI_INTR_TYPE_MSI; 323 } 324 } 325 326 if (!(uhcip->uhci_htable) && (intr_types & DDI_INTR_TYPE_FIXED)) { 327 if (uhci_add_intrs(uhcip, DDI_INTR_TYPE_FIXED) 328 != DDI_SUCCESS) { 329 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 330 "uhci_attach: FIXED interrupt registration " 331 "failed\n"); 332 333 usb_free_log_hdl(uhcip->uhci_log_hdl); 334 ddi_soft_state_free(uhci_statep, instance); 335 336 return (DDI_FAILURE); 337 } 338 339 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 340 "uhci_attach: Using FIXED interrupt type\n"); 341 342 uhcip->uhci_intr_type = DDI_INTR_TYPE_FIXED; 343 } 344 345 skip_intr: 346 /* Semaphore to serialize opens and closes */ 347 sema_init(&uhcip->uhci_ocsem, 1, NULL, SEMA_DRIVER, NULL); 348 349 /* Create prototype condition variable */ 350 cv_init(&uhcip->uhci_cv_SOF, NULL, CV_DRIVER, NULL); 351 352 /* Initialize the DMA attributes */ 353 uhci_set_dma_attributes(uhcip); 354 355 /* Initialize the kstat structures */ 356 uhci_create_stats(uhcip); 357 358 /* Create the td and ed pools */ 359 if (uhci_allocate_pools(uhcip) != USB_SUCCESS) { 360 361 goto fail; 362 } 363 364 /* Map the registers */ 365 if (uhci_map_regs(uhcip) != USB_SUCCESS) { 366 367 goto fail; 368 } 369 370 /* Enable all interrupts */ 371 if (polled) { 372 extern pri_t maxclsyspri; 373 374 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 375 "uhci_attach: running in simulated polled mode."); 376 377 /* create thread to poll */ 378 (void) thread_create(NULL, 0, uhci_poll_intr, uhcip, 0, &p0, 379 TS_RUN, maxclsyspri); 380 } else if (uhcip->uhci_intr_cap & DDI_INTR_FLAG_BLOCK) { 381 /* Call ddi_intr_block_enable() for MSI interrupts */ 382 (void) ddi_intr_block_enable(uhcip->uhci_htable, 383 uhcip->uhci_intr_cnt); 384 } else { 385 /* Call ddi_intr_enable for MSI or FIXED interrupts */ 386 for (i = 0; i < uhcip->uhci_intr_cnt; i++) 387 (void) ddi_intr_enable(uhcip->uhci_htable[i]); 388 } 389 390 391 /* Initialize the controller */ 392 if (uhci_init_ctlr(uhcip) != USB_SUCCESS) { 393 394 goto fail; 395 } 396 397 /* 398 * At this point, the hardware will be okay. 399 * Initialize the usba_hcdi structure 400 */ 401 uhcip->uhci_hcdi_ops = uhci_alloc_hcdi_ops(uhcip); 402 403 /* 404 * Make this HCD instance known to USBA 405 * (dma_attr must be passed for USBA busctl's) 406 */ 407 hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION; 408 hcdi_args.usba_hcdi_register_dip = dip; 409 hcdi_args.usba_hcdi_register_ops = uhcip->uhci_hcdi_ops; 410 hcdi_args.usba_hcdi_register_dma_attr = &uhcip->uhci_dma_attr; 411 hcdi_args.usba_hcdi_register_iblock_cookie = 412 (ddi_iblock_cookie_t)(uintptr_t)uhcip->uhci_intr_pri; 413 414 if (usba_hcdi_register(&hcdi_args, 0) != USB_SUCCESS) { 415 416 goto fail; 417 } 418 419 #ifndef __sparc 420 /* 421 * On NCR system, the driver seen failure of some commands 422 * while booting. This delay mysteriously solved the problem. 423 */ 424 delay(drv_usectohz(uhci_attach_wait*1000000)); 425 #endif 426 427 /* 428 * Create another timeout handler to check whether any 429 * control/bulk/interrupt commands failed. 430 * This gets called every second. 431 */ 432 uhcip->uhci_cmd_timeout_id = timeout(uhci_cmd_timeout_hdlr, 433 (void *)uhcip, UHCI_ONE_SECOND); 434 435 mutex_enter(&uhcip->uhci_int_mutex); 436 437 /* 438 * Set HcInterruptEnable to enable all interrupts except Root 439 * Hub Status change and SOF interrupts. 440 */ 441 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS); 442 443 /* Test the SOF interrupt */ 444 if (uhci_wait_for_sof(uhcip) != USB_SUCCESS) { 445 USB_DPRINTF_L0(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 446 "No SOF interrupts have been received, this USB UHCI host" 447 " controller is unusable"); 448 mutex_exit(&uhcip->uhci_int_mutex); 449 450 goto fail; 451 } 452 453 mutex_exit(&uhcip->uhci_int_mutex); 454 455 /* This should be the last step which might fail during attaching */ 456 if (uhci_init_root_hub(uhcip) != USB_SUCCESS) { 457 458 goto fail; 459 } 460 461 /* Display information in the banner */ 462 ddi_report_dev(dip); 463 464 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 465 "uhci_attach successful"); 466 467 return (DDI_SUCCESS); 468 469 fail: 470 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 471 "failed to attach"); 472 473 (void) uhci_cleanup(uhcip); 474 475 return (DDI_FAILURE); 476 } 477 478 479 /* 480 * uhci_add_intrs: 481 * 482 * Register FIXED or MSI interrupts. 483 */ 484 static int 485 uhci_add_intrs(uhci_state_t *uhcip, 486 int intr_type) 487 { 488 int actual, avail, intr_size, count = 0; 489 int i, flag, ret; 490 491 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 492 "uhci_add_intrs: interrupt type 0x%x", intr_type); 493 494 /* Get number of interrupts */ 495 ret = ddi_intr_get_nintrs(uhcip->uhci_dip, intr_type, &count); 496 if ((ret != DDI_SUCCESS) || (count == 0)) { 497 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 498 "uhci_add_intrs: ddi_intr_get_nintrs() failure, " 499 "ret: %d, count: %d", ret, count); 500 501 return (DDI_FAILURE); 502 } 503 504 /* Get number of available interrupts */ 505 ret = ddi_intr_get_navail(uhcip->uhci_dip, intr_type, &avail); 506 if ((ret != DDI_SUCCESS) || (avail == 0)) { 507 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 508 "uhci_add_intrs: ddi_intr_get_navail() failure, " 509 "ret: %d, count: %d", ret, count); 510 511 return (DDI_FAILURE); 512 } 513 514 if (avail < count) { 515 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 516 "uhci_add_intrs: uhci_add_intrs: nintrs () " 517 "returned %d, navail returned %d\n", count, avail); 518 } 519 520 /* Allocate an array of interrupt handles */ 521 intr_size = count * sizeof (ddi_intr_handle_t); 522 uhcip->uhci_htable = kmem_zalloc(intr_size, KM_SLEEP); 523 524 flag = (intr_type == DDI_INTR_TYPE_MSI) ? 525 DDI_INTR_ALLOC_STRICT:DDI_INTR_ALLOC_NORMAL; 526 527 /* call ddi_intr_alloc() */ 528 ret = ddi_intr_alloc(uhcip->uhci_dip, uhcip->uhci_htable, 529 intr_type, 0, count, &actual, flag); 530 531 if ((ret != DDI_SUCCESS) || (actual == 0)) { 532 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 533 "uhci_add_intrs: ddi_intr_alloc() failed %d", ret); 534 535 kmem_free(uhcip->uhci_htable, intr_size); 536 537 return (DDI_FAILURE); 538 } 539 540 if (actual < count) { 541 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 542 "uhci_add_intrs: Requested: %d, Received: %d\n", 543 count, actual); 544 545 for (i = 0; i < actual; i++) 546 (void) ddi_intr_free(uhcip->uhci_htable[i]); 547 548 kmem_free(uhcip->uhci_htable, intr_size); 549 550 return (DDI_FAILURE); 551 } 552 553 uhcip->uhci_intr_cnt = actual; 554 555 if ((ret = ddi_intr_get_pri(uhcip->uhci_htable[0], 556 &uhcip->uhci_intr_pri)) != DDI_SUCCESS) { 557 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 558 "uhci_add_intrs: ddi_intr_get_pri() failed %d", ret); 559 560 for (i = 0; i < actual; i++) 561 (void) ddi_intr_free(uhcip->uhci_htable[i]); 562 563 kmem_free(uhcip->uhci_htable, intr_size); 564 565 return (DDI_FAILURE); 566 } 567 568 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 569 "uhci_add_intrs: Supported Interrupt priority 0x%x", 570 uhcip->uhci_intr_pri); 571 572 /* Test for high level mutex */ 573 if (uhcip->uhci_intr_pri >= ddi_intr_get_hilevel_pri()) { 574 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 575 "uhci_add_intrs: Hi level interrupt not supported"); 576 577 for (i = 0; i < actual; i++) 578 (void) ddi_intr_free(uhcip->uhci_htable[i]); 579 580 kmem_free(uhcip->uhci_htable, intr_size); 581 582 return (DDI_FAILURE); 583 } 584 585 /* Initialize the mutex */ 586 mutex_init(&uhcip->uhci_int_mutex, NULL, MUTEX_DRIVER, 587 DDI_INTR_PRI(uhcip->uhci_intr_pri)); 588 589 /* Call ddi_intr_add_handler() */ 590 for (i = 0; i < actual; i++) { 591 if ((ret = ddi_intr_add_handler(uhcip->uhci_htable[i], 592 uhci_intr, (caddr_t)uhcip, 593 (caddr_t)(uintptr_t)i)) != DDI_SUCCESS) { 594 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 595 "uhci_add_intrs: ddi_intr_add_handler() " 596 "failed %d", ret); 597 598 for (i = 0; i < actual; i++) 599 (void) ddi_intr_free(uhcip->uhci_htable[i]); 600 601 mutex_destroy(&uhcip->uhci_int_mutex); 602 kmem_free(uhcip->uhci_htable, intr_size); 603 604 return (DDI_FAILURE); 605 } 606 } 607 608 if ((ret = ddi_intr_get_cap(uhcip->uhci_htable[0], 609 &uhcip->uhci_intr_cap)) != DDI_SUCCESS) { 610 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 611 "uhci_add_intrs: ddi_intr_get_cap() failed %d", ret); 612 613 for (i = 0; i < actual; i++) { 614 (void) ddi_intr_remove_handler(uhcip->uhci_htable[i]); 615 (void) ddi_intr_free(uhcip->uhci_htable[i]); 616 } 617 618 mutex_destroy(&uhcip->uhci_int_mutex); 619 kmem_free(uhcip->uhci_htable, intr_size); 620 621 return (DDI_FAILURE); 622 } 623 624 return (DDI_SUCCESS); 625 } 626 627 628 /* 629 * Function Name: uhci_detach 630 * Description: Detach entry point - called by the Kernel. 631 * Deallocates all the memory 632 * Unregisters the interrupt handle and other resources. 633 * Output: DDI_SUCCESS / DDI_FAILURE 634 */ 635 static int 636 uhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 637 { 638 uhci_state_t *uhcip = uhci_obtain_state(dip); 639 640 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 641 "uhci_detach:"); 642 643 switch (cmd) { 644 case DDI_DETACH: 645 646 return (uhci_cleanup(uhcip) == USB_SUCCESS ? 647 DDI_SUCCESS : DDI_FAILURE); 648 case DDI_SUSPEND: 649 650 return (uhci_cpr_suspend(uhcip)); 651 default: 652 653 return (DDI_FAILURE); 654 } 655 } 656 657 658 /* 659 * uhci_rem_intrs: 660 * 661 * Unregister FIXED or MSI interrupts 662 */ 663 static void 664 uhci_rem_intrs(uhci_state_t *uhcip) 665 { 666 int i; 667 668 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 669 "uhci_rem_intrs: interrupt type 0x%x", uhcip->uhci_intr_type); 670 671 /* Disable all interrupts */ 672 if (uhcip->uhci_intr_cap & DDI_INTR_FLAG_BLOCK) { 673 (void) ddi_intr_block_disable(uhcip->uhci_htable, 674 uhcip->uhci_intr_cnt); 675 } else { 676 for (i = 0; i < uhcip->uhci_intr_cnt; i++) { 677 (void) ddi_intr_disable(uhcip->uhci_htable[i]); 678 } 679 } 680 681 /* Call ddi_intr_remove_handler() */ 682 for (i = 0; i < uhcip->uhci_intr_cnt; i++) { 683 (void) ddi_intr_remove_handler(uhcip->uhci_htable[i]); 684 (void) ddi_intr_free(uhcip->uhci_htable[i]); 685 } 686 687 kmem_free(uhcip->uhci_htable, 688 uhcip->uhci_intr_cnt * sizeof (ddi_intr_handle_t)); 689 } 690 691 692 /* 693 * Function Name: uhci_reset 694 * Description: Reset entry point - called by the Kernel 695 * on the way down. 696 * The Toshiba laptop has been observed to hang 697 * on reboot when BIOS is set to suspend/resume. 698 * The resetting uhci on the way down solves the 699 * problem. 700 * Output: DDI_SUCCESS / DDI_FAILURE 701 */ 702 /* ARGSUSED */ 703 static int 704 uhci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd) 705 { 706 uhci_state_t *uhcip = uhci_obtain_state(dip); 707 708 /* Disable all HC ED list processing */ 709 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); 710 Set_OpReg16(USBCMD, 0); 711 712 return (DDI_SUCCESS); 713 } 714 715 /* 716 * quiesce(9E) entry point. 717 * 718 * This function is called when the system is single-threaded at high 719 * PIL with preemption disabled. Therefore, this function must not be 720 * blocked. 721 * 722 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 723 * DDI_FAILURE indicates an error condition and should almost never happen. 724 */ 725 static int 726 uhci_quiesce(dev_info_t *dip) 727 { 728 uhci_state_t *uhcip = uhci_obtain_state(dip); 729 730 if (uhcip == NULL) 731 return (DDI_FAILURE); 732 733 /* Disable interrupts */ 734 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); 735 736 /* Stop the Host Controller */ 737 Set_OpReg16(USBCMD, 0); 738 739 /* Clear all status bits */ 740 Set_OpReg16(USBSTS, Get_OpReg16(USBSTS) & UHCI_INTR_MASK); 741 742 return (DDI_SUCCESS); 743 } 744 745 746 /* 747 * uhci_info: 748 */ 749 /* ARGSUSED */ 750 static int 751 uhci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 752 { 753 dev_t dev; 754 int instance; 755 int error = DDI_FAILURE; 756 uhci_state_t *uhcip; 757 758 switch (infocmd) { 759 case DDI_INFO_DEVT2DEVINFO: 760 dev = (dev_t)arg; 761 instance = UHCI_UNIT(dev); 762 uhcip = ddi_get_soft_state(uhci_statep, instance); 763 if (uhcip != NULL) { 764 *result = (void *)uhcip->uhci_dip; 765 if (*result != NULL) { 766 error = DDI_SUCCESS; 767 } 768 } else { 769 *result = NULL; 770 } 771 772 break; 773 case DDI_INFO_DEVT2INSTANCE: 774 dev = (dev_t)arg; 775 instance = UHCI_UNIT(dev); 776 *result = (void *)(uintptr_t)instance; 777 error = DDI_SUCCESS; 778 779 break; 780 default: 781 break; 782 } 783 784 return (error); 785 } 786 787 788 /* 789 * uhci_cleanup: 790 * Cleanup on attach failure or detach 791 */ 792 static int 793 uhci_cleanup(uhci_state_t *uhcip) 794 { 795 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, "uhci_cleanup:"); 796 797 if (usba_hubdi_unbind_root_hub(uhcip->uhci_dip) != USB_SUCCESS) { 798 799 return (USB_FAILURE); 800 } 801 802 mutex_enter(&uhcip->uhci_int_mutex); 803 804 if (uhcip->uhci_cmd_timeout_id) { 805 timeout_id_t timeout_id = uhcip->uhci_cmd_timeout_id; 806 uhcip->uhci_cmd_timeout_id = 0; 807 mutex_exit(&uhcip->uhci_int_mutex); 808 (void) untimeout(timeout_id); 809 mutex_enter(&uhcip->uhci_int_mutex); 810 } 811 812 uhci_uninit_ctlr(uhcip); 813 814 mutex_exit(&uhcip->uhci_int_mutex); 815 816 /* do interrupt cleanup */ 817 if (uhcip->uhci_htable) { 818 uhci_rem_intrs(uhcip); 819 } 820 821 mutex_enter(&uhcip->uhci_int_mutex); 822 823 usba_hcdi_unregister(uhcip->uhci_dip); 824 825 uhci_unmap_regs(uhcip); 826 827 uhci_free_pools(uhcip); 828 829 mutex_exit(&uhcip->uhci_int_mutex); 830 831 mutex_destroy(&uhcip->uhci_int_mutex); 832 cv_destroy(&uhcip->uhci_cv_SOF); 833 sema_destroy(&uhcip->uhci_ocsem); 834 835 /* cleanup kstat structures */ 836 uhci_destroy_stats(uhcip); 837 838 usba_free_hcdi_ops(uhcip->uhci_hcdi_ops); 839 usb_free_log_hdl(uhcip->uhci_log_hdl); 840 ddi_prop_remove_all(uhcip->uhci_dip); 841 ddi_soft_state_free(uhci_statep, uhcip->uhci_instance); 842 843 return (USB_SUCCESS); 844 } 845 846 847 /* 848 * uhci_cpr_suspend 849 */ 850 static int 851 uhci_cpr_suspend(uhci_state_t *uhcip) 852 { 853 uint16_t cmd_reg; 854 int i; 855 856 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 857 "uhci_cpr_suspend:"); 858 859 /* Call into the root hub and suspend it */ 860 if (usba_hubdi_detach(uhcip->uhci_dip, DDI_SUSPEND) != DDI_SUCCESS) { 861 862 return (DDI_FAILURE); 863 } 864 865 mutex_enter(&uhcip->uhci_int_mutex); 866 867 /* Stop the Host Controller */ 868 cmd_reg = Get_OpReg16(USBCMD); 869 cmd_reg &= ~USBCMD_REG_HC_RUN; 870 Set_OpReg16(USBCMD, cmd_reg); 871 872 /* 873 * Wait for the duration of an SOF period until the host controller 874 * reaches the stopped state, indicated by the HCHalted bit in the 875 * USB status register. 876 */ 877 for (i = 0; i <= UHCI_TIMEWAIT / 1000; i++) { 878 if (Get_OpReg16(USBSTS) & USBSTS_REG_HC_HALTED) 879 break; 880 drv_usecwait(1000); 881 } 882 883 USB_DPRINTF_L3(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 884 "uhci_cpr_suspend: waited %d milliseconds for hc to halt", i); 885 886 /* Disable interrupts */ 887 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); 888 889 /* Clear any scheduled pending interrupts */ 890 Set_OpReg16(USBSTS, USBSTS_REG_HC_HALTED | 891 USBSTS_REG_HC_PROCESS_ERR | USBSTS_REG_HOST_SYS_ERR | 892 USBSTS_REG_RESUME_DETECT | USBSTS_REG_USB_ERR_INTR | 893 USBSTS_REG_USB_INTR); 894 895 /* Set Global Suspend bit */ 896 Set_OpReg16(USBCMD, USBCMD_REG_ENTER_GBL_SUSPEND); 897 898 /* Set host controller soft state to suspend */ 899 uhcip->uhci_hc_soft_state = UHCI_CTLR_SUSPEND_STATE; 900 901 /* Reset the host controller. This can poweroff downstream ports */ 902 Set_OpReg16(USBCMD, USBCMD_REG_GBL_RESET); 903 904 /* Wait 10ms for reset to complete */ 905 mutex_exit(&uhcip->uhci_int_mutex); 906 delay(drv_usectohz(UHCI_RESET_DELAY)); 907 mutex_enter(&uhcip->uhci_int_mutex); 908 909 Set_OpReg16(USBCMD, 0); 910 911 mutex_exit(&uhcip->uhci_int_mutex); 912 913 return (USB_SUCCESS); 914 } 915 916 917 /* 918 * uhci_cpr_cleanup: 919 * 920 * Cleanup uhci specific information across resuming. 921 */ 922 static void 923 uhci_cpr_cleanup(uhci_state_t *uhcip) 924 { 925 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 926 927 /* Reset software part of usb frame number */ 928 uhcip->uhci_sw_frnum = 0; 929 } 930 931 932 /* 933 * uhci_cpr_resume 934 */ 935 static int 936 uhci_cpr_resume(uhci_state_t *uhcip) 937 { 938 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 939 "uhci_cpr_resume: Restart the controller"); 940 941 mutex_enter(&uhcip->uhci_int_mutex); 942 943 /* Cleanup uhci specific information across cpr */ 944 uhci_cpr_cleanup(uhcip); 945 946 mutex_exit(&uhcip->uhci_int_mutex); 947 948 /* Restart the controller */ 949 if (uhci_init_ctlr(uhcip) != DDI_SUCCESS) { 950 951 USB_DPRINTF_L2(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 952 "uhci_cpr_resume: uhci host controller resume failed "); 953 954 return (DDI_FAILURE); 955 } 956 957 mutex_enter(&uhcip->uhci_int_mutex); 958 959 /* 960 * Set HcInterruptEnable to enable all interrupts except Root 961 * Hub Status change and SOF interrupts. 962 */ 963 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS); 964 965 mutex_exit(&uhcip->uhci_int_mutex); 966 967 /* Now resume the root hub */ 968 if (usba_hubdi_attach(uhcip->uhci_dip, DDI_RESUME) != DDI_SUCCESS) { 969 970 return (DDI_FAILURE); 971 } 972 973 return (DDI_SUCCESS); 974 } 975 976 977 /* 978 * uhci_intr: 979 * uhci interrupt handling routine. 980 */ 981 static uint_t 982 uhci_intr(caddr_t arg1, caddr_t arg2) 983 { 984 ushort_t intr_status, cmd_reg, intr_reg; 985 uhci_state_t *uhcip = (uhci_state_t *)arg1; 986 987 USB_DPRINTF_L4(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 988 "uhci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p", 989 (void *)arg1, (void *)arg2); 990 991 mutex_enter(&uhcip->uhci_int_mutex); 992 993 /* Any interrupt is not handled for the suspended device. */ 994 if (uhcip->uhci_hc_soft_state == UHCI_CTLR_SUSPEND_STATE) { 995 mutex_exit(&uhcip->uhci_int_mutex); 996 997 return (DDI_INTR_UNCLAIMED); 998 } 999 1000 /* Get the status of the interrupts */ 1001 intr_status = Get_OpReg16(USBSTS); 1002 intr_reg = Get_OpReg16(USBINTR); 1003 1004 USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1005 "uhci_intr: intr_status = %x, intr_reg = %x", 1006 intr_status, intr_reg); 1007 1008 /* 1009 * If uhci interrupts are all disabled, the driver should return 1010 * unclaimed. 1011 * HC Process Error and Host System Error interrupts cannot be 1012 * disabled by intr register, and need to be judged separately. 1013 */ 1014 if (((intr_reg & ENABLE_ALL_INTRS) == 0) && 1015 ((intr_status & USBSTS_REG_HC_PROCESS_ERR) == 0) && 1016 ((intr_status & USBSTS_REG_HOST_SYS_ERR) == 0)) { 1017 1018 USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1019 "uhci_intr: interrupts disabled, unclaim"); 1020 mutex_exit(&uhcip->uhci_int_mutex); 1021 1022 return (DDI_INTR_UNCLAIMED); 1023 } 1024 1025 /* 1026 * If the intr is not from our controller, just return unclaimed. 1027 * HCHalted status bit cannot generate interrupts and should be 1028 * ignored. 1029 */ 1030 if (!(intr_status & UHCI_INTR_MASK)) { 1031 1032 USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1033 "uhci_intr: no interrupt status set, unclaim"); 1034 mutex_exit(&uhcip->uhci_int_mutex); 1035 1036 return (DDI_INTR_UNCLAIMED); 1037 } 1038 1039 /* Update kstat values */ 1040 uhci_do_intrs_stats(uhcip, intr_status); 1041 1042 /* Acknowledge the interrupt */ 1043 Set_OpReg16(USBSTS, intr_status); 1044 1045 /* 1046 * If uhci controller has not been initialized, just clear the 1047 * interrupter status and return claimed. 1048 */ 1049 if (uhcip->uhci_hc_soft_state != UHCI_CTLR_OPERATIONAL_STATE) { 1050 1051 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1052 "uhci_intr: uhci controller is not in the operational " 1053 "state"); 1054 mutex_exit(&uhcip->uhci_int_mutex); 1055 1056 return (DDI_INTR_CLAIMED); 1057 } 1058 1059 /* 1060 * We configured the hw incorrectly, disable future interrupts. 1061 */ 1062 if ((intr_status & USBSTS_REG_HOST_SYS_ERR)) { 1063 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1064 "uhci_intr: Sys Err Disabling Interrupt"); 1065 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); 1066 uhcip->uhci_hc_soft_state = UHCI_CTLR_ERROR_STATE; 1067 1068 mutex_exit(&uhcip->uhci_int_mutex); 1069 1070 return (DDI_INTR_CLAIMED); 1071 } 1072 1073 /* 1074 * Check whether a frame number overflow occurred. 1075 * if so, update the sw frame number. 1076 */ 1077 uhci_isoc_update_sw_frame_number(uhcip); 1078 1079 /* 1080 * Check whether any commands got completed. If so, process them. 1081 */ 1082 uhci_process_submitted_td_queue(uhcip); 1083 1084 /* 1085 * This should not occur. It occurs only if a HC controller 1086 * experiences internal problem. 1087 */ 1088 if (intr_status & USBSTS_REG_HC_HALTED) { 1089 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1090 "uhci_intr: Controller halted"); 1091 cmd_reg = Get_OpReg16(USBCMD); 1092 Set_OpReg16(USBCMD, (cmd_reg | USBCMD_REG_HC_RUN)); 1093 } 1094 1095 /* 1096 * Wake up all the threads which are waiting for the Start of Frame 1097 */ 1098 if (uhcip->uhci_cv_signal == B_TRUE) { 1099 cv_broadcast(&uhcip->uhci_cv_SOF); 1100 uhcip->uhci_cv_signal = B_FALSE; 1101 } 1102 1103 mutex_exit(&uhcip->uhci_int_mutex); 1104 1105 return (DDI_INTR_CLAIMED); 1106 } 1107 1108 1109 /* 1110 * uhci_process_submitted_td_queue: 1111 * Traverse thru the submitted queue and process the completed ones. 1112 */ 1113 void 1114 uhci_process_submitted_td_queue(uhci_state_t *uhcip) 1115 { 1116 uhci_td_t *head = uhcip->uhci_outst_tds_head; 1117 uhci_trans_wrapper_t *tw; 1118 1119 while (head != NULL) { 1120 if ((!(GetTD_status(uhcip, head) & UHCI_TD_ACTIVE)) && 1121 (head->tw->tw_claim == UHCI_NOT_CLAIMED)) { 1122 tw = head->tw; 1123 1124 /* 1125 * Call the corresponding handle_td routine 1126 */ 1127 (*tw->tw_handle_td)(uhcip, head); 1128 1129 /* restart at the beginning again */ 1130 head = uhcip->uhci_outst_tds_head; 1131 } else { 1132 head = head->outst_td_next; 1133 } 1134 } 1135 } 1136 1137 1138 /* 1139 * uhci_handle_intr_td: 1140 * handles the completed interrupt transfer TD's. 1141 */ 1142 void 1143 uhci_handle_intr_td(uhci_state_t *uhcip, uhci_td_t *td) 1144 { 1145 usb_req_attrs_t attrs; 1146 uint_t bytes_xfered; 1147 usb_cr_t usb_err; 1148 uhci_trans_wrapper_t *tw = td->tw; 1149 uhci_pipe_private_t *pp = tw->tw_pipe_private; 1150 usb_intr_req_t *intr_reqp = 1151 (usb_intr_req_t *)tw->tw_curr_xfer_reqp; 1152 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1153 1154 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1155 "uhci_handle_intr_td: intr_reqp = 0x%p", (void *)intr_reqp); 1156 1157 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 1158 1159 /* set tw->tw_claim flag, so that nobody else works on this td. */ 1160 tw->tw_claim = UHCI_INTR_HDLR_CLAIMED; 1161 1162 /* Interrupt OUT */ 1163 if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_OUT) { 1164 1165 /* process errors first */ 1166 usb_err = uhci_parse_td_error(uhcip, pp, td); 1167 1168 /* get the actual xfered data size */ 1169 bytes_xfered = GetTD_alen(uhcip, td); 1170 1171 /* check data underrun error */ 1172 if ((usb_err == USB_CR_OK) && (bytes_xfered != 1173 GetTD_mlen(uhcip, td))) { 1174 1175 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1176 uhcip->uhci_log_hdl, "uhci_handle_intr_td:" 1177 " Intr out pipe, data underrun occurred"); 1178 1179 usb_err = USB_CR_DATA_UNDERRUN; 1180 1181 } 1182 1183 bytes_xfered = (bytes_xfered == ZERO_LENGTH) ? 1184 0 : bytes_xfered+1; 1185 tw->tw_bytes_xfered += bytes_xfered; 1186 uhci_do_byte_stats(uhcip, tw->tw_bytes_xfered, 1187 ph->p_ep.bmAttributes, ph->p_ep.bEndpointAddress); 1188 1189 1190 /* 1191 * If error occurred or all data xfered, delete the current td, 1192 * free tw, do the callback. Otherwise wait for the next td. 1193 */ 1194 if (usb_err != USB_CR_OK) { 1195 1196 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1197 "uhci_handle_intr_td: Intr out pipe error"); 1198 1199 /* update the element pointer */ 1200 SetQH32(uhcip, pp->pp_qh->element_ptr, GetTD32( 1201 uhcip, tw->tw_hctd_tail->link_ptr)); 1202 1203 1204 } else if (tw->tw_bytes_xfered == tw->tw_length) { 1205 1206 /* all data xfered */ 1207 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1208 "uhci_handle_intr_td: Intr out pipe," 1209 " all data xfered"); 1210 1211 } else { 1212 1213 /* remove the current td and wait for the next one. */ 1214 uhci_delete_td(uhcip, td); 1215 tw->tw_claim = UHCI_NOT_CLAIMED; 1216 1217 return; 1218 } 1219 1220 uhci_delete_td(uhcip, td); 1221 uhci_hcdi_callback(uhcip, pp, ph, tw, usb_err); 1222 uhci_deallocate_tw(uhcip, tw->tw_pipe_private, tw); 1223 1224 return; 1225 } 1226 1227 /* Interrupt IN */ 1228 1229 /* Get the actual received data size */ 1230 tw->tw_bytes_xfered = GetTD_alen(uhcip, td); 1231 if (tw->tw_bytes_xfered == ZERO_LENGTH) { 1232 tw->tw_bytes_xfered = 0; 1233 } else { 1234 tw->tw_bytes_xfered++; 1235 } 1236 1237 /* process errors first */ 1238 if (GetTD_status(uhcip, td) & TD_STATUS_MASK) { 1239 SetQH32(uhcip, pp->pp_qh->element_ptr, 1240 GetTD32(uhcip, td->link_ptr)); 1241 1242 uhci_handle_intr_td_errors(uhcip, td, tw, pp); 1243 1244 return; 1245 } 1246 1247 /* 1248 * Check for data underruns. 1249 * For data underrun case, the host controller does not update 1250 * element pointer. So, we update here. 1251 */ 1252 if (GetTD_alen(uhcip, td) != GetTD_mlen(uhcip, td)) { 1253 SetQH32(uhcip, pp->pp_qh->element_ptr, 1254 GetTD32(uhcip, td->link_ptr)); 1255 } 1256 1257 /* 1258 * Call uhci_sendup_td_message to send message upstream. 1259 * The function uhci_sendup_td_message returns USB_NO_RESOURCES 1260 * if allocb fails and also sends error message to upstream by 1261 * calling USBA callback function. Under error conditions just 1262 * drop the current message. 1263 */ 1264 1265 /* Get the interrupt xfer attributes */ 1266 attrs = intr_reqp->intr_attributes; 1267 1268 /* 1269 * Check usb flag whether USB_FLAGS_ONE_XFER flag is set 1270 * and if so, free duplicate request. 1271 */ 1272 if (attrs & USB_ATTRS_ONE_XFER) { 1273 uhci_handle_one_xfer_completion(uhcip, USB_CR_OK, td); 1274 1275 return; 1276 } 1277 1278 /* save it temporarily */ 1279 if (tw->tw_bytes_xfered != 0) { 1280 uhci_sendup_td_message(uhcip, USB_CR_OK, tw); 1281 } 1282 1283 /* Clear the tw->tw_claim flag */ 1284 tw->tw_claim = UHCI_NOT_CLAIMED; 1285 1286 uhci_delete_td(uhcip, td); 1287 1288 /* allocate another interrupt periodic resource */ 1289 if (pp->pp_state == UHCI_PIPE_STATE_ACTIVE) { 1290 if (uhci_allocate_periodic_in_resource(uhcip, pp, tw, 0) != 1291 USB_SUCCESS) { 1292 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1293 "uhci_insert_intr_req: Interrupt request structure" 1294 "allocation failed"); 1295 1296 uhci_hcdi_callback(uhcip, pp, ph, 1297 tw, USB_CR_NO_RESOURCES); 1298 1299 return; 1300 } 1301 1302 /* Insert another interrupt TD */ 1303 if (uhci_insert_hc_td(uhcip, 0, 1304 tw->tw_length, pp, tw, PID_IN, attrs) != USB_SUCCESS) { 1305 1306 uhci_deallocate_periodic_in_resource(uhcip, pp, tw); 1307 1308 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1309 "uhci_handle_intr_td: TD exhausted"); 1310 1311 uhci_hcdi_callback(uhcip, pp, ph, 1312 tw, USB_CR_NO_RESOURCES); 1313 } 1314 } 1315 } 1316 1317 1318 /* 1319 * uhci_sendup_td_message: 1320 * 1321 * Get a message block and send the received message upstream. 1322 */ 1323 void 1324 uhci_sendup_td_message( 1325 uhci_state_t *uhcip, 1326 usb_cr_t usb_err, 1327 uhci_trans_wrapper_t *tw) 1328 { 1329 mblk_t *mp = NULL; 1330 size_t length = 0; 1331 size_t skip_len = 0; 1332 uchar_t *buf; 1333 usb_opaque_t curr_xfer_reqp = tw->tw_curr_xfer_reqp; 1334 uhci_pipe_private_t *pp = tw->tw_pipe_private; 1335 usb_ep_descr_t *ept = &pp->pp_pipe_handle->p_ep; 1336 1337 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 1338 1339 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1340 "uhci_sendup_td_message: bytes transferred=0x%x, " 1341 "bytes pending=0x%x", 1342 tw->tw_bytes_xfered, tw->tw_bytes_pending); 1343 1344 length = tw->tw_bytes_xfered; 1345 1346 switch (UHCI_XFER_TYPE(ept)) { 1347 case USB_EP_ATTR_CONTROL: 1348 skip_len = UHCI_CTRL_EPT_MAX_SIZE; /* length to skip */ 1349 mp = ((usb_ctrl_req_t *)curr_xfer_reqp)->ctrl_data; 1350 break; 1351 case USB_EP_ATTR_INTR: 1352 mp = ((usb_intr_req_t *)curr_xfer_reqp)->intr_data; 1353 break; 1354 case USB_EP_ATTR_BULK: 1355 mp = ((usb_bulk_req_t *)curr_xfer_reqp)->bulk_data; 1356 break; 1357 case USB_EP_ATTR_ISOCH: 1358 length = tw->tw_length; 1359 mp = ((usb_isoc_req_t *)curr_xfer_reqp)->isoc_data; 1360 break; 1361 default: 1362 break; 1363 } 1364 1365 /* Copy the data into the mblk_t */ 1366 buf = (uchar_t *)tw->tw_buf + skip_len; 1367 1368 ASSERT(mp != NULL); 1369 1370 /* 1371 * Update kstat byte counts 1372 * The control endpoints don't have direction bits so in 1373 * order for control stats to be counted correctly an IN 1374 * bit must be faked on a control read. 1375 */ 1376 uhci_do_byte_stats(uhcip, length, ept->bmAttributes, 1377 (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_CONTROL) ? 1378 USB_EP_DIR_IN : ept->bEndpointAddress); 1379 1380 if (length) { 1381 int rval, i; 1382 uchar_t *p = mp->b_rptr; 1383 1384 if (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_ISOCH) { 1385 /* Deal with isoc data by packets */ 1386 for (i = 0; i < tw->tw_ncookies; i++) { 1387 rval = ddi_dma_sync( 1388 tw->tw_isoc_bufs[i].dma_handle, 0, 1389 tw->tw_isoc_bufs[i].length, 1390 DDI_DMA_SYNC_FORCPU); 1391 ASSERT(rval == DDI_SUCCESS); 1392 1393 ddi_rep_get8(tw->tw_isoc_bufs[i].mem_handle, 1394 p, (uint8_t *)tw->tw_isoc_bufs[i].buf_addr, 1395 tw->tw_isoc_bufs[i].length, 1396 DDI_DEV_AUTOINCR); 1397 p += tw->tw_isoc_bufs[i].length; 1398 } 1399 } else { 1400 /* Sync the streaming buffer */ 1401 rval = ddi_dma_sync(tw->tw_dmahandle, 0, 1402 (skip_len + length), DDI_DMA_SYNC_FORCPU); 1403 ASSERT(rval == DDI_SUCCESS); 1404 1405 /* Copy the data into the message */ 1406 ddi_rep_get8(tw->tw_accesshandle, 1407 mp->b_rptr, buf, length, DDI_DEV_AUTOINCR); 1408 } 1409 1410 /* Increment the write pointer */ 1411 mp->b_wptr += length; 1412 } else { 1413 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1414 "uhci_sendup_td_message: Zero length packet"); 1415 } 1416 1417 /* Do the callback */ 1418 uhci_hcdi_callback(uhcip, pp, pp->pp_pipe_handle, tw, usb_err); 1419 } 1420 1421 1422 /* 1423 * uhci_handle_ctrl_td: 1424 * Handle a control Transfer Descriptor (TD). 1425 */ 1426 void 1427 uhci_handle_ctrl_td(uhci_state_t *uhcip, uhci_td_t *td) 1428 { 1429 ushort_t direction; 1430 ushort_t bytes_for_xfer; 1431 ushort_t bytes_xfered; 1432 ushort_t MaxPacketSize; 1433 usb_cr_t error; 1434 uhci_trans_wrapper_t *tw = td->tw; 1435 uhci_pipe_private_t *pp = tw->tw_pipe_private; 1436 usba_pipe_handle_data_t *usb_pp = pp->pp_pipe_handle; 1437 usb_ep_descr_t *eptd = &usb_pp->p_ep; 1438 usb_ctrl_req_t *reqp = (usb_ctrl_req_t *)tw->tw_curr_xfer_reqp; 1439 1440 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1441 "uhci_handle_ctrl_td: pp = 0x%p tw = 0x%p td = 0x%p " 1442 "state = 0x%x len = 0x%lx", (void *)pp, (void *)tw, 1443 (void *)td, tw->tw_ctrl_state, tw->tw_length); 1444 1445 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 1446 1447 error = uhci_parse_td_error(uhcip, pp, td); 1448 1449 /* 1450 * In case of control transfers, the device can send NAK when it 1451 * is busy. If a NAK is received, then send the status TD again. 1452 */ 1453 if (error != USB_CR_OK) { 1454 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1455 "uhci_handle_ctrl_td: Ctrl cmd failed, error = %x", error); 1456 1457 SetQH32(uhcip, pp->pp_qh->element_ptr, 1458 GetTD32(uhcip, td->link_ptr)); 1459 uhci_delete_td(uhcip, td); 1460 1461 /* Return number of bytes xfered */ 1462 if (GetTD_alen(uhcip, td) != ZERO_LENGTH) { 1463 tw->tw_bytes_xfered = GetTD_alen(uhcip, td) + 1; 1464 } 1465 1466 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1467 "uhci_handle_ctrl_td: Bytes transferred = %x", 1468 tw->tw_bytes_xfered); 1469 1470 if ((tw->tw_ctrl_state == DATA) && 1471 (tw->tw_direction == PID_IN)) { 1472 uhci_sendup_td_message(uhcip, error, tw); 1473 } else { 1474 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, error); 1475 1476 uhci_deallocate_tw(uhcip, pp, tw); 1477 } 1478 1479 return; 1480 } 1481 1482 /* 1483 * A control transfer consists of three phases: 1484 * - Setup 1485 * - Data (optional) 1486 * - Status 1487 * 1488 * There is a TD per phase. A TD for a given phase isn't 1489 * enqueued until the previous phase is finished. 1490 */ 1491 switch (tw->tw_ctrl_state) { 1492 case SETUP: 1493 /* 1494 * Enqueue either the data or the status 1495 * phase depending on the length. 1496 */ 1497 pp->pp_data_toggle = 1; 1498 uhci_delete_td(uhcip, td); 1499 1500 /* 1501 * If the length is 0, move to the status. 1502 * If length is not 0, then we have some data 1503 * to move on the bus to device either IN or OUT. 1504 */ 1505 if ((tw->tw_length - SETUP_SIZE) == 0) { 1506 /* 1507 * There is no data stage, then 1508 * initiate status phase from the host. 1509 */ 1510 if ((uhci_insert_hc_td(uhcip, 0, 0, pp, tw, PID_IN, 1511 reqp->ctrl_attributes)) != USB_SUCCESS) { 1512 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1513 uhcip->uhci_log_hdl, 1514 "uhci_handle_ctrl_td: No resources"); 1515 1516 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, 1517 USB_CR_NO_RESOURCES); 1518 1519 return; 1520 } 1521 1522 tw->tw_ctrl_state = STATUS; 1523 } else { 1524 uint_t xx; 1525 1526 /* 1527 * Each USB device can send/receive 8/16/32/64 1528 * depending on wMaxPacketSize's implementation. 1529 * We need to insert 'N = Number of byte/ 1530 * MaxpktSize" TD's in the lattice to send/ 1531 * receive the data. Though the USB protocol 1532 * allows to insert more than one TD in the same 1533 * frame, we are inserting only one TD in one 1534 * frame. This is bcos OHCI has seen some problem 1535 * when multiple TD's are inserted at the same time. 1536 */ 1537 tw->tw_length -= UHCI_CTRL_EPT_MAX_SIZE; 1538 MaxPacketSize = eptd->wMaxPacketSize; 1539 1540 /* 1541 * We dont know the maximum packet size that 1542 * the device can handle(MaxPAcketSize=0). 1543 * In that case insert a data phase with 1544 * eight bytes or less. 1545 */ 1546 if (MaxPacketSize == 0) { 1547 xx = (tw->tw_length > 8) ? 8 : tw->tw_length; 1548 } else { 1549 xx = (tw->tw_length > MaxPacketSize) ? 1550 MaxPacketSize : tw->tw_length; 1551 } 1552 1553 tw->tw_tmp = xx; 1554 1555 /* 1556 * Create the TD. If this is an OUT 1557 * transaction, the data is already 1558 * in the buffer of the TW. 1559 * Get first 8 bytes of the command only. 1560 */ 1561 if ((uhci_insert_hc_td(uhcip, 1562 UHCI_CTRL_EPT_MAX_SIZE, xx, 1563 pp, tw, tw->tw_direction, 1564 reqp->ctrl_attributes)) != USB_SUCCESS) { 1565 1566 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1567 uhcip->uhci_log_hdl, 1568 "uhci_handle_ctrl_td: No resources"); 1569 1570 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, 1571 USB_CR_NO_RESOURCES); 1572 1573 return; 1574 } 1575 1576 tw->tw_ctrl_state = DATA; 1577 } 1578 1579 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1580 "Setup complete: pp 0x%p td 0x%p", (void *)pp, (void *)td); 1581 1582 break; 1583 case DATA: 1584 uhci_delete_td(uhcip, td); 1585 1586 MaxPacketSize = eptd->wMaxPacketSize; 1587 1588 /* 1589 * Decrement pending bytes and increment the total 1590 * number bytes transferred by the actual number of bytes 1591 * transferred in this TD. If the number of bytes transferred 1592 * is less than requested, that means an underrun has 1593 * occurred. Set the tw_tmp varible to indicate UNDER run. 1594 */ 1595 bytes_xfered = GetTD_alen(uhcip, td); 1596 if (bytes_xfered == ZERO_LENGTH) { 1597 bytes_xfered = 0; 1598 } else { 1599 bytes_xfered++; 1600 } 1601 1602 tw->tw_bytes_pending -= bytes_xfered; 1603 tw->tw_bytes_xfered += bytes_xfered; 1604 1605 if (bytes_xfered < tw->tw_tmp) { 1606 tw->tw_bytes_pending = 0; 1607 tw->tw_tmp = UHCI_UNDERRUN_OCCURRED; 1608 1609 /* 1610 * Controller does not update the queue head 1611 * element pointer when a data underrun occurs. 1612 */ 1613 SetQH32(uhcip, pp->pp_qh->element_ptr, 1614 GetTD32(uhcip, td->link_ptr)); 1615 } 1616 1617 if (bytes_xfered > tw->tw_tmp) { 1618 tw->tw_bytes_pending = 0; 1619 tw->tw_tmp = UHCI_OVERRUN_OCCURRED; 1620 } 1621 1622 /* 1623 * If no more bytes are pending, insert status 1624 * phase. Otherwise insert data phase. 1625 */ 1626 if (tw->tw_bytes_pending) { 1627 bytes_for_xfer = (tw->tw_bytes_pending > 1628 MaxPacketSize) ? MaxPacketSize : 1629 tw->tw_bytes_pending; 1630 1631 tw->tw_tmp = bytes_for_xfer; 1632 1633 if ((uhci_insert_hc_td(uhcip, 1634 UHCI_CTRL_EPT_MAX_SIZE + tw->tw_bytes_xfered, 1635 bytes_for_xfer, pp, tw, 1636 tw->tw_direction, 1637 reqp->ctrl_attributes)) != USB_SUCCESS) { 1638 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1639 uhcip->uhci_log_hdl, 1640 "uhci_handle_ctrl_td: No TD"); 1641 1642 uhci_hcdi_callback(uhcip, pp, usb_pp, 1643 tw, USB_NO_RESOURCES); 1644 1645 return; 1646 } 1647 1648 tw->tw_ctrl_state = DATA; 1649 1650 break; 1651 } 1652 1653 pp->pp_data_toggle = 1; 1654 direction = (tw->tw_direction == PID_IN) ? PID_OUT : PID_IN; 1655 1656 if ((uhci_insert_hc_td(uhcip, 0, 0, pp, tw, direction, 1657 reqp->ctrl_attributes)) != USB_SUCCESS) { 1658 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1659 "uhci_handle_ctrl_td: TD exhausted"); 1660 1661 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, 1662 USB_NO_RESOURCES); 1663 1664 return; 1665 } 1666 1667 tw->tw_ctrl_state = STATUS; 1668 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1669 "Data complete: pp 0x%p td 0x%p", (void *)pp, (void *)td); 1670 1671 break; 1672 case STATUS: 1673 /* 1674 * Send the data to the client if it is a DATA IN, 1675 * else send just return status for DATA OUT commnads. 1676 * And set the tw_claim flag. 1677 */ 1678 tw->tw_claim = UHCI_INTR_HDLR_CLAIMED; 1679 1680 if ((tw->tw_length != 0) && (tw->tw_direction == PID_IN)) { 1681 usb_req_attrs_t attrs = ((usb_ctrl_req_t *) 1682 tw->tw_curr_xfer_reqp)->ctrl_attributes; 1683 /* 1684 * Call uhci_sendup_td_message to send message 1685 * upstream. The function uhci_sendup_td_message 1686 * returns USB_NO_RESOURCES if allocb fails and 1687 * also sends error message to upstream by calling 1688 * USBA callback function. 1689 * 1690 * Under error conditions just drop the current msg. 1691 */ 1692 if ((tw->tw_tmp == UHCI_UNDERRUN_OCCURRED) && 1693 (!(attrs & USB_ATTRS_SHORT_XFER_OK))) { 1694 error = USB_CR_DATA_UNDERRUN; 1695 } else if (tw->tw_tmp == UHCI_OVERRUN_OCCURRED) { 1696 error = USB_CR_DATA_OVERRUN; 1697 } 1698 uhci_sendup_td_message(uhcip, error, tw); 1699 1700 } else { 1701 uhci_do_byte_stats(uhcip, tw->tw_length, 1702 eptd->bmAttributes, eptd->bEndpointAddress); 1703 1704 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, USB_CR_OK); 1705 } 1706 1707 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1708 "Status complete: pp 0x%p td 0x%p", (void *)pp, (void *)td); 1709 1710 uhci_delete_td(uhcip, td); 1711 uhci_deallocate_tw(uhcip, pp, tw); 1712 1713 break; 1714 default: 1715 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1716 "uhci_handle_ctrl_td: Bad control state"); 1717 1718 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, 1719 USB_CR_UNSPECIFIED_ERR); 1720 } 1721 } 1722 1723 1724 /* 1725 * uhci_handle_intr_td_errors: 1726 * Handles the errors encountered for the interrupt transfers. 1727 */ 1728 static void 1729 uhci_handle_intr_td_errors(uhci_state_t *uhcip, uhci_td_t *td, 1730 uhci_trans_wrapper_t *tw, uhci_pipe_private_t *pp) 1731 { 1732 usb_cr_t usb_err; 1733 usb_intr_req_t *intr_reqp = 1734 (usb_intr_req_t *)tw->tw_curr_xfer_reqp; 1735 1736 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1737 "uhci_handle_intr_td_errors: td = 0x%p tw = 0x%p", 1738 (void *)td, (void *)tw); 1739 1740 usb_err = uhci_parse_td_error(uhcip, pp, td); 1741 1742 if (intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) { 1743 uhci_handle_one_xfer_completion(uhcip, usb_err, td); 1744 1745 return; 1746 } 1747 1748 uhci_delete_td(uhcip, td); 1749 uhci_sendup_td_message(uhcip, usb_err, tw); 1750 uhci_deallocate_tw(uhcip, tw->tw_pipe_private, tw); 1751 } 1752 1753 1754 /* 1755 * uhci_handle_one_xfer_completion: 1756 */ 1757 static void 1758 uhci_handle_one_xfer_completion( 1759 uhci_state_t *uhcip, 1760 usb_cr_t usb_err, 1761 uhci_td_t *td) 1762 { 1763 uhci_trans_wrapper_t *tw = td->tw; 1764 uhci_pipe_private_t *pp = tw->tw_pipe_private; 1765 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1766 usb_intr_req_t *intr_reqp = 1767 (usb_intr_req_t *)tw->tw_curr_xfer_reqp; 1768 1769 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1770 "uhci_handle_one_xfer_completion: td = 0x%p", (void *)td); 1771 1772 ASSERT(intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER); 1773 1774 /* set state to idle */ 1775 pp->pp_state = UHCI_PIPE_STATE_IDLE; 1776 1777 ((usb_intr_req_t *)(pp->pp_client_periodic_in_reqp))-> 1778 intr_data = ((usb_intr_req_t *)(tw->tw_curr_xfer_reqp))->intr_data; 1779 1780 ((usb_intr_req_t *)tw->tw_curr_xfer_reqp)->intr_data = NULL; 1781 1782 /* now free duplicate current request */ 1783 usb_free_intr_req((usb_intr_req_t *)tw->tw_curr_xfer_reqp); 1784 mutex_enter(&ph->p_mutex); 1785 ph->p_req_count--; 1786 mutex_exit(&ph->p_mutex); 1787 1788 /* make client's request the current request */ 1789 tw->tw_curr_xfer_reqp = pp->pp_client_periodic_in_reqp; 1790 pp->pp_client_periodic_in_reqp = NULL; 1791 1792 uhci_sendup_td_message(uhcip, usb_err, tw); 1793 /* Clear the tw->tw_claim flag */ 1794 tw->tw_claim = UHCI_NOT_CLAIMED; 1795 1796 uhci_delete_td(uhcip, td); 1797 uhci_deallocate_tw(uhcip, pp, tw); 1798 } 1799 1800 1801 /* 1802 * uhci_parse_td_error 1803 * Parses the Transfer Descriptors error 1804 */ 1805 usb_cr_t 1806 uhci_parse_td_error(uhci_state_t *uhcip, uhci_pipe_private_t *pp, uhci_td_t *td) 1807 { 1808 uint_t status; 1809 1810 status = GetTD_status(uhcip, td) & TD_STATUS_MASK; 1811 1812 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1813 "uhci_parse_td_error: status_bits=0x%x", status); 1814 1815 if (UHCI_XFER_TYPE(&pp->pp_pipe_handle->p_ep) == USB_EP_ATTR_ISOCH) { 1816 1817 return (USB_CR_OK); 1818 } 1819 1820 if (!status) { 1821 1822 return (USB_CR_OK); 1823 } 1824 1825 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1826 "uhci_parse_td_error: status_bits=0x%x", status); 1827 1828 1829 if (status & UHCI_TD_BITSTUFF_ERR) { 1830 1831 return (USB_CR_BITSTUFFING); 1832 } 1833 1834 if (status & UHCI_TD_CRC_TIMEOUT) { 1835 pp->pp_data_toggle = GetTD_dtogg(uhcip, td); 1836 1837 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1838 "uhci_parse_td_error: timeout & data toggle reset; " 1839 "data toggle: %x", pp->pp_data_toggle); 1840 1841 return ((GetTD_PID(uhcip, td) == PID_IN) ? USB_CR_DEV_NOT_RESP : 1842 USB_CR_TIMEOUT); 1843 } 1844 1845 if (status & UHCI_TD_BABBLE_ERR) { 1846 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1847 "babble error"); 1848 1849 return (USB_CR_UNSPECIFIED_ERR); 1850 } 1851 1852 if (status & UHCI_TD_DATA_BUFFER_ERR) { 1853 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1854 "buffer error"); 1855 1856 return ((GetTD_PID(uhcip, td) == PID_IN) ? 1857 USB_CR_BUFFER_OVERRUN : USB_CR_BUFFER_UNDERRUN); 1858 } 1859 1860 if (status & UHCI_TD_STALLED) { 1861 pp->pp_data_toggle = 0; 1862 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1863 "uhci_parse_td_error: stall; data toggle reset; " 1864 "data toggle: %x", pp->pp_data_toggle); 1865 1866 return (USB_CR_STALL); 1867 } 1868 1869 if (status) { 1870 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1871 "unspecified error=0x%x", status); 1872 } 1873 1874 return (USB_CR_OK); 1875 } 1876 1877 1878 static dev_info_t * 1879 uhci_get_dip(dev_t dev) 1880 { 1881 int instance = UHCI_UNIT(dev); 1882 uhci_state_t *uhcip = ddi_get_soft_state(uhci_statep, instance); 1883 1884 return (uhcip ? uhcip->uhci_dip : NULL); 1885 } 1886 1887 1888 /* 1889 * cb_ops entry points 1890 */ 1891 static int 1892 uhci_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1893 { 1894 dev_info_t *dip = uhci_get_dip(*devp); 1895 1896 return (usba_hubdi_open(dip, devp, flags, otyp, credp)); 1897 } 1898 1899 1900 static int 1901 uhci_close(dev_t dev, int flag, int otyp, cred_t *credp) 1902 { 1903 dev_info_t *dip = uhci_get_dip(dev); 1904 1905 return (usba_hubdi_close(dip, dev, flag, otyp, credp)); 1906 } 1907 1908 1909 static int 1910 uhci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 1911 cred_t *credp, int *rvalp) 1912 { 1913 dev_info_t *dip = uhci_get_dip(dev); 1914 1915 return (usba_hubdi_ioctl(dip, dev, cmd, arg, mode, credp, rvalp)); 1916 } 1917