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 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * EHCI Host Controller Driver (EHCI) 30 * 31 * The EHCI driver is a software driver which interfaces to the Universal 32 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to 33 * the Host Controller is defined by the EHCI Host Controller Interface. 34 * 35 * This file contains code for Auto-configuration and HCDI entry points. 36 * 37 * NOTE: 38 * 39 * Currently EHCI driver does not support the following features 40 * 41 * - Alternate QTD for short xfer condition is only used in Bulk xfers. 42 * - Frame Span Traversal Nodes (FSTN). 43 * - Bandwidth allocation scheme needs to be updated for FSTN and USB2.0 44 * or High speed hub with multiple TT implementation. Currently bandwidth 45 * allocation scheme assumes one TT per USB2.0 or High speed hub. 46 * - 64 bit addressing capability. 47 * - Programmable periodic frame list size like 256, 512, 1024. 48 * It supports only 1024 periodic frame list size. 49 */ 50 51 #include <sys/usb/hcd/ehci/ehcid.h> 52 #include <sys/usb/hcd/ehci/ehci_xfer.h> 53 #include <sys/usb/hcd/ehci/ehci_intr.h> 54 #include <sys/usb/hcd/ehci/ehci_util.h> 55 #include <sys/usb/hcd/ehci/ehci_isoch.h> 56 57 /* Pointer to the state structure */ 58 void *ehci_statep; 59 60 /* Number of instances */ 61 #define EHCI_INSTS 1 62 63 /* Debugging information */ 64 uint_t ehci_errmask = (uint_t)PRINT_MASK_ALL; 65 uint_t ehci_errlevel = USB_LOG_L2; 66 uint_t ehci_instance_debug = (uint_t)-1; 67 68 /* 69 * Tunable to ensure host controller goes off even if a keyboard is attached. 70 */ 71 int force_ehci_off = 1; 72 73 /* Enable all workarounds for VIA VT62x2 */ 74 uint_t ehci_vt62x2_workaround = EHCI_VIA_WORKAROUNDS; 75 76 /* 77 * EHCI Auto-configuration entry points. 78 * 79 * Device operations (dev_ops) entries function prototypes. 80 * 81 * We use the hub cbops since all nexus ioctl operations defined so far will 82 * be executed by the root hub. The following are the Host Controller Driver 83 * (HCD) entry points. 84 * 85 * the open/close/ioctl functions call the corresponding usba_hubdi_* 86 * calls after looking up the dip thru the dev_t. 87 */ 88 static int ehci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 89 static int ehci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 90 static int ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd); 91 static int ehci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 92 void *arg, void **result); 93 94 static int ehci_open(dev_t *devp, int flags, int otyp, cred_t *credp); 95 static int ehci_close(dev_t dev, int flag, int otyp, cred_t *credp); 96 static int ehci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 97 cred_t *credp, int *rvalp); 98 99 int usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level); 100 101 static struct cb_ops ehci_cb_ops = { 102 ehci_open, /* EHCI */ 103 ehci_close, /* Close */ 104 nodev, /* Strategy */ 105 nodev, /* Print */ 106 nodev, /* Dump */ 107 nodev, /* Read */ 108 nodev, /* Write */ 109 ehci_ioctl, /* Ioctl */ 110 nodev, /* Devmap */ 111 nodev, /* Mmap */ 112 nodev, /* Segmap */ 113 nochpoll, /* Poll */ 114 ddi_prop_op, /* cb_prop_op */ 115 NULL, /* Streamtab */ 116 D_NEW | D_MP | D_HOTPLUG /* Driver compatibility flag */ 117 }; 118 119 static struct dev_ops ehci_ops = { 120 DEVO_REV, /* Devo_rev */ 121 0, /* Refcnt */ 122 ehci_info, /* Info */ 123 nulldev, /* Identify */ 124 nulldev, /* Probe */ 125 ehci_attach, /* Attach */ 126 ehci_detach, /* Detach */ 127 ehci_reset, /* Reset */ 128 &ehci_cb_ops, /* Driver operations */ 129 &usba_hubdi_busops, /* Bus operations */ 130 usba_hubdi_root_hub_power /* Power */ 131 }; 132 133 /* 134 * The USBA library must be loaded for this driver. 135 */ 136 static struct modldrv modldrv = { 137 &mod_driverops, /* Type of module. This one is a driver */ 138 "USB EHCI Driver %I%", /* Name of the module. */ 139 &ehci_ops, /* Driver ops */ 140 }; 141 142 static struct modlinkage modlinkage = { 143 MODREV_1, (void *)&modldrv, NULL 144 }; 145 146 147 int 148 _init(void) 149 { 150 int error; 151 152 /* Initialize the soft state structures */ 153 if ((error = ddi_soft_state_init(&ehci_statep, sizeof (ehci_state_t), 154 EHCI_INSTS)) != 0) { 155 return (error); 156 } 157 158 /* Install the loadable module */ 159 if ((error = mod_install(&modlinkage)) != 0) { 160 ddi_soft_state_fini(&ehci_statep); 161 } 162 163 return (error); 164 } 165 166 167 int 168 _info(struct modinfo *modinfop) 169 { 170 return (mod_info(&modlinkage, modinfop)); 171 } 172 173 174 int 175 _fini(void) 176 { 177 int error; 178 179 if ((error = mod_remove(&modlinkage)) == 0) { 180 181 /* Release per module resources */ 182 ddi_soft_state_fini(&ehci_statep); 183 } 184 185 return (error); 186 } 187 188 189 /* 190 * EHCI Auto configuration entry points. 191 */ 192 193 /* 194 * ehci_attach: 195 * 196 * Description: Attach entry point is called by the Kernel. 197 * Allocates resources for each EHCI host controller instance. 198 * Initializes the EHCI Host Controller. 199 * 200 * Return : DDI_SUCCESS / DDI_FAILURE. 201 */ 202 static int 203 ehci_attach(dev_info_t *dip, 204 ddi_attach_cmd_t cmd) 205 { 206 int instance; 207 ehci_state_t *ehcip = NULL; 208 usba_hcdi_register_args_t hcdi_args; 209 210 switch (cmd) { 211 case DDI_ATTACH: 212 break; 213 case DDI_RESUME: 214 ehcip = ehci_obtain_state(dip); 215 216 return (ehci_cpr_resume(ehcip)); 217 default: 218 return (DDI_FAILURE); 219 } 220 221 /* Get the instance and create soft state */ 222 instance = ddi_get_instance(dip); 223 224 if (ddi_soft_state_zalloc(ehci_statep, instance) != 0) { 225 226 return (DDI_FAILURE); 227 } 228 229 ehcip = ddi_get_soft_state(ehci_statep, instance); 230 if (ehcip == NULL) { 231 232 return (DDI_FAILURE); 233 } 234 235 ehcip->ehci_flags = EHCI_ATTACH; 236 237 ehcip->ehci_log_hdl = usb_alloc_log_hdl(dip, "ehci", &ehci_errlevel, 238 &ehci_errmask, &ehci_instance_debug, 0); 239 240 ehcip->ehci_flags |= EHCI_ZALLOC; 241 242 /* Set host controller soft state to initialization */ 243 ehcip->ehci_hc_soft_state = EHCI_CTLR_INIT_STATE; 244 245 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, 246 "ehcip = 0x%p", (void *)ehcip); 247 248 /* Initialize the DMA attributes */ 249 ehci_set_dma_attributes(ehcip); 250 251 /* Save the dip and instance */ 252 ehcip->ehci_dip = dip; 253 ehcip->ehci_instance = instance; 254 255 /* Initialize the DMA attributes */ 256 ehci_create_stats(ehcip); 257 258 /* Create the qtd and qh pools */ 259 if (ehci_allocate_pools(ehcip) != DDI_SUCCESS) { 260 (void) ehci_cleanup(ehcip); 261 262 return (DDI_FAILURE); 263 } 264 265 /* Initialize the isochronous resources */ 266 if (ehci_isoc_init(ehcip) != DDI_SUCCESS) { 267 (void) ehci_cleanup(ehcip); 268 269 return (DDI_FAILURE); 270 } 271 272 /* Map the registers */ 273 if (ehci_map_regs(ehcip) != DDI_SUCCESS) { 274 (void) ehci_cleanup(ehcip); 275 276 return (DDI_FAILURE); 277 } 278 279 /* Get the ehci chip vendor and device id */ 280 ehcip->ehci_vendor_id = pci_config_get16( 281 ehcip->ehci_config_handle, PCI_CONF_VENID); 282 ehcip->ehci_device_id = pci_config_get16( 283 ehcip->ehci_config_handle, PCI_CONF_DEVID); 284 ehcip->ehci_rev_id = pci_config_get8( 285 ehcip->ehci_config_handle, PCI_CONF_REVID); 286 287 /* Register interrupts */ 288 if (ehci_register_intrs_and_init_mutex(ehcip) != DDI_SUCCESS) { 289 (void) ehci_cleanup(ehcip); 290 291 return (DDI_FAILURE); 292 } 293 294 mutex_enter(&ehcip->ehci_int_mutex); 295 296 /* Initialize the controller */ 297 if (ehci_init_ctlr(ehcip, EHCI_NORMAL_INITIALIZATION) != DDI_SUCCESS) { 298 mutex_exit(&ehcip->ehci_int_mutex); 299 (void) ehci_cleanup(ehcip); 300 301 return (DDI_FAILURE); 302 } 303 304 /* 305 * At this point, the hardware will be okay. 306 * Initialize the usba_hcdi structure 307 */ 308 ehcip->ehci_hcdi_ops = ehci_alloc_hcdi_ops(ehcip); 309 310 mutex_exit(&ehcip->ehci_int_mutex); 311 312 /* 313 * Make this HCD instance known to USBA 314 * (dma_attr must be passed for USBA busctl's) 315 */ 316 hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION; 317 hcdi_args.usba_hcdi_register_dip = dip; 318 hcdi_args.usba_hcdi_register_ops = ehcip->ehci_hcdi_ops; 319 hcdi_args.usba_hcdi_register_dma_attr = &ehcip->ehci_dma_attr; 320 321 /* 322 * Priority and iblock_cookie are one and the same 323 * (However, retaining hcdi_soft_iblock_cookie for now 324 * assigning it w/ priority. In future all iblock_cookie 325 * could just go) 326 */ 327 hcdi_args.usba_hcdi_register_iblock_cookie = 328 (ddi_iblock_cookie_t)(uintptr_t)ehcip->ehci_intr_pri; 329 330 if (usba_hcdi_register(&hcdi_args, 0) != DDI_SUCCESS) { 331 (void) ehci_cleanup(ehcip); 332 333 return (DDI_FAILURE); 334 } 335 336 ehcip->ehci_flags |= EHCI_USBAREG; 337 338 mutex_enter(&ehcip->ehci_int_mutex); 339 340 if ((ehci_init_root_hub(ehcip)) != USB_SUCCESS) { 341 mutex_exit(&ehcip->ehci_int_mutex); 342 (void) ehci_cleanup(ehcip); 343 344 return (DDI_FAILURE); 345 } 346 347 mutex_exit(&ehcip->ehci_int_mutex); 348 349 /* Finally load the root hub driver */ 350 if (ehci_load_root_hub_driver(ehcip) != USB_SUCCESS) { 351 (void) ehci_cleanup(ehcip); 352 353 return (DDI_FAILURE); 354 } 355 ehcip->ehci_flags |= EHCI_RHREG; 356 357 /* Display information in the banner */ 358 ddi_report_dev(dip); 359 360 mutex_enter(&ehcip->ehci_int_mutex); 361 362 /* Reset the ehci initialization flag */ 363 ehcip->ehci_flags &= ~EHCI_ATTACH; 364 365 /* Print the Host Control's Operational registers */ 366 ehci_print_caps(ehcip); 367 ehci_print_regs(ehcip); 368 369 (void) pci_report_pmcap(dip, PCI_PM_IDLESPEED, (void *)4000); 370 371 mutex_exit(&ehcip->ehci_int_mutex); 372 373 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, 374 "ehci_attach: dip = 0x%p done", (void *)dip); 375 376 return (DDI_SUCCESS); 377 } 378 379 380 /* 381 * ehci_detach: 382 * 383 * Description: Detach entry point is called by the Kernel. 384 * Deallocates all resource allocated. 385 * Unregisters the interrupt handler. 386 * 387 * Return : DDI_SUCCESS / DDI_FAILURE 388 */ 389 int 390 ehci_detach(dev_info_t *dip, 391 ddi_detach_cmd_t cmd) 392 { 393 ehci_state_t *ehcip = ehci_obtain_state(dip); 394 395 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, "ehci_detach:"); 396 397 switch (cmd) { 398 case DDI_DETACH: 399 400 return (ehci_cleanup(ehcip)); 401 case DDI_SUSPEND: 402 403 return (ehci_cpr_suspend(ehcip)); 404 default: 405 406 return (DDI_FAILURE); 407 } 408 } 409 410 /* 411 * ehci_reset: 412 * 413 * Description: Reset entry point - called by the Kernel 414 * on the way down. 415 * Toshiba Tecra laptop has been observed to hang 416 * on soft reboot. The resetting ehci on the way 417 * down solves the problem. 418 * 419 * Return : DDI_SUCCESS / DDI_FAILURE 420 */ 421 /* ARGSUSED */ 422 static int 423 ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd) 424 { 425 #if defined(__sparc) 426 /* 427 * Don't reset the host controller on SPARC, for OBP needs Solaris 428 * to continue to provide keyboard support after shutdown of SPARC, 429 * or the keyboard connected to a USB 2.0 port will not work after 430 * that. The incomplete reset problem on Toshiba Tecra laptop is 431 * specific to Tecra laptop or BIOS, not present on SPARC. The SPARC 432 * OBP guarantees good reset behavior during startup. 433 */ 434 return (DDI_SUCCESS); 435 #else 436 ehci_state_t *ehcip = ehci_obtain_state(dip); 437 438 mutex_enter(&ehcip->ehci_int_mutex); 439 440 /* 441 * To reset the host controller, the HCRESET bit should be set to one. 442 * Software should not set this bit to a one when the HCHalted bit in 443 * the USBSTS register is a zero. Attempting to reset an actively 444 * running host controller will result in undefined behavior. 445 * see EHCI SPEC. for more information. 446 */ 447 if (!(Get_OpReg(ehci_status) & EHCI_STS_HOST_CTRL_HALTED)) { 448 449 /* Stop the EHCI host controller */ 450 Set_OpReg(ehci_command, 451 Get_OpReg(ehci_command) & ~EHCI_CMD_HOST_CTRL_RUN); 452 /* 453 * When this bit is set to 0, the Host Controller completes the 454 * current and any actively pipelined transactions on the USB 455 * and then halts. The Host Controller must halt within 16 456 * micro-frames after software clears the Run bit. 457 * The HC Halted bit in the status register indicates when the 458 * Host Controller has finished its pending pipelined 459 * transactions and has entered the stopped state. 460 */ 461 drv_usecwait(EHCI_RESET_TIMEWAIT); 462 } 463 464 /* Reset the EHCI host controller */ 465 Set_OpReg(ehci_command, 466 Get_OpReg(ehci_command) | EHCI_CMD_HOST_CTRL_RESET); 467 468 mutex_exit(&ehcip->ehci_int_mutex); 469 470 return (DDI_SUCCESS); 471 #endif 472 } 473 474 /* 475 * ehci_info: 476 */ 477 /* ARGSUSED */ 478 static int 479 ehci_info(dev_info_t *dip, 480 ddi_info_cmd_t infocmd, 481 void *arg, 482 void **result) 483 { 484 dev_t dev; 485 ehci_state_t *ehcip; 486 int instance; 487 int error = DDI_FAILURE; 488 489 switch (infocmd) { 490 case DDI_INFO_DEVT2DEVINFO: 491 dev = (dev_t)arg; 492 instance = EHCI_UNIT(dev); 493 ehcip = ddi_get_soft_state(ehci_statep, instance); 494 if (ehcip != NULL) { 495 *result = (void *)ehcip->ehci_dip; 496 if (*result != NULL) { 497 error = DDI_SUCCESS; 498 } 499 } else { 500 *result = NULL; 501 } 502 503 break; 504 case DDI_INFO_DEVT2INSTANCE: 505 dev = (dev_t)arg; 506 instance = EHCI_UNIT(dev); 507 *result = (void *)(uintptr_t)instance; 508 error = DDI_SUCCESS; 509 break; 510 default: 511 break; 512 } 513 514 return (error); 515 } 516 517 518 /* 519 * EHCI CB_OPS entry points. 520 */ 521 static dev_info_t * 522 ehci_get_dip(dev_t dev) 523 { 524 int instance = EHCI_UNIT(dev); 525 ehci_state_t *ehcip = ddi_get_soft_state(ehci_statep, instance); 526 527 if (ehcip) { 528 529 return (ehcip->ehci_dip); 530 } else { 531 532 return (NULL); 533 } 534 } 535 536 537 static int 538 ehci_open(dev_t *devp, 539 int flags, 540 int otyp, 541 cred_t *credp) 542 { 543 dev_info_t *dip = ehci_get_dip(*devp); 544 545 return (usba_hubdi_open(dip, devp, flags, otyp, credp)); 546 } 547 548 549 static int 550 ehci_close(dev_t dev, 551 int flag, 552 int otyp, 553 cred_t *credp) 554 { 555 dev_info_t *dip = ehci_get_dip(dev); 556 557 return (usba_hubdi_close(dip, dev, flag, otyp, credp)); 558 } 559 560 561 static int 562 ehci_ioctl(dev_t dev, 563 int cmd, 564 intptr_t arg, 565 int mode, 566 cred_t *credp, 567 int *rvalp) 568 { 569 dev_info_t *dip = ehci_get_dip(dev); 570 571 return (usba_hubdi_ioctl(dip, 572 dev, cmd, arg, mode, credp, rvalp)); 573 } 574 575 /* 576 * EHCI Interrupt Handler entry point. 577 */ 578 579 /* 580 * ehci_intr: 581 * 582 * EHCI (EHCI) interrupt handling routine. 583 */ 584 uint_t 585 ehci_intr(caddr_t arg1, caddr_t arg2) 586 { 587 uint_t intr; 588 ehci_state_t *ehcip = (ehci_state_t *)arg1; 589 590 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 591 "ehci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p", arg1, 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, 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, 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, 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", 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, 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