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