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