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