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 2007 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 /* 597 * Now process the actual ehci interrupt events that caused 598 * invocation of this ehci interrupt handler. 599 */ 600 intr = (Get_OpReg(ehci_status) & Get_OpReg(ehci_interrupt)); 601 602 /* Update kstat values */ 603 ehci_do_intrs_stats(ehcip, intr); 604 605 /* 606 * We could have gotten a spurious interrupts. If so, do not 607 * claim it. This is quite possible on some architectures 608 * where more than one PCI slots share the IRQs. If so, the 609 * associated driver's interrupt routine may get called even 610 * if the interrupt is not meant for them. 611 * 612 * By unclaiming the interrupt, the other driver gets chance 613 * to service its interrupt. 614 */ 615 if (!intr) { 616 mutex_exit(&ehcip->ehci_int_mutex); 617 618 return (DDI_INTR_UNCLAIMED); 619 } 620 621 /* Acknowledge the interrupt */ 622 Set_OpReg(ehci_status, intr); 623 624 if (ehcip->ehci_hc_soft_state == EHCI_CTLR_ERROR_STATE) { 625 mutex_exit(&ehcip->ehci_int_mutex); 626 627 return (DDI_INTR_CLAIMED); 628 } 629 630 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 631 "Interrupt status 0x%x", intr); 632 633 /* 634 * If necessary broadcast that an interrupt has occured. This 635 * is only necessary during controller init. 636 */ 637 if (ehcip->ehci_flags & EHCI_CV_INTR) { 638 ehcip->ehci_flags &= ~EHCI_CV_INTR; 639 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv); 640 } 641 642 /* Check for Frame List Rollover */ 643 if (intr & EHCI_INTR_FRAME_LIST_ROLLOVER) { 644 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 645 "ehci_intr: Frame List Rollover"); 646 647 ehci_handle_frame_list_rollover(ehcip); 648 649 /* VIA VT6202 looses EHCI_INTR_USB interrupts, workaround. */ 650 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) && 651 (ehci_vt62x2_workaround & EHCI_VIA_LOST_INTERRUPTS)) { 652 ehcip->ehci_missed_intr_sts |= EHCI_INTR_USB; 653 } 654 } 655 656 /* Check for Advance on Asynchronous Schedule */ 657 if (intr & EHCI_INTR_ASYNC_ADVANCE) { 658 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 659 "ehci_intr: Asynchronous Schedule Advance Notification"); 660 661 /* Disable async list advance interrupt */ 662 Set_OpReg(ehci_interrupt, 663 (Get_OpReg(ehci_interrupt) & ~EHCI_INTR_ASYNC_ADVANCE)); 664 665 /* 666 * Call cv_broadcast on every this interrupt to wakeup 667 * all the threads that are waiting the async list advance 668 * event. 669 */ 670 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv); 671 } 672 673 /* Always process completed itds */ 674 ehci_traverse_active_isoc_list(ehcip); 675 676 /* 677 * Check for any USB transaction completion notification. Also 678 * process any missed USB transaction completion interrupts. 679 */ 680 if ((intr & EHCI_INTR_USB) || (intr & EHCI_INTR_USB_ERROR) || 681 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB) || 682 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB_ERROR)) { 683 684 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 685 "ehci_intr: USB Transaction Completion Notification"); 686 687 /* Clear missed interrupts */ 688 if (ehcip->ehci_missed_intr_sts) { 689 ehcip->ehci_missed_intr_sts = 0; 690 } 691 692 /* Process completed qtds */ 693 ehci_traverse_active_qtd_list(ehcip); 694 } 695 696 /* Process endpoint reclamation list */ 697 if (ehcip->ehci_reclaim_list) { 698 ehci_handle_endpoint_reclaimation(ehcip); 699 } 700 701 /* Check for Host System Error */ 702 if (intr & EHCI_INTR_HOST_SYSTEM_ERROR) { 703 USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 704 "ehci_intr: Unrecoverable error"); 705 706 ehci_handle_ue(ehcip); 707 } 708 709 /* 710 * Read interrupt status register to make sure that any PIO 711 * store to clear the ISR has made it on the PCI bus before 712 * returning from its interrupt handler. 713 */ 714 (void) Get_OpReg(ehci_status); 715 716 /* Release the ehci global mutex */ 717 mutex_exit(&ehcip->ehci_int_mutex); 718 719 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 720 "Interrupt handling completed"); 721 722 return (DDI_INTR_CLAIMED); 723 } 724 725 726 /* 727 * EHCI HCDI entry points 728 * 729 * The Host Controller Driver Interfaces (HCDI) are the software interfaces 730 * between the Universal Serial Bus Layer (USBA) and the Host Controller 731 * Driver (HCD). The HCDI interfaces or entry points are subject to change. 732 */ 733 734 /* 735 * ehci_hcdi_pipe_open: 736 * 737 * Member of HCD Ops structure and called during client specific pipe open 738 * Add the pipe to the data structure representing the device and allocate 739 * bandwidth for the pipe if it is a interrupt or isochronous endpoint. 740 */ 741 int 742 ehci_hcdi_pipe_open( 743 usba_pipe_handle_data_t *ph, 744 usb_flags_t flags) 745 { 746 ehci_state_t *ehcip = ehci_obtain_state( 747 ph->p_usba_device->usb_root_hub_dip); 748 usb_ep_descr_t *epdt = &ph->p_ep; 749 int rval, error = USB_SUCCESS; 750 int kmflag = (flags & USB_FLAGS_SLEEP) ? 751 KM_SLEEP : KM_NOSLEEP; 752 uchar_t smask = 0; 753 uchar_t cmask = 0; 754 uint_t pnode = 0; 755 ehci_pipe_private_t *pp; 756 757 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 758 "ehci_hcdi_pipe_open: addr = 0x%x, ep%d", 759 ph->p_usba_device->usb_addr, 760 epdt->bEndpointAddress & USB_EP_NUM_MASK); 761 762 mutex_enter(&ehcip->ehci_int_mutex); 763 rval = ehci_state_is_operational(ehcip); 764 mutex_exit(&ehcip->ehci_int_mutex); 765 766 if (rval != USB_SUCCESS) { 767 768 return (rval); 769 } 770 771 /* 772 * Check and handle root hub pipe open. 773 */ 774 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 775 776 mutex_enter(&ehcip->ehci_int_mutex); 777 error = ehci_handle_root_hub_pipe_open(ph, flags); 778 mutex_exit(&ehcip->ehci_int_mutex); 779 780 return (error); 781 } 782 783 /* 784 * Opening of other pipes excluding root hub pipe are 785 * handled below. Check whether pipe is already opened. 786 */ 787 if (ph->p_hcd_private) { 788 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 789 "ehci_hcdi_pipe_open: Pipe is already opened"); 790 791 return (USB_FAILURE); 792 } 793 794 /* 795 * A portion of the bandwidth is reserved for the non-periodic 796 * transfers, i.e control and bulk transfers in each of one 797 * millisecond frame period & usually it will be 20% of frame 798 * period. Hence there is no need to check for the available 799 * bandwidth before adding the control or bulk endpoints. 800 * 801 * There is a need to check for the available bandwidth before 802 * adding the periodic transfers, i.e interrupt & isochronous, 803 * since all these periodic transfers are guaranteed transfers. 804 * Usually 80% of the total frame time is reserved for periodic 805 * transfers. 806 */ 807 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 808 809 mutex_enter(&ehcip->ehci_int_mutex); 810 mutex_enter(&ph->p_mutex); 811 812 error = ehci_allocate_bandwidth(ehcip, 813 ph, &pnode, &smask, &cmask); 814 815 if (error != USB_SUCCESS) { 816 817 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 818 "ehci_hcdi_pipe_open: Bandwidth allocation failed"); 819 820 mutex_exit(&ph->p_mutex); 821 mutex_exit(&ehcip->ehci_int_mutex); 822 823 return (error); 824 } 825 826 mutex_exit(&ph->p_mutex); 827 mutex_exit(&ehcip->ehci_int_mutex); 828 } 829 830 /* Create the HCD pipe private structure */ 831 pp = kmem_zalloc(sizeof (ehci_pipe_private_t), kmflag); 832 833 /* 834 * Return failure if ehci pipe private 835 * structure allocation fails. 836 */ 837 if (pp == NULL) { 838 839 mutex_enter(&ehcip->ehci_int_mutex); 840 841 /* Deallocate bandwidth */ 842 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 843 844 mutex_enter(&ph->p_mutex); 845 ehci_deallocate_bandwidth(ehcip, 846 ph, pnode, smask, cmask); 847 mutex_exit(&ph->p_mutex); 848 } 849 850 mutex_exit(&ehcip->ehci_int_mutex); 851 852 return (USB_NO_RESOURCES); 853 } 854 855 mutex_enter(&ehcip->ehci_int_mutex); 856 857 /* Save periodic nodes */ 858 pp->pp_pnode = pnode; 859 860 /* Save start and complete split mask values */ 861 pp->pp_smask = smask; 862 pp->pp_cmask = cmask; 863 864 /* Create prototype for xfer completion condition variable */ 865 cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL); 866 867 /* Set the state of pipe as idle */ 868 pp->pp_state = EHCI_PIPE_STATE_IDLE; 869 870 /* Store a pointer to the pipe handle */ 871 pp->pp_pipe_handle = ph; 872 873 mutex_enter(&ph->p_mutex); 874 875 /* Store the pointer in the pipe handle */ 876 ph->p_hcd_private = (usb_opaque_t)pp; 877 878 /* Store a copy of the pipe policy */ 879 bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t)); 880 881 mutex_exit(&ph->p_mutex); 882 883 /* Allocate the host controller endpoint descriptor */ 884 pp->pp_qh = ehci_alloc_qh(ehcip, ph, NULL); 885 886 /* Initialize the halting flag */ 887 pp->pp_halt_state = EHCI_HALT_STATE_FREE; 888 889 /* Create prototype for halt completion condition variable */ 890 cv_init(&pp->pp_halt_cmpl_cv, NULL, CV_DRIVER, NULL); 891 892 /* Isoch does not use QH, so ignore this */ 893 if ((pp->pp_qh == NULL) && !(EHCI_ISOC_ENDPOINT(epdt))) { 894 ASSERT(pp->pp_qh == NULL); 895 896 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 897 "ehci_hcdi_pipe_open: QH allocation failed"); 898 899 mutex_enter(&ph->p_mutex); 900 901 /* Deallocate bandwidth */ 902 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 903 904 ehci_deallocate_bandwidth(ehcip, 905 ph, pnode, smask, cmask); 906 } 907 908 /* Destroy the xfer completion condition variable */ 909 cv_destroy(&pp->pp_xfer_cmpl_cv); 910 911 /* 912 * Deallocate the hcd private portion 913 * of the pipe handle. 914 */ 915 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t)); 916 917 /* 918 * Set the private structure in the 919 * pipe handle equal to NULL. 920 */ 921 ph->p_hcd_private = NULL; 922 923 mutex_exit(&ph->p_mutex); 924 mutex_exit(&ehcip->ehci_int_mutex); 925 926 return (USB_NO_RESOURCES); 927 } 928 929 /* 930 * Isoch does not use QH so no need to 931 * restore data toggle or insert QH 932 */ 933 if (!(EHCI_ISOC_ENDPOINT(epdt))) { 934 /* Restore the data toggle information */ 935 ehci_restore_data_toggle(ehcip, ph); 936 } 937 938 /* 939 * Insert the endpoint onto the host controller's 940 * appropriate endpoint list. The host controller 941 * will not schedule this endpoint and will not have 942 * any QTD's to process. It will also update the pipe count. 943 */ 944 ehci_insert_qh(ehcip, ph); 945 946 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 947 "ehci_hcdi_pipe_open: ph = 0x%p", (void *)ph); 948 949 ehcip->ehci_open_pipe_count++; 950 951 mutex_exit(&ehcip->ehci_int_mutex); 952 953 return (USB_SUCCESS); 954 } 955 956 957 /* 958 * ehci_hcdi_pipe_close: 959 * 960 * Member of HCD Ops structure and called during the client specific pipe 961 * close. Remove the pipe and the data structure representing the device. 962 * Deallocate bandwidth for the pipe if it is a interrupt or isochronous 963 * endpoint. 964 */ 965 /* ARGSUSED */ 966 int 967 ehci_hcdi_pipe_close( 968 usba_pipe_handle_data_t *ph, 969 usb_flags_t flags) 970 { 971 ehci_state_t *ehcip = ehci_obtain_state( 972 ph->p_usba_device->usb_root_hub_dip); 973 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 974 usb_ep_descr_t *eptd = &ph->p_ep; 975 int error = USB_SUCCESS; 976 977 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 978 "ehci_hcdi_pipe_close: addr = 0x%x, ep%d", 979 ph->p_usba_device->usb_addr, 980 eptd->bEndpointAddress & USB_EP_NUM_MASK); 981 982 /* Check and handle root hub pipe close */ 983 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 984 985 mutex_enter(&ehcip->ehci_int_mutex); 986 error = ehci_handle_root_hub_pipe_close(ph); 987 mutex_exit(&ehcip->ehci_int_mutex); 988 989 return (error); 990 } 991 992 ASSERT(ph->p_hcd_private != NULL); 993 994 mutex_enter(&ehcip->ehci_int_mutex); 995 996 /* Set pipe state to pipe close */ 997 pp->pp_state = EHCI_PIPE_STATE_CLOSE; 998 999 ehci_pipe_cleanup(ehcip, ph); 1000 1001 /* 1002 * Remove the endpoint descriptor from Host 1003 * Controller's appropriate endpoint list. 1004 */ 1005 ehci_remove_qh(ehcip, pp, B_TRUE); 1006 1007 /* Deallocate bandwidth */ 1008 if (EHCI_PERIODIC_ENDPOINT(eptd)) { 1009 1010 mutex_enter(&ph->p_mutex); 1011 ehci_deallocate_bandwidth(ehcip, ph, pp->pp_pnode, 1012 pp->pp_smask, pp->pp_cmask); 1013 mutex_exit(&ph->p_mutex); 1014 } 1015 1016 mutex_enter(&ph->p_mutex); 1017 1018 /* Destroy the xfer completion condition variable */ 1019 cv_destroy(&pp->pp_xfer_cmpl_cv); 1020 1021 1022 /* Destory halt completion condition variable */ 1023 cv_destroy(&pp->pp_halt_cmpl_cv); 1024 1025 /* 1026 * Deallocate the hcd private portion 1027 * of the pipe handle. 1028 */ 1029 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t)); 1030 ph->p_hcd_private = NULL; 1031 1032 mutex_exit(&ph->p_mutex); 1033 1034 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1035 "ehci_hcdi_pipe_close: ph = 0x%p", (void *)ph); 1036 1037 ehcip->ehci_open_pipe_count--; 1038 1039 mutex_exit(&ehcip->ehci_int_mutex); 1040 1041 return (error); 1042 } 1043 1044 1045 /* 1046 * ehci_hcdi_pipe_reset: 1047 */ 1048 /* ARGSUSED */ 1049 int 1050 ehci_hcdi_pipe_reset( 1051 usba_pipe_handle_data_t *ph, 1052 usb_flags_t usb_flags) 1053 { 1054 ehci_state_t *ehcip = ehci_obtain_state( 1055 ph->p_usba_device->usb_root_hub_dip); 1056 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1057 int error = USB_SUCCESS; 1058 1059 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1060 "ehci_hcdi_pipe_reset:"); 1061 1062 /* 1063 * Check and handle root hub pipe reset. 1064 */ 1065 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1066 1067 error = ehci_handle_root_hub_pipe_reset(ph, usb_flags); 1068 return (error); 1069 } 1070 1071 mutex_enter(&ehcip->ehci_int_mutex); 1072 1073 /* Set pipe state to pipe reset */ 1074 pp->pp_state = EHCI_PIPE_STATE_RESET; 1075 1076 ehci_pipe_cleanup(ehcip, ph); 1077 1078 mutex_exit(&ehcip->ehci_int_mutex); 1079 1080 return (error); 1081 } 1082 1083 /* 1084 * ehci_hcdi_pipe_ctrl_xfer: 1085 */ 1086 int 1087 ehci_hcdi_pipe_ctrl_xfer( 1088 usba_pipe_handle_data_t *ph, 1089 usb_ctrl_req_t *ctrl_reqp, 1090 usb_flags_t usb_flags) 1091 { 1092 ehci_state_t *ehcip = ehci_obtain_state( 1093 ph->p_usba_device->usb_root_hub_dip); 1094 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1095 int rval; 1096 int error = USB_SUCCESS; 1097 ehci_trans_wrapper_t *tw; 1098 1099 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1100 "ehci_hcdi_pipe_ctrl_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1101 (void *)ph, ctrl_reqp, usb_flags); 1102 1103 mutex_enter(&ehcip->ehci_int_mutex); 1104 rval = ehci_state_is_operational(ehcip); 1105 mutex_exit(&ehcip->ehci_int_mutex); 1106 1107 if (rval != USB_SUCCESS) { 1108 1109 return (rval); 1110 } 1111 1112 /* 1113 * Check and handle root hub control request. 1114 */ 1115 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1116 1117 error = ehci_handle_root_hub_request(ehcip, ph, ctrl_reqp); 1118 1119 return (error); 1120 } 1121 1122 mutex_enter(&ehcip->ehci_int_mutex); 1123 1124 /* 1125 * Check whether pipe is in halted state. 1126 */ 1127 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) { 1128 1129 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1130 "ehci_hcdi_pipe_ctrl_xfer: " 1131 "Pipe is in error state, need pipe reset to continue"); 1132 1133 mutex_exit(&ehcip->ehci_int_mutex); 1134 1135 return (USB_FAILURE); 1136 } 1137 1138 /* Allocate a transfer wrapper */ 1139 if ((tw = ehci_allocate_ctrl_resources(ehcip, pp, ctrl_reqp, 1140 usb_flags)) == NULL) { 1141 1142 error = USB_NO_RESOURCES; 1143 } else { 1144 /* Insert the qtd's on the endpoint */ 1145 ehci_insert_ctrl_req(ehcip, ph, ctrl_reqp, tw, usb_flags); 1146 } 1147 1148 mutex_exit(&ehcip->ehci_int_mutex); 1149 1150 return (error); 1151 } 1152 1153 1154 /* 1155 * ehci_hcdi_bulk_transfer_size: 1156 * 1157 * Return maximum bulk transfer size 1158 */ 1159 1160 /* ARGSUSED */ 1161 int 1162 ehci_hcdi_bulk_transfer_size( 1163 usba_device_t *usba_device, 1164 size_t *size) 1165 { 1166 ehci_state_t *ehcip = ehci_obtain_state( 1167 usba_device->usb_root_hub_dip); 1168 int rval; 1169 1170 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1171 "ehci_hcdi_bulk_transfer_size:"); 1172 1173 mutex_enter(&ehcip->ehci_int_mutex); 1174 rval = ehci_state_is_operational(ehcip); 1175 mutex_exit(&ehcip->ehci_int_mutex); 1176 1177 if (rval != USB_SUCCESS) { 1178 1179 return (rval); 1180 } 1181 1182 /* VIA VT6202 may not handle bigger xfers well, workaround. */ 1183 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) && 1184 (ehci_vt62x2_workaround & EHCI_VIA_REDUCED_MAX_BULK_XFER_SIZE)) { 1185 *size = EHCI_VIA_MAX_BULK_XFER_SIZE; 1186 } else { 1187 *size = EHCI_MAX_BULK_XFER_SIZE; 1188 } 1189 1190 return (USB_SUCCESS); 1191 } 1192 1193 1194 /* 1195 * ehci_hcdi_pipe_bulk_xfer: 1196 */ 1197 int 1198 ehci_hcdi_pipe_bulk_xfer( 1199 usba_pipe_handle_data_t *ph, 1200 usb_bulk_req_t *bulk_reqp, 1201 usb_flags_t usb_flags) 1202 { 1203 ehci_state_t *ehcip = ehci_obtain_state( 1204 ph->p_usba_device->usb_root_hub_dip); 1205 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1206 int rval, error = USB_SUCCESS; 1207 ehci_trans_wrapper_t *tw; 1208 1209 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1210 "ehci_hcdi_pipe_bulk_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1211 (void *)ph, bulk_reqp, usb_flags); 1212 1213 mutex_enter(&ehcip->ehci_int_mutex); 1214 rval = ehci_state_is_operational(ehcip); 1215 1216 if (rval != USB_SUCCESS) { 1217 mutex_exit(&ehcip->ehci_int_mutex); 1218 1219 return (rval); 1220 } 1221 1222 /* 1223 * Check whether pipe is in halted state. 1224 */ 1225 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) { 1226 1227 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1228 "ehci_hcdi_pipe_bulk_xfer:" 1229 "Pipe is in error state, need pipe reset to continue"); 1230 1231 mutex_exit(&ehcip->ehci_int_mutex); 1232 1233 return (USB_FAILURE); 1234 } 1235 1236 /* Allocate a transfer wrapper */ 1237 if ((tw = ehci_allocate_bulk_resources(ehcip, pp, bulk_reqp, 1238 usb_flags)) == NULL) { 1239 1240 error = USB_NO_RESOURCES; 1241 } else { 1242 /* Add the QTD into the Host Controller's bulk list */ 1243 ehci_insert_bulk_req(ehcip, ph, bulk_reqp, tw, usb_flags); 1244 } 1245 1246 mutex_exit(&ehcip->ehci_int_mutex); 1247 1248 return (error); 1249 } 1250 1251 1252 /* 1253 * ehci_hcdi_pipe_intr_xfer: 1254 */ 1255 int 1256 ehci_hcdi_pipe_intr_xfer( 1257 usba_pipe_handle_data_t *ph, 1258 usb_intr_req_t *intr_reqp, 1259 usb_flags_t usb_flags) 1260 { 1261 ehci_state_t *ehcip = ehci_obtain_state( 1262 ph->p_usba_device->usb_root_hub_dip); 1263 int pipe_dir, rval, error = USB_SUCCESS; 1264 ehci_trans_wrapper_t *tw; 1265 1266 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1267 "ehci_hcdi_pipe_intr_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1268 (void *)ph, intr_reqp, usb_flags); 1269 1270 mutex_enter(&ehcip->ehci_int_mutex); 1271 rval = ehci_state_is_operational(ehcip); 1272 1273 if (rval != USB_SUCCESS) { 1274 mutex_exit(&ehcip->ehci_int_mutex); 1275 1276 return (rval); 1277 } 1278 1279 /* Get the pipe direction */ 1280 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1281 1282 if (pipe_dir == USB_EP_DIR_IN) { 1283 error = ehci_start_periodic_pipe_polling(ehcip, ph, 1284 (usb_opaque_t)intr_reqp, usb_flags); 1285 } else { 1286 /* Allocate transaction resources */ 1287 if ((tw = ehci_allocate_intr_resources(ehcip, ph, 1288 intr_reqp, usb_flags)) == NULL) { 1289 1290 error = USB_NO_RESOURCES; 1291 } else { 1292 ehci_insert_intr_req(ehcip, 1293 (ehci_pipe_private_t *)ph->p_hcd_private, 1294 tw, usb_flags); 1295 } 1296 } 1297 1298 mutex_exit(&ehcip->ehci_int_mutex); 1299 1300 return (error); 1301 } 1302 1303 /* 1304 * ehci_hcdi_pipe_stop_intr_polling() 1305 */ 1306 int 1307 ehci_hcdi_pipe_stop_intr_polling( 1308 usba_pipe_handle_data_t *ph, 1309 usb_flags_t flags) 1310 { 1311 ehci_state_t *ehcip = ehci_obtain_state( 1312 ph->p_usba_device->usb_root_hub_dip); 1313 int error = USB_SUCCESS; 1314 1315 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1316 "ehci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x", 1317 (void *)ph, flags); 1318 1319 mutex_enter(&ehcip->ehci_int_mutex); 1320 1321 error = ehci_stop_periodic_pipe_polling(ehcip, ph, flags); 1322 1323 mutex_exit(&ehcip->ehci_int_mutex); 1324 1325 return (error); 1326 } 1327 1328 1329 /* 1330 * ehci_hcdi_get_current_frame_number: 1331 * 1332 * Return the current usb frame number 1333 */ 1334 usb_frame_number_t 1335 ehci_hcdi_get_current_frame_number(usba_device_t *usba_device) 1336 { 1337 ehci_state_t *ehcip = ehci_obtain_state( 1338 usba_device->usb_root_hub_dip); 1339 usb_frame_number_t frame_number; 1340 int rval; 1341 1342 ehcip = ehci_obtain_state(usba_device->usb_root_hub_dip); 1343 1344 mutex_enter(&ehcip->ehci_int_mutex); 1345 rval = ehci_state_is_operational(ehcip); 1346 1347 if (rval != USB_SUCCESS) { 1348 mutex_exit(&ehcip->ehci_int_mutex); 1349 1350 return (rval); 1351 } 1352 1353 frame_number = ehci_get_current_frame_number(ehcip); 1354 1355 mutex_exit(&ehcip->ehci_int_mutex); 1356 1357 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1358 "ehci_hcdi_get_current_frame_number: " 1359 "Current frame number 0x%llx", frame_number); 1360 1361 return (frame_number); 1362 } 1363 1364 1365 /* 1366 * ehci_hcdi_get_max_isoc_pkts: 1367 * 1368 * Return maximum isochronous packets per usb isochronous request 1369 */ 1370 uint_t 1371 ehci_hcdi_get_max_isoc_pkts(usba_device_t *usba_device) 1372 { 1373 ehci_state_t *ehcip = ehci_obtain_state( 1374 usba_device->usb_root_hub_dip); 1375 uint_t max_isoc_pkts_per_request; 1376 int rval; 1377 1378 mutex_enter(&ehcip->ehci_int_mutex); 1379 rval = ehci_state_is_operational(ehcip); 1380 mutex_exit(&ehcip->ehci_int_mutex); 1381 1382 if (rval != USB_SUCCESS) { 1383 1384 return (rval); 1385 } 1386 1387 max_isoc_pkts_per_request = EHCI_MAX_ISOC_PKTS_PER_XFER; 1388 1389 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1390 "ehci_hcdi_get_max_isoc_pkts: maximum isochronous" 1391 "packets per usb isochronous request = 0x%x", 1392 max_isoc_pkts_per_request); 1393 1394 return (max_isoc_pkts_per_request); 1395 } 1396 1397 1398 /* 1399 * ehci_hcdi_pipe_isoc_xfer: 1400 */ 1401 int 1402 ehci_hcdi_pipe_isoc_xfer( 1403 usba_pipe_handle_data_t *ph, 1404 usb_isoc_req_t *isoc_reqp, 1405 usb_flags_t usb_flags) 1406 { 1407 ehci_state_t *ehcip = ehci_obtain_state( 1408 ph->p_usba_device->usb_root_hub_dip); 1409 1410 int pipe_dir, rval; 1411 ehci_isoc_xwrapper_t *itw; 1412 1413 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1414 "ehci_hcdi_pipe_isoc_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x", 1415 (void *)ph, isoc_reqp, usb_flags); 1416 1417 mutex_enter(&ehcip->ehci_int_mutex); 1418 rval = ehci_state_is_operational(ehcip); 1419 1420 if (rval != USB_SUCCESS) { 1421 mutex_exit(&ehcip->ehci_int_mutex); 1422 1423 return (rval); 1424 } 1425 1426 /* Get the isochronous pipe direction */ 1427 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1428 1429 if (pipe_dir == USB_EP_DIR_IN) { 1430 rval = ehci_start_periodic_pipe_polling(ehcip, ph, 1431 (usb_opaque_t)isoc_reqp, usb_flags); 1432 } else { 1433 /* Allocate transaction resources */ 1434 if ((itw = ehci_allocate_isoc_resources(ehcip, ph, 1435 isoc_reqp, usb_flags)) == NULL) { 1436 rval = USB_NO_RESOURCES; 1437 } else { 1438 rval = ehci_insert_isoc_req(ehcip, 1439 (ehci_pipe_private_t *)ph->p_hcd_private, 1440 itw, usb_flags); 1441 } 1442 } 1443 1444 mutex_exit(&ehcip->ehci_int_mutex); 1445 1446 return (rval); 1447 } 1448 1449 1450 /* 1451 * ehci_hcdi_pipe_stop_isoc_polling() 1452 */ 1453 /*ARGSUSED*/ 1454 int 1455 ehci_hcdi_pipe_stop_isoc_polling( 1456 usba_pipe_handle_data_t *ph, 1457 usb_flags_t flags) 1458 { 1459 ehci_state_t *ehcip = ehci_obtain_state( 1460 ph->p_usba_device->usb_root_hub_dip); 1461 int rval; 1462 1463 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1464 "ehci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x", 1465 (void *)ph, flags); 1466 1467 mutex_enter(&ehcip->ehci_int_mutex); 1468 rval = ehci_state_is_operational(ehcip); 1469 1470 if (rval != USB_SUCCESS) { 1471 mutex_exit(&ehcip->ehci_int_mutex); 1472 1473 return (rval); 1474 } 1475 1476 rval = ehci_stop_periodic_pipe_polling(ehcip, ph, flags); 1477 1478 mutex_exit(&ehcip->ehci_int_mutex); 1479 1480 return (rval); 1481 } 1482