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