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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /* 28 * EHCI Host Controller Driver (EHCI) 29 * 30 * The EHCI driver is a software driver which interfaces to the Universal 31 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to 32 * the Host Controller is defined by the EHCI Host Controller Interface. 33 * 34 * This file contains code for Auto-configuration and HCDI entry points. 35 * 36 * NOTE: 37 * 38 * Currently EHCI driver does not support the following features 39 * 40 * - Alternate QTD for short xfer condition is only used in Bulk xfers. 41 * - Frame Span Traversal Nodes (FSTN). 42 * - Bandwidth allocation scheme needs to be updated for FSTN and USB2.0 43 * or High speed hub with multiple TT implementation. Currently bandwidth 44 * allocation scheme assumes one TT per USB2.0 or High speed hub. 45 * - 64 bit addressing capability. 46 * - Programmable periodic frame list size like 256, 512, 1024. 47 * It supports only 1024 periodic frame list size. 48 */ 49 50 #include <sys/usb/hcd/ehci/ehcid.h> 51 #include <sys/usb/hcd/ehci/ehci_xfer.h> 52 #include <sys/usb/hcd/ehci/ehci_intr.h> 53 #include <sys/usb/hcd/ehci/ehci_util.h> 54 #include <sys/usb/hcd/ehci/ehci_isoch.h> 55 56 /* Pointer to the state structure */ 57 void *ehci_statep; 58 59 /* Number of instances */ 60 #define EHCI_INSTS 1 61 62 /* Debugging information */ 63 uint_t ehci_errmask = (uint_t)PRINT_MASK_ALL; 64 uint_t ehci_errlevel = USB_LOG_L2; 65 uint_t ehci_instance_debug = (uint_t)-1; 66 67 /* 68 * Tunable to ensure host controller goes off even if a keyboard is attached. 69 */ 70 int force_ehci_off = 1; 71 72 /* Enable all workarounds for VIA VT62x2 */ 73 uint_t ehci_vt62x2_workaround = EHCI_VIA_WORKAROUNDS; 74 75 /* 76 * EHCI Auto-configuration entry points. 77 * 78 * Device operations (dev_ops) entries function prototypes. 79 * 80 * We use the hub cbops since all nexus ioctl operations defined so far will 81 * be executed by the root hub. The following are the Host Controller Driver 82 * (HCD) entry points. 83 * 84 * the open/close/ioctl functions call the corresponding usba_hubdi_* 85 * calls after looking up the dip thru the dev_t. 86 */ 87 static int ehci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 88 static int ehci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 89 static int ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd); 90 static int ehci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 91 void *arg, void **result); 92 93 static int ehci_open(dev_t *devp, int flags, int otyp, cred_t *credp); 94 static int ehci_close(dev_t dev, int flag, int otyp, cred_t *credp); 95 static int ehci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 96 cred_t *credp, int *rvalp); 97 98 int usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level); 99 100 static struct cb_ops ehci_cb_ops = { 101 ehci_open, /* EHCI */ 102 ehci_close, /* Close */ 103 nodev, /* Strategy */ 104 nodev, /* Print */ 105 nodev, /* Dump */ 106 nodev, /* Read */ 107 nodev, /* Write */ 108 ehci_ioctl, /* Ioctl */ 109 nodev, /* Devmap */ 110 nodev, /* Mmap */ 111 nodev, /* Segmap */ 112 nochpoll, /* Poll */ 113 ddi_prop_op, /* cb_prop_op */ 114 NULL, /* Streamtab */ 115 D_NEW | D_MP | D_HOTPLUG /* Driver compatibility flag */ 116 }; 117 118 static struct dev_ops ehci_ops = { 119 DEVO_REV, /* Devo_rev */ 120 0, /* Refcnt */ 121 ehci_info, /* Info */ 122 nulldev, /* Identify */ 123 nulldev, /* Probe */ 124 ehci_attach, /* Attach */ 125 ehci_detach, /* Detach */ 126 ehci_reset, /* Reset */ 127 &ehci_cb_ops, /* Driver operations */ 128 &usba_hubdi_busops, /* Bus operations */ 129 usba_hubdi_root_hub_power /* Power */ 130 }; 131 132 /* 133 * The USBA library must be loaded for this driver. 134 */ 135 static struct modldrv modldrv = { 136 &mod_driverops, /* Type of module. This one is a driver */ 137 "USB EHCI Driver", /* Name of the module. */ 138 &ehci_ops, /* Driver ops */ 139 }; 140 141 static struct modlinkage modlinkage = { 142 MODREV_1, (void *)&modldrv, NULL 143 }; 144 145 146 int 147 _init(void) 148 { 149 int error; 150 151 /* Initialize the soft state structures */ 152 if ((error = ddi_soft_state_init(&ehci_statep, sizeof (ehci_state_t), 153 EHCI_INSTS)) != 0) { 154 return (error); 155 } 156 157 /* Install the loadable module */ 158 if ((error = mod_install(&modlinkage)) != 0) { 159 ddi_soft_state_fini(&ehci_statep); 160 } 161 162 return (error); 163 } 164 165 166 int 167 _info(struct modinfo *modinfop) 168 { 169 return (mod_info(&modlinkage, modinfop)); 170 } 171 172 173 int 174 _fini(void) 175 { 176 int error; 177 178 if ((error = mod_remove(&modlinkage)) == 0) { 179 180 /* Release per module resources */ 181 ddi_soft_state_fini(&ehci_statep); 182 } 183 184 return (error); 185 } 186 187 188 /* 189 * EHCI Auto configuration entry points. 190 */ 191 192 /* 193 * ehci_attach: 194 * 195 * Description: Attach entry point is called by the Kernel. 196 * Allocates resources for each EHCI host controller instance. 197 * Initializes the EHCI Host Controller. 198 * 199 * Return : DDI_SUCCESS / DDI_FAILURE. 200 */ 201 static int 202 ehci_attach(dev_info_t *dip, 203 ddi_attach_cmd_t cmd) 204 { 205 int instance; 206 ehci_state_t *ehcip = NULL; 207 usba_hcdi_register_args_t hcdi_args; 208 209 switch (cmd) { 210 case DDI_ATTACH: 211 break; 212 case DDI_RESUME: 213 ehcip = ehci_obtain_state(dip); 214 215 return (ehci_cpr_resume(ehcip)); 216 default: 217 return (DDI_FAILURE); 218 } 219 220 /* Get the instance and create soft state */ 221 instance = ddi_get_instance(dip); 222 223 if (ddi_soft_state_zalloc(ehci_statep, instance) != 0) { 224 225 return (DDI_FAILURE); 226 } 227 228 ehcip = ddi_get_soft_state(ehci_statep, instance); 229 if (ehcip == NULL) { 230 231 return (DDI_FAILURE); 232 } 233 234 ehcip->ehci_flags = EHCI_ATTACH; 235 236 ehcip->ehci_log_hdl = usb_alloc_log_hdl(dip, "ehci", &ehci_errlevel, 237 &ehci_errmask, &ehci_instance_debug, 0); 238 239 ehcip->ehci_flags |= EHCI_ZALLOC; 240 241 /* Set host controller soft state to initialization */ 242 ehcip->ehci_hc_soft_state = EHCI_CTLR_INIT_STATE; 243 244 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, 245 "ehcip = 0x%p", (void *)ehcip); 246 247 /* Save the dip and instance */ 248 ehcip->ehci_dip = dip; 249 ehcip->ehci_instance = instance; 250 251 /* Map the registers */ 252 if (ehci_map_regs(ehcip) != DDI_SUCCESS) { 253 (void) ehci_cleanup(ehcip); 254 255 return (DDI_FAILURE); 256 } 257 258 /* Get the ehci chip vendor and device id */ 259 ehcip->ehci_vendor_id = pci_config_get16( 260 ehcip->ehci_config_handle, PCI_CONF_VENID); 261 ehcip->ehci_device_id = pci_config_get16( 262 ehcip->ehci_config_handle, PCI_CONF_DEVID); 263 ehcip->ehci_rev_id = pci_config_get8( 264 ehcip->ehci_config_handle, PCI_CONF_REVID); 265 266 /* Initialize the DMA attributes */ 267 ehci_set_dma_attributes(ehcip); 268 269 /* Initialize kstat structures */ 270 ehci_create_stats(ehcip); 271 272 /* Create the qtd and qh pools */ 273 if (ehci_allocate_pools(ehcip) != DDI_SUCCESS) { 274 (void) ehci_cleanup(ehcip); 275 276 return (DDI_FAILURE); 277 } 278 279 /* Initialize the isochronous resources */ 280 if (ehci_isoc_init(ehcip) != DDI_SUCCESS) { 281 (void) ehci_cleanup(ehcip); 282 283 return (DDI_FAILURE); 284 } 285 286 /* Register interrupts */ 287 if (ehci_register_intrs_and_init_mutex(ehcip) != DDI_SUCCESS) { 288 (void) ehci_cleanup(ehcip); 289 290 return (DDI_FAILURE); 291 } 292 293 mutex_enter(&ehcip->ehci_int_mutex); 294 295 /* Initialize the controller */ 296 if (ehci_init_ctlr(ehcip, EHCI_NORMAL_INITIALIZATION) != DDI_SUCCESS) { 297 mutex_exit(&ehcip->ehci_int_mutex); 298 (void) ehci_cleanup(ehcip); 299 300 return (DDI_FAILURE); 301 } 302 303 /* 304 * At this point, the hardware will be okay. 305 * Initialize the usba_hcdi structure 306 */ 307 ehcip->ehci_hcdi_ops = ehci_alloc_hcdi_ops(ehcip); 308 309 mutex_exit(&ehcip->ehci_int_mutex); 310 311 /* 312 * Make this HCD instance known to USBA 313 * (dma_attr must be passed for USBA busctl's) 314 */ 315 hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION; 316 hcdi_args.usba_hcdi_register_dip = dip; 317 hcdi_args.usba_hcdi_register_ops = ehcip->ehci_hcdi_ops; 318 hcdi_args.usba_hcdi_register_dma_attr = &ehcip->ehci_dma_attr; 319 320 /* 321 * Priority and iblock_cookie are one and the same 322 * (However, retaining hcdi_soft_iblock_cookie for now 323 * assigning it w/ priority. In future all iblock_cookie 324 * could just go) 325 */ 326 hcdi_args.usba_hcdi_register_iblock_cookie = 327 (ddi_iblock_cookie_t)(uintptr_t)ehcip->ehci_intr_pri; 328 329 if (usba_hcdi_register(&hcdi_args, 0) != DDI_SUCCESS) { 330 (void) ehci_cleanup(ehcip); 331 332 return (DDI_FAILURE); 333 } 334 335 ehcip->ehci_flags |= EHCI_USBAREG; 336 337 mutex_enter(&ehcip->ehci_int_mutex); 338 339 if ((ehci_init_root_hub(ehcip)) != USB_SUCCESS) { 340 mutex_exit(&ehcip->ehci_int_mutex); 341 (void) ehci_cleanup(ehcip); 342 343 return (DDI_FAILURE); 344 } 345 346 mutex_exit(&ehcip->ehci_int_mutex); 347 348 /* Finally load the root hub driver */ 349 if (ehci_load_root_hub_driver(ehcip) != USB_SUCCESS) { 350 (void) ehci_cleanup(ehcip); 351 352 return (DDI_FAILURE); 353 } 354 ehcip->ehci_flags |= EHCI_RHREG; 355 356 /* Display information in the banner */ 357 ddi_report_dev(dip); 358 359 mutex_enter(&ehcip->ehci_int_mutex); 360 361 /* Reset the ehci initialization flag */ 362 ehcip->ehci_flags &= ~EHCI_ATTACH; 363 364 /* Print the Host Control's Operational registers */ 365 ehci_print_caps(ehcip); 366 ehci_print_regs(ehcip); 367 368 (void) pci_report_pmcap(dip, PCI_PM_IDLESPEED, (void *)4000); 369 370 mutex_exit(&ehcip->ehci_int_mutex); 371 372 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, 373 "ehci_attach: dip = 0x%p done", (void *)dip); 374 375 return (DDI_SUCCESS); 376 } 377 378 379 /* 380 * ehci_detach: 381 * 382 * Description: Detach entry point is called by the Kernel. 383 * Deallocates all resource allocated. 384 * Unregisters the interrupt handler. 385 * 386 * Return : DDI_SUCCESS / DDI_FAILURE 387 */ 388 int 389 ehci_detach(dev_info_t *dip, 390 ddi_detach_cmd_t cmd) 391 { 392 ehci_state_t *ehcip = ehci_obtain_state(dip); 393 394 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, "ehci_detach:"); 395 396 switch (cmd) { 397 case DDI_DETACH: 398 399 return (ehci_cleanup(ehcip)); 400 case DDI_SUSPEND: 401 402 return (ehci_cpr_suspend(ehcip)); 403 default: 404 405 return (DDI_FAILURE); 406 } 407 } 408 409 /* 410 * ehci_reset: 411 * 412 * Description: Reset entry point - called by the Kernel 413 * on the way down. 414 * Toshiba Tecra laptop has been observed to hang 415 * on soft reboot. The resetting ehci on the way 416 * down solves the problem. 417 * 418 * Return : DDI_SUCCESS / DDI_FAILURE 419 */ 420 /* ARGSUSED */ 421 static int 422 ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd) 423 { 424 #if defined(__sparc) 425 /* 426 * Don't reset the host controller on SPARC, for OBP needs Solaris 427 * to continue to provide keyboard support after shutdown of SPARC, 428 * or the keyboard connected to a USB 2.0 port will not work after 429 * that. The incomplete reset problem on Toshiba Tecra laptop is 430 * specific to Tecra laptop or BIOS, not present on SPARC. The SPARC 431 * OBP guarantees good reset behavior during startup. 432 */ 433 return (DDI_SUCCESS); 434 #else 435 ehci_state_t *ehcip = ehci_obtain_state(dip); 436 437 mutex_enter(&ehcip->ehci_int_mutex); 438 439 /* 440 * To reset the host controller, the HCRESET bit should be set to one. 441 * Software should not set this bit to a one when the HCHalted bit in 442 * the USBSTS register is a zero. Attempting to reset an actively 443 * running host controller will result in undefined behavior. 444 * see EHCI SPEC. for more information. 445 */ 446 if (!(Get_OpReg(ehci_status) & EHCI_STS_HOST_CTRL_HALTED)) { 447 448 /* Stop the EHCI host controller */ 449 Set_OpReg(ehci_command, 450 Get_OpReg(ehci_command) & ~EHCI_CMD_HOST_CTRL_RUN); 451 /* 452 * When this bit is set to 0, the Host Controller completes the 453 * current and any actively pipelined transactions on the USB 454 * and then halts. The Host Controller must halt within 16 455 * micro-frames after software clears the Run bit. 456 * The HC Halted bit in the status register indicates when the 457 * Host Controller has finished its pending pipelined 458 * transactions and has entered the stopped state. 459 */ 460 drv_usecwait(EHCI_RESET_TIMEWAIT); 461 } 462 463 /* Reset the EHCI host controller */ 464 Set_OpReg(ehci_command, 465 Get_OpReg(ehci_command) | EHCI_CMD_HOST_CTRL_RESET); 466 467 mutex_exit(&ehcip->ehci_int_mutex); 468 469 return (DDI_SUCCESS); 470 #endif 471 } 472 473 /* 474 * ehci_info: 475 */ 476 /* ARGSUSED */ 477 static int 478 ehci_info(dev_info_t *dip, 479 ddi_info_cmd_t infocmd, 480 void *arg, 481 void **result) 482 { 483 dev_t dev; 484 ehci_state_t *ehcip; 485 int instance; 486 int error = DDI_FAILURE; 487 488 switch (infocmd) { 489 case DDI_INFO_DEVT2DEVINFO: 490 dev = (dev_t)arg; 491 instance = EHCI_UNIT(dev); 492 ehcip = ddi_get_soft_state(ehci_statep, instance); 493 if (ehcip != NULL) { 494 *result = (void *)ehcip->ehci_dip; 495 if (*result != NULL) { 496 error = DDI_SUCCESS; 497 } 498 } else { 499 *result = NULL; 500 } 501 502 break; 503 case DDI_INFO_DEVT2INSTANCE: 504 dev = (dev_t)arg; 505 instance = EHCI_UNIT(dev); 506 *result = (void *)(uintptr_t)instance; 507 error = DDI_SUCCESS; 508 break; 509 default: 510 break; 511 } 512 513 return (error); 514 } 515 516 517 /* 518 * EHCI CB_OPS entry points. 519 */ 520 static dev_info_t * 521 ehci_get_dip(dev_t dev) 522 { 523 int instance = EHCI_UNIT(dev); 524 ehci_state_t *ehcip = ddi_get_soft_state(ehci_statep, instance); 525 526 if (ehcip) { 527 528 return (ehcip->ehci_dip); 529 } else { 530 531 return (NULL); 532 } 533 } 534 535 536 static int 537 ehci_open(dev_t *devp, 538 int flags, 539 int otyp, 540 cred_t *credp) 541 { 542 dev_info_t *dip = ehci_get_dip(*devp); 543 544 return (usba_hubdi_open(dip, devp, flags, otyp, credp)); 545 } 546 547 548 static int 549 ehci_close(dev_t dev, 550 int flag, 551 int otyp, 552 cred_t *credp) 553 { 554 dev_info_t *dip = ehci_get_dip(dev); 555 556 return (usba_hubdi_close(dip, dev, flag, otyp, credp)); 557 } 558 559 560 static int 561 ehci_ioctl(dev_t dev, 562 int cmd, 563 intptr_t arg, 564 int mode, 565 cred_t *credp, 566 int *rvalp) 567 { 568 dev_info_t *dip = ehci_get_dip(dev); 569 570 return (usba_hubdi_ioctl(dip, 571 dev, cmd, arg, mode, credp, rvalp)); 572 } 573 574 /* 575 * EHCI Interrupt Handler entry point. 576 */ 577 578 /* 579 * ehci_intr: 580 * 581 * EHCI (EHCI) interrupt handling routine. 582 */ 583 uint_t 584 ehci_intr(caddr_t arg1, caddr_t arg2) 585 { 586 uint_t intr; 587 ehci_state_t *ehcip = (ehci_state_t *)arg1; 588 589 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 590 "ehci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p", 591 (void *)arg1, (void *)arg2); 592 593 /* Get the ehci global mutex */ 594 mutex_enter(&ehcip->ehci_int_mutex); 595 596 /* Any interrupt is not handled for the suspended device. */ 597 if (ehcip->ehci_hc_soft_state == EHCI_CTLR_SUSPEND_STATE) { 598 mutex_exit(&ehcip->ehci_int_mutex); 599 600 return (DDI_INTR_UNCLAIMED); 601 } 602 603 /* 604 * Now process the actual ehci interrupt events that caused 605 * invocation of this ehci interrupt handler. 606 */ 607 intr = (Get_OpReg(ehci_status) & Get_OpReg(ehci_interrupt)); 608 609 /* Update kstat values */ 610 ehci_do_intrs_stats(ehcip, intr); 611 612 /* 613 * We could have gotten a spurious interrupts. If so, do not 614 * claim it. This is quite possible on some architectures 615 * where more than one PCI slots share the IRQs. If so, the 616 * associated driver's interrupt routine may get called even 617 * if the interrupt is not meant for them. 618 * 619 * By unclaiming the interrupt, the other driver gets chance 620 * to service its interrupt. 621 */ 622 if (!intr) { 623 mutex_exit(&ehcip->ehci_int_mutex); 624 625 return (DDI_INTR_UNCLAIMED); 626 } 627 628 /* Acknowledge the interrupt */ 629 Set_OpReg(ehci_status, intr); 630 631 if (ehcip->ehci_hc_soft_state == EHCI_CTLR_ERROR_STATE) { 632 mutex_exit(&ehcip->ehci_int_mutex); 633 634 return (DDI_INTR_CLAIMED); 635 } 636 637 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 638 "Interrupt status 0x%x", intr); 639 640 /* 641 * If necessary broadcast that an interrupt has occured. This 642 * is only necessary during controller init. 643 */ 644 if (ehcip->ehci_flags & EHCI_CV_INTR) { 645 ehcip->ehci_flags &= ~EHCI_CV_INTR; 646 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv); 647 } 648 649 /* Check for Frame List Rollover */ 650 if (intr & EHCI_INTR_FRAME_LIST_ROLLOVER) { 651 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 652 "ehci_intr: Frame List Rollover"); 653 654 ehci_handle_frame_list_rollover(ehcip); 655 656 /* VIA VT6202 looses EHCI_INTR_USB interrupts, workaround. */ 657 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) && 658 (ehci_vt62x2_workaround & EHCI_VIA_LOST_INTERRUPTS)) { 659 ehcip->ehci_missed_intr_sts |= EHCI_INTR_USB; 660 } 661 } 662 663 /* Check for Advance on Asynchronous Schedule */ 664 if (intr & EHCI_INTR_ASYNC_ADVANCE) { 665 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 666 "ehci_intr: Asynchronous Schedule Advance Notification"); 667 668 /* Disable async list advance interrupt */ 669 Set_OpReg(ehci_interrupt, 670 (Get_OpReg(ehci_interrupt) & ~EHCI_INTR_ASYNC_ADVANCE)); 671 672 /* 673 * Call cv_broadcast on every this interrupt to wakeup 674 * all the threads that are waiting the async list advance 675 * event. 676 */ 677 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv); 678 } 679 680 /* Always process completed itds */ 681 ehci_traverse_active_isoc_list(ehcip); 682 683 /* 684 * Check for any USB transaction completion notification. Also 685 * process any missed USB transaction completion interrupts. 686 */ 687 if ((intr & EHCI_INTR_USB) || (intr & EHCI_INTR_USB_ERROR) || 688 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB) || 689 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB_ERROR)) { 690 691 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 692 "ehci_intr: USB Transaction Completion Notification"); 693 694 /* Clear missed interrupts */ 695 if (ehcip->ehci_missed_intr_sts) { 696 ehcip->ehci_missed_intr_sts = 0; 697 } 698 699 /* Process completed qtds */ 700 ehci_traverse_active_qtd_list(ehcip); 701 } 702 703 /* Process endpoint reclamation list */ 704 if (ehcip->ehci_reclaim_list) { 705 ehci_handle_endpoint_reclaimation(ehcip); 706 } 707 708 /* Check for Host System Error */ 709 if (intr & EHCI_INTR_HOST_SYSTEM_ERROR) { 710 USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 711 "ehci_intr: Unrecoverable error"); 712 713 ehci_handle_ue(ehcip); 714 } 715 716 /* 717 * Read interrupt status register to make sure that any PIO 718 * store to clear the ISR has made it on the PCI bus before 719 * returning from its interrupt handler. 720 */ 721 (void) Get_OpReg(ehci_status); 722 723 /* Release the ehci global mutex */ 724 mutex_exit(&ehcip->ehci_int_mutex); 725 726 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 727 "Interrupt handling completed"); 728 729 return (DDI_INTR_CLAIMED); 730 } 731 732 733 /* 734 * EHCI HCDI entry points 735 * 736 * The Host Controller Driver Interfaces (HCDI) are the software interfaces 737 * between the Universal Serial Bus Layer (USBA) and the Host Controller 738 * Driver (HCD). The HCDI interfaces or entry points are subject to change. 739 */ 740 741 /* 742 * ehci_hcdi_pipe_open: 743 * 744 * Member of HCD Ops structure and called during client specific pipe open 745 * Add the pipe to the data structure representing the device and allocate 746 * bandwidth for the pipe if it is a interrupt or isochronous endpoint. 747 */ 748 int 749 ehci_hcdi_pipe_open( 750 usba_pipe_handle_data_t *ph, 751 usb_flags_t flags) 752 { 753 ehci_state_t *ehcip = ehci_obtain_state( 754 ph->p_usba_device->usb_root_hub_dip); 755 usb_ep_descr_t *epdt = &ph->p_ep; 756 int rval, error = USB_SUCCESS; 757 int kmflag = (flags & USB_FLAGS_SLEEP) ? 758 KM_SLEEP : KM_NOSLEEP; 759 uchar_t smask = 0; 760 uchar_t cmask = 0; 761 uint_t pnode = 0; 762 ehci_pipe_private_t *pp; 763 764 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 765 "ehci_hcdi_pipe_open: addr = 0x%x, ep%d", 766 ph->p_usba_device->usb_addr, 767 epdt->bEndpointAddress & USB_EP_NUM_MASK); 768 769 mutex_enter(&ehcip->ehci_int_mutex); 770 rval = ehci_state_is_operational(ehcip); 771 mutex_exit(&ehcip->ehci_int_mutex); 772 773 if (rval != USB_SUCCESS) { 774 775 return (rval); 776 } 777 778 /* 779 * Check and handle root hub pipe open. 780 */ 781 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 782 783 mutex_enter(&ehcip->ehci_int_mutex); 784 error = ehci_handle_root_hub_pipe_open(ph, flags); 785 mutex_exit(&ehcip->ehci_int_mutex); 786 787 return (error); 788 } 789 790 /* 791 * Opening of other pipes excluding root hub pipe are 792 * handled below. Check whether pipe is already opened. 793 */ 794 if (ph->p_hcd_private) { 795 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 796 "ehci_hcdi_pipe_open: Pipe is already opened"); 797 798 return (USB_FAILURE); 799 } 800 801 /* 802 * A portion of the bandwidth is reserved for the non-periodic 803 * transfers, i.e control and bulk transfers in each of one 804 * millisecond frame period & usually it will be 20% of frame 805 * period. Hence there is no need to check for the available 806 * bandwidth before adding the control or bulk endpoints. 807 * 808 * There is a need to check for the available bandwidth before 809 * adding the periodic transfers, i.e interrupt & isochronous, 810 * since all these periodic transfers are guaranteed transfers. 811 * Usually 80% of the total frame time is reserved for periodic 812 * transfers. 813 */ 814 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 815 816 mutex_enter(&ehcip->ehci_int_mutex); 817 mutex_enter(&ph->p_mutex); 818 819 error = ehci_allocate_bandwidth(ehcip, 820 ph, &pnode, &smask, &cmask); 821 822 if (error != USB_SUCCESS) { 823 824 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 825 "ehci_hcdi_pipe_open: Bandwidth allocation failed"); 826 827 mutex_exit(&ph->p_mutex); 828 mutex_exit(&ehcip->ehci_int_mutex); 829 830 return (error); 831 } 832 833 mutex_exit(&ph->p_mutex); 834 mutex_exit(&ehcip->ehci_int_mutex); 835 } 836 837 /* Create the HCD pipe private structure */ 838 pp = kmem_zalloc(sizeof (ehci_pipe_private_t), kmflag); 839 840 /* 841 * Return failure if ehci pipe private 842 * structure allocation fails. 843 */ 844 if (pp == NULL) { 845 846 mutex_enter(&ehcip->ehci_int_mutex); 847 848 /* Deallocate bandwidth */ 849 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 850 851 mutex_enter(&ph->p_mutex); 852 ehci_deallocate_bandwidth(ehcip, 853 ph, pnode, smask, cmask); 854 mutex_exit(&ph->p_mutex); 855 } 856 857 mutex_exit(&ehcip->ehci_int_mutex); 858 859 return (USB_NO_RESOURCES); 860 } 861 862 mutex_enter(&ehcip->ehci_int_mutex); 863 864 /* Save periodic nodes */ 865 pp->pp_pnode = pnode; 866 867 /* Save start and complete split mask values */ 868 pp->pp_smask = smask; 869 pp->pp_cmask = cmask; 870 871 /* Create prototype for xfer completion condition variable */ 872 cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL); 873 874 /* Set the state of pipe as idle */ 875 pp->pp_state = EHCI_PIPE_STATE_IDLE; 876 877 /* Store a pointer to the pipe handle */ 878 pp->pp_pipe_handle = ph; 879 880 mutex_enter(&ph->p_mutex); 881 882 /* Store the pointer in the pipe handle */ 883 ph->p_hcd_private = (usb_opaque_t)pp; 884 885 /* Store a copy of the pipe policy */ 886 bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t)); 887 888 mutex_exit(&ph->p_mutex); 889 890 /* Allocate the host controller endpoint descriptor */ 891 pp->pp_qh = ehci_alloc_qh(ehcip, ph, NULL); 892 893 /* Initialize the halting flag */ 894 pp->pp_halt_state = EHCI_HALT_STATE_FREE; 895 896 /* Create prototype for halt completion condition variable */ 897 cv_init(&pp->pp_halt_cmpl_cv, NULL, CV_DRIVER, NULL); 898 899 /* Isoch does not use QH, so ignore this */ 900 if ((pp->pp_qh == NULL) && !(EHCI_ISOC_ENDPOINT(epdt))) { 901 ASSERT(pp->pp_qh == NULL); 902 903 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 904 "ehci_hcdi_pipe_open: QH allocation failed"); 905 906 mutex_enter(&ph->p_mutex); 907 908 /* Deallocate bandwidth */ 909 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 910 911 ehci_deallocate_bandwidth(ehcip, 912 ph, pnode, smask, cmask); 913 } 914 915 /* Destroy the xfer completion condition variable */ 916 cv_destroy(&pp->pp_xfer_cmpl_cv); 917 918 /* 919 * Deallocate the hcd private portion 920 * of the pipe handle. 921 */ 922 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t)); 923 924 /* 925 * Set the private structure in the 926 * pipe handle equal to NULL. 927 */ 928 ph->p_hcd_private = NULL; 929 930 mutex_exit(&ph->p_mutex); 931 mutex_exit(&ehcip->ehci_int_mutex); 932 933 return (USB_NO_RESOURCES); 934 } 935 936 /* 937 * Isoch does not use QH so no need to 938 * restore data toggle or insert QH 939 */ 940 if (!(EHCI_ISOC_ENDPOINT(epdt))) { 941 /* Restore the data toggle information */ 942 ehci_restore_data_toggle(ehcip, ph); 943 } 944 945 /* 946 * Insert the endpoint onto the host controller's 947 * appropriate endpoint list. The host controller 948 * will not schedule this endpoint and will not have 949 * any QTD's to process. It will also update the pipe count. 950 */ 951 ehci_insert_qh(ehcip, ph); 952 953 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 954 "ehci_hcdi_pipe_open: ph = 0x%p", (void *)ph); 955 956 ehcip->ehci_open_pipe_count++; 957 958 mutex_exit(&ehcip->ehci_int_mutex); 959 960 return (USB_SUCCESS); 961 } 962 963 964 /* 965 * ehci_hcdi_pipe_close: 966 * 967 * Member of HCD Ops structure and called during the client specific pipe 968 * close. Remove the pipe and the data structure representing the device. 969 * Deallocate bandwidth for the pipe if it is a interrupt or isochronous 970 * endpoint. 971 */ 972 /* ARGSUSED */ 973 int 974 ehci_hcdi_pipe_close( 975 usba_pipe_handle_data_t *ph, 976 usb_flags_t flags) 977 { 978 ehci_state_t *ehcip = ehci_obtain_state( 979 ph->p_usba_device->usb_root_hub_dip); 980 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 981 usb_ep_descr_t *eptd = &ph->p_ep; 982 int error = USB_SUCCESS; 983 984 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 985 "ehci_hcdi_pipe_close: addr = 0x%x, ep%d", 986 ph->p_usba_device->usb_addr, 987 eptd->bEndpointAddress & USB_EP_NUM_MASK); 988 989 /* Check and handle root hub pipe close */ 990 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 991 992 mutex_enter(&ehcip->ehci_int_mutex); 993 error = ehci_handle_root_hub_pipe_close(ph); 994 mutex_exit(&ehcip->ehci_int_mutex); 995 996 return (error); 997 } 998 999 ASSERT(ph->p_hcd_private != NULL); 1000 1001 mutex_enter(&ehcip->ehci_int_mutex); 1002 1003 /* Set pipe state to pipe close */ 1004 pp->pp_state = EHCI_PIPE_STATE_CLOSE; 1005 1006 ehci_pipe_cleanup(ehcip, ph); 1007 1008 /* 1009 * Remove the endpoint descriptor from Host 1010 * Controller's appropriate endpoint list. 1011 */ 1012 ehci_remove_qh(ehcip, pp, B_TRUE); 1013 1014 /* Deallocate bandwidth */ 1015 if (EHCI_PERIODIC_ENDPOINT(eptd)) { 1016 1017 mutex_enter(&ph->p_mutex); 1018 ehci_deallocate_bandwidth(ehcip, ph, pp->pp_pnode, 1019 pp->pp_smask, pp->pp_cmask); 1020 mutex_exit(&ph->p_mutex); 1021 } 1022 1023 mutex_enter(&ph->p_mutex); 1024 1025 /* Destroy the xfer completion condition variable */ 1026 cv_destroy(&pp->pp_xfer_cmpl_cv); 1027 1028 1029 /* Destory halt completion condition variable */ 1030 cv_destroy(&pp->pp_halt_cmpl_cv); 1031 1032 /* 1033 * Deallocate the hcd private portion 1034 * of the pipe handle. 1035 */ 1036 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t)); 1037 ph->p_hcd_private = NULL; 1038 1039 mutex_exit(&ph->p_mutex); 1040 1041 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1042 "ehci_hcdi_pipe_close: ph = 0x%p", (void *)ph); 1043 1044 ehcip->ehci_open_pipe_count--; 1045 1046 mutex_exit(&ehcip->ehci_int_mutex); 1047 1048 return (error); 1049 } 1050 1051 1052 /* 1053 * ehci_hcdi_pipe_reset: 1054 */ 1055 /* ARGSUSED */ 1056 int 1057 ehci_hcdi_pipe_reset( 1058 usba_pipe_handle_data_t *ph, 1059 usb_flags_t usb_flags) 1060 { 1061 ehci_state_t *ehcip = ehci_obtain_state( 1062 ph->p_usba_device->usb_root_hub_dip); 1063 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1064 int error = USB_SUCCESS; 1065 1066 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1067 "ehci_hcdi_pipe_reset:"); 1068 1069 /* 1070 * Check and handle root hub pipe reset. 1071 */ 1072 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1073 1074 error = ehci_handle_root_hub_pipe_reset(ph, usb_flags); 1075 return (error); 1076 } 1077 1078 mutex_enter(&ehcip->ehci_int_mutex); 1079 1080 /* Set pipe state to pipe reset */ 1081 pp->pp_state = EHCI_PIPE_STATE_RESET; 1082 1083 ehci_pipe_cleanup(ehcip, ph); 1084 1085 mutex_exit(&ehcip->ehci_int_mutex); 1086 1087 return (error); 1088 } 1089 1090 /* 1091 * ehci_hcdi_pipe_ctrl_xfer: 1092 */ 1093 int 1094 ehci_hcdi_pipe_ctrl_xfer( 1095 usba_pipe_handle_data_t *ph, 1096 usb_ctrl_req_t *ctrl_reqp, 1097 usb_flags_t usb_flags) 1098 { 1099 ehci_state_t *ehcip = ehci_obtain_state( 1100 ph->p_usba_device->usb_root_hub_dip); 1101 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1102 int rval; 1103 int error = USB_SUCCESS; 1104 ehci_trans_wrapper_t *tw; 1105 1106 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1107 "ehci_hcdi_pipe_ctrl_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1108 (void *)ph, (void *)ctrl_reqp, usb_flags); 1109 1110 mutex_enter(&ehcip->ehci_int_mutex); 1111 rval = ehci_state_is_operational(ehcip); 1112 mutex_exit(&ehcip->ehci_int_mutex); 1113 1114 if (rval != USB_SUCCESS) { 1115 1116 return (rval); 1117 } 1118 1119 /* 1120 * Check and handle root hub control request. 1121 */ 1122 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1123 1124 error = ehci_handle_root_hub_request(ehcip, ph, ctrl_reqp); 1125 1126 return (error); 1127 } 1128 1129 mutex_enter(&ehcip->ehci_int_mutex); 1130 1131 /* 1132 * Check whether pipe is in halted state. 1133 */ 1134 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) { 1135 1136 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1137 "ehci_hcdi_pipe_ctrl_xfer: " 1138 "Pipe is in error state, need pipe reset to continue"); 1139 1140 mutex_exit(&ehcip->ehci_int_mutex); 1141 1142 return (USB_FAILURE); 1143 } 1144 1145 /* Allocate a transfer wrapper */ 1146 if ((tw = ehci_allocate_ctrl_resources(ehcip, pp, ctrl_reqp, 1147 usb_flags)) == NULL) { 1148 1149 error = USB_NO_RESOURCES; 1150 } else { 1151 /* Insert the qtd's on the endpoint */ 1152 ehci_insert_ctrl_req(ehcip, ph, ctrl_reqp, tw, usb_flags); 1153 } 1154 1155 mutex_exit(&ehcip->ehci_int_mutex); 1156 1157 return (error); 1158 } 1159 1160 1161 /* 1162 * ehci_hcdi_bulk_transfer_size: 1163 * 1164 * Return maximum bulk transfer size 1165 */ 1166 1167 /* ARGSUSED */ 1168 int 1169 ehci_hcdi_bulk_transfer_size( 1170 usba_device_t *usba_device, 1171 size_t *size) 1172 { 1173 ehci_state_t *ehcip = ehci_obtain_state( 1174 usba_device->usb_root_hub_dip); 1175 int rval; 1176 1177 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1178 "ehci_hcdi_bulk_transfer_size:"); 1179 1180 mutex_enter(&ehcip->ehci_int_mutex); 1181 rval = ehci_state_is_operational(ehcip); 1182 mutex_exit(&ehcip->ehci_int_mutex); 1183 1184 if (rval != USB_SUCCESS) { 1185 1186 return (rval); 1187 } 1188 1189 /* VIA VT6202 may not handle bigger xfers well, workaround. */ 1190 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) && 1191 (ehci_vt62x2_workaround & EHCI_VIA_REDUCED_MAX_BULK_XFER_SIZE)) { 1192 *size = EHCI_VIA_MAX_BULK_XFER_SIZE; 1193 } else { 1194 *size = EHCI_MAX_BULK_XFER_SIZE; 1195 } 1196 1197 return (USB_SUCCESS); 1198 } 1199 1200 1201 /* 1202 * ehci_hcdi_pipe_bulk_xfer: 1203 */ 1204 int 1205 ehci_hcdi_pipe_bulk_xfer( 1206 usba_pipe_handle_data_t *ph, 1207 usb_bulk_req_t *bulk_reqp, 1208 usb_flags_t usb_flags) 1209 { 1210 ehci_state_t *ehcip = ehci_obtain_state( 1211 ph->p_usba_device->usb_root_hub_dip); 1212 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1213 int rval, error = USB_SUCCESS; 1214 ehci_trans_wrapper_t *tw; 1215 1216 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1217 "ehci_hcdi_pipe_bulk_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1218 (void *)ph, (void *)bulk_reqp, usb_flags); 1219 1220 mutex_enter(&ehcip->ehci_int_mutex); 1221 rval = ehci_state_is_operational(ehcip); 1222 1223 if (rval != USB_SUCCESS) { 1224 mutex_exit(&ehcip->ehci_int_mutex); 1225 1226 return (rval); 1227 } 1228 1229 /* 1230 * Check whether pipe is in halted state. 1231 */ 1232 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) { 1233 1234 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1235 "ehci_hcdi_pipe_bulk_xfer:" 1236 "Pipe is in error state, need pipe reset to continue"); 1237 1238 mutex_exit(&ehcip->ehci_int_mutex); 1239 1240 return (USB_FAILURE); 1241 } 1242 1243 /* Allocate a transfer wrapper */ 1244 if ((tw = ehci_allocate_bulk_resources(ehcip, pp, bulk_reqp, 1245 usb_flags)) == NULL) { 1246 1247 error = USB_NO_RESOURCES; 1248 } else { 1249 /* Add the QTD into the Host Controller's bulk list */ 1250 ehci_insert_bulk_req(ehcip, ph, bulk_reqp, tw, usb_flags); 1251 } 1252 1253 mutex_exit(&ehcip->ehci_int_mutex); 1254 1255 return (error); 1256 } 1257 1258 1259 /* 1260 * ehci_hcdi_pipe_intr_xfer: 1261 */ 1262 int 1263 ehci_hcdi_pipe_intr_xfer( 1264 usba_pipe_handle_data_t *ph, 1265 usb_intr_req_t *intr_reqp, 1266 usb_flags_t usb_flags) 1267 { 1268 ehci_state_t *ehcip = ehci_obtain_state( 1269 ph->p_usba_device->usb_root_hub_dip); 1270 int pipe_dir, rval, error = USB_SUCCESS; 1271 ehci_trans_wrapper_t *tw; 1272 1273 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1274 "ehci_hcdi_pipe_intr_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1275 (void *)ph, (void *)intr_reqp, usb_flags); 1276 1277 mutex_enter(&ehcip->ehci_int_mutex); 1278 rval = ehci_state_is_operational(ehcip); 1279 1280 if (rval != USB_SUCCESS) { 1281 mutex_exit(&ehcip->ehci_int_mutex); 1282 1283 return (rval); 1284 } 1285 1286 /* Get the pipe direction */ 1287 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1288 1289 if (pipe_dir == USB_EP_DIR_IN) { 1290 error = ehci_start_periodic_pipe_polling(ehcip, ph, 1291 (usb_opaque_t)intr_reqp, usb_flags); 1292 } else { 1293 /* Allocate transaction resources */ 1294 if ((tw = ehci_allocate_intr_resources(ehcip, ph, 1295 intr_reqp, usb_flags)) == NULL) { 1296 1297 error = USB_NO_RESOURCES; 1298 } else { 1299 ehci_insert_intr_req(ehcip, 1300 (ehci_pipe_private_t *)ph->p_hcd_private, 1301 tw, usb_flags); 1302 } 1303 } 1304 1305 mutex_exit(&ehcip->ehci_int_mutex); 1306 1307 return (error); 1308 } 1309 1310 /* 1311 * ehci_hcdi_pipe_stop_intr_polling() 1312 */ 1313 int 1314 ehci_hcdi_pipe_stop_intr_polling( 1315 usba_pipe_handle_data_t *ph, 1316 usb_flags_t flags) 1317 { 1318 ehci_state_t *ehcip = ehci_obtain_state( 1319 ph->p_usba_device->usb_root_hub_dip); 1320 int error = USB_SUCCESS; 1321 1322 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1323 "ehci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x", 1324 (void *)ph, flags); 1325 1326 mutex_enter(&ehcip->ehci_int_mutex); 1327 1328 error = ehci_stop_periodic_pipe_polling(ehcip, ph, flags); 1329 1330 mutex_exit(&ehcip->ehci_int_mutex); 1331 1332 return (error); 1333 } 1334 1335 1336 /* 1337 * ehci_hcdi_get_current_frame_number: 1338 * 1339 * Get the current usb frame number. 1340 * Return whether the request is handled successfully. 1341 */ 1342 int 1343 ehci_hcdi_get_current_frame_number( 1344 usba_device_t *usba_device, 1345 usb_frame_number_t *frame_number) 1346 { 1347 ehci_state_t *ehcip = ehci_obtain_state( 1348 usba_device->usb_root_hub_dip); 1349 int rval; 1350 1351 ehcip = ehci_obtain_state(usba_device->usb_root_hub_dip); 1352 1353 mutex_enter(&ehcip->ehci_int_mutex); 1354 rval = ehci_state_is_operational(ehcip); 1355 1356 if (rval != USB_SUCCESS) { 1357 mutex_exit(&ehcip->ehci_int_mutex); 1358 1359 return (rval); 1360 } 1361 1362 *frame_number = ehci_get_current_frame_number(ehcip); 1363 1364 mutex_exit(&ehcip->ehci_int_mutex); 1365 1366 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1367 "ehci_hcdi_get_current_frame_number: " 1368 "Current frame number 0x%llx", (unsigned long long)(*frame_number)); 1369 1370 return (rval); 1371 } 1372 1373 1374 /* 1375 * ehci_hcdi_get_max_isoc_pkts: 1376 * 1377 * Get maximum isochronous packets per usb isochronous request. 1378 * Return whether the request is handled successfully. 1379 */ 1380 int 1381 ehci_hcdi_get_max_isoc_pkts( 1382 usba_device_t *usba_device, 1383 uint_t *max_isoc_pkts_per_request) 1384 { 1385 ehci_state_t *ehcip = ehci_obtain_state( 1386 usba_device->usb_root_hub_dip); 1387 int rval; 1388 1389 mutex_enter(&ehcip->ehci_int_mutex); 1390 rval = ehci_state_is_operational(ehcip); 1391 mutex_exit(&ehcip->ehci_int_mutex); 1392 1393 if (rval != USB_SUCCESS) { 1394 1395 return (rval); 1396 } 1397 1398 *max_isoc_pkts_per_request = EHCI_MAX_ISOC_PKTS_PER_XFER; 1399 1400 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1401 "ehci_hcdi_get_max_isoc_pkts: maximum isochronous" 1402 "packets per usb isochronous request = 0x%x", 1403 *max_isoc_pkts_per_request); 1404 1405 return (rval); 1406 } 1407 1408 1409 /* 1410 * ehci_hcdi_pipe_isoc_xfer: 1411 */ 1412 int 1413 ehci_hcdi_pipe_isoc_xfer( 1414 usba_pipe_handle_data_t *ph, 1415 usb_isoc_req_t *isoc_reqp, 1416 usb_flags_t usb_flags) 1417 { 1418 ehci_state_t *ehcip = ehci_obtain_state( 1419 ph->p_usba_device->usb_root_hub_dip); 1420 1421 int pipe_dir, rval; 1422 ehci_isoc_xwrapper_t *itw; 1423 1424 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1425 "ehci_hcdi_pipe_isoc_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x", 1426 (void *)ph, (void *)isoc_reqp, usb_flags); 1427 1428 mutex_enter(&ehcip->ehci_int_mutex); 1429 rval = ehci_state_is_operational(ehcip); 1430 1431 if (rval != USB_SUCCESS) { 1432 mutex_exit(&ehcip->ehci_int_mutex); 1433 1434 return (rval); 1435 } 1436 1437 /* Get the isochronous pipe direction */ 1438 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1439 1440 if (pipe_dir == USB_EP_DIR_IN) { 1441 rval = ehci_start_periodic_pipe_polling(ehcip, ph, 1442 (usb_opaque_t)isoc_reqp, usb_flags); 1443 } else { 1444 /* Allocate transaction resources */ 1445 if ((itw = ehci_allocate_isoc_resources(ehcip, ph, 1446 isoc_reqp, usb_flags)) == NULL) { 1447 rval = USB_NO_RESOURCES; 1448 } else { 1449 rval = ehci_insert_isoc_req(ehcip, 1450 (ehci_pipe_private_t *)ph->p_hcd_private, 1451 itw, usb_flags); 1452 } 1453 } 1454 1455 mutex_exit(&ehcip->ehci_int_mutex); 1456 1457 return (rval); 1458 } 1459 1460 1461 /* 1462 * ehci_hcdi_pipe_stop_isoc_polling() 1463 */ 1464 /*ARGSUSED*/ 1465 int 1466 ehci_hcdi_pipe_stop_isoc_polling( 1467 usba_pipe_handle_data_t *ph, 1468 usb_flags_t flags) 1469 { 1470 ehci_state_t *ehcip = ehci_obtain_state( 1471 ph->p_usba_device->usb_root_hub_dip); 1472 int rval; 1473 1474 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1475 "ehci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x", 1476 (void *)ph, flags); 1477 1478 mutex_enter(&ehcip->ehci_int_mutex); 1479 rval = ehci_state_is_operational(ehcip); 1480 1481 if (rval != USB_SUCCESS) { 1482 mutex_exit(&ehcip->ehci_int_mutex); 1483 1484 return (rval); 1485 } 1486 1487 rval = ehci_stop_periodic_pipe_polling(ehcip, ph, flags); 1488 1489 mutex_exit(&ehcip->ehci_int_mutex); 1490 1491 return (rval); 1492 } 1493