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 * Universal Host Controller Driver (UHCI) 31 * 32 * The UHCI driver is a driver which interfaces to the Universal 33 * Serial Bus Architecture (USBA) and the Host Controller (HC). The interface to 34 * the Host Controller is defined by the Universal Host Controller Interface. 35 * This file contains code for auto-configuration entry points and interrupt 36 * handling. 37 */ 38 #include <sys/usb/hcd/uhci/uhcid.h> 39 #include <sys/usb/hcd/uhci/uhcihub.h> 40 #include <sys/usb/hcd/uhci/uhciutil.h> 41 42 /* 43 * Prototype Declarations for cb_ops and dev_ops 44 */ 45 static int uhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 46 static int uhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 47 static int uhci_open(dev_t *devp, int flags, int otyp, cred_t *credp); 48 static int uhci_close(dev_t dev, int flag, int otyp, cred_t *credp); 49 static int uhci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 50 cred_t *credp, int *rvalp); 51 static int uhci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd); 52 static int uhci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, 53 void **result); 54 55 static struct cb_ops uhci_cb_ops = { 56 uhci_open, /* Open */ 57 uhci_close, /* Close */ 58 nodev, /* Strategy */ 59 nodev, /* Print */ 60 nodev, /* Dump */ 61 nodev, /* Read */ 62 nodev, /* Write */ 63 uhci_ioctl, /* Ioctl */ 64 nodev, /* Devmap */ 65 nodev, /* Mmap */ 66 nodev, /* Segmap */ 67 nochpoll, /* Poll */ 68 ddi_prop_op, /* cb_prop_op */ 69 NULL, /* Streamtab */ 70 D_MP /* Driver compatibility flag */ 71 }; 72 73 static struct dev_ops uhci_ops = { 74 DEVO_REV, /* Devo_rev */ 75 0, /* Refcnt */ 76 uhci_info, /* Info */ 77 nulldev, /* Identify */ 78 nulldev, /* Probe */ 79 uhci_attach, /* Attach */ 80 uhci_detach, /* Detach */ 81 uhci_reset, /* Reset */ 82 &uhci_cb_ops, /* Driver operations */ 83 &usba_hubdi_busops, /* Bus operations */ 84 NULL /* Power */ 85 }; 86 87 static struct modldrv modldrv = { 88 &mod_driverops, /* Type of module. This one is a driver */ 89 "USB UHCI Controller Driver %I%", /* Name of the module. */ 90 &uhci_ops, /* Driver ops */ 91 }; 92 93 static struct modlinkage modlinkage = { 94 MODREV_1, (void *)&modldrv, NULL 95 }; 96 97 /* 98 * Globals 99 */ 100 void *uhci_statep; 101 static uint_t uhci_errlevel = USB_LOG_L2; 102 static uint_t uhci_errmask = PRINT_MASK_ALL; 103 static uint_t uhci_instance_debug = (uint_t)-1; 104 105 uint_t uhci_td_pool_size = 256; /* Num TDs */ 106 uint_t uhci_qh_pool_size = 130; /* Num QHs */ 107 ushort_t uhci_tree_bottom_nodes[NUM_FRAME_LST_ENTRIES]; 108 109 110 /* 111 * tunable, delay during attach in seconds 112 */ 113 static int uhci_attach_wait = 1; 114 115 /* function prototypes */ 116 static void uhci_handle_intr_td_errors(uhci_state_t *uhcip, uhci_td_t *td, 117 uhci_trans_wrapper_t *tw, uhci_pipe_private_t *pp); 118 static void uhci_handle_one_xfer_completion(uhci_state_t *uhcip, 119 usb_cr_t usb_err, uhci_td_t *td); 120 static uint_t uhci_intr(caddr_t arg); 121 static int uhci_cleanup(uhci_state_t *uhcip); 122 123 124 int 125 _init(void) 126 { 127 int error; 128 ushort_t i, j, k, *temp, num_of_nodes; 129 130 /* Initialize the soft state structures */ 131 if ((error = ddi_soft_state_init(&uhci_statep, sizeof (uhci_state_t), 132 UHCI_MAX_INSTS)) != 0) { 133 134 return (error); 135 } 136 137 /* Install the loadable module */ 138 if ((error = mod_install(&modlinkage)) != 0) { 139 ddi_soft_state_fini(&uhci_statep); 140 141 return (error); 142 } 143 144 /* 145 * Build the tree bottom shared by all instances 146 */ 147 temp = kmem_zalloc(NUM_FRAME_LST_ENTRIES * 2, KM_SLEEP); 148 149 num_of_nodes = 1; 150 for (i = 0; i < log_2(NUM_FRAME_LST_ENTRIES); i++) { 151 for (j = 0, k = 0; k < num_of_nodes; k++, j++) { 152 uhci_tree_bottom_nodes[j++] = temp[k]; 153 uhci_tree_bottom_nodes[j] = temp[k] + pow_2(i); 154 } 155 156 num_of_nodes *= 2; 157 for (k = 0; k < num_of_nodes; k++) 158 temp[k] = uhci_tree_bottom_nodes[k]; 159 160 } 161 kmem_free(temp, (NUM_FRAME_LST_ENTRIES*2)); 162 163 164 return (error); 165 } 166 167 168 int 169 _info(struct modinfo *modinfop) 170 { 171 return (mod_info(&modlinkage, modinfop)); 172 } 173 174 175 int 176 _fini(void) 177 { 178 int error; 179 180 error = mod_remove(&modlinkage); 181 182 if (error == 0) { 183 /* Release per module resources */ 184 ddi_soft_state_fini(&uhci_statep); 185 } 186 187 return (error); 188 } 189 190 191 /* 192 * Host Controller Driver (HCD) Auto configuration entry points 193 */ 194 195 /* 196 * Function Name : uhci_attach: 197 * Description : Attach entry point - called by the Kernel. 198 * Allocates of per controller data structure. 199 * Initializes the controller. 200 * Output : DDI_SUCCESS / DDI_FAILURE 201 */ 202 static int 203 uhci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 204 { 205 int instance; 206 int type, count, actual, ret; 207 uint_t intr_pri; 208 uhci_state_t *uhcip = NULL; 209 usba_hcdi_register_args_t hcdi_args; 210 211 USB_DPRINTF_L4(PRINT_MASK_ATTA, NULL, "uhci_attach:"); 212 213 switch (cmd) { 214 case DDI_ATTACH: 215 break; 216 case DDI_RESUME: 217 default: 218 219 return (DDI_FAILURE); 220 } 221 222 223 /* Get the instance and create soft state */ 224 instance = ddi_get_instance(dip); 225 226 /* Allocate the soft state structure for this instance of the driver */ 227 if (ddi_soft_state_zalloc(uhci_statep, instance) != 0) { 228 229 return (DDI_FAILURE); 230 } 231 232 if ((uhcip = ddi_get_soft_state(uhci_statep, instance)) == NULL) { 233 234 return (DDI_FAILURE); 235 } 236 237 uhcip->uhci_log_hdl = usb_alloc_log_hdl(dip, "uhci", &uhci_errlevel, 238 &uhci_errmask, &uhci_instance_debug, 0); 239 240 /* Save the dip and instance */ 241 uhcip->uhci_dip = dip; 242 uhcip->uhci_instance = instance; 243 244 /* Semaphore to serialize opens and closes */ 245 sema_init(&uhcip->uhci_ocsem, 1, NULL, SEMA_DRIVER, NULL); 246 247 ret = ddi_intr_get_supported_types(dip, &type); 248 if ((ret != DDI_SUCCESS) || (!(type & DDI_INTR_TYPE_FIXED))) { 249 USB_DPRINTF_L1(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 250 "Fixed type interrupts not supported"); 251 usb_free_log_hdl(uhcip->uhci_log_hdl); 252 ddi_soft_state_free(uhci_statep, instance); 253 254 return (DDI_FAILURE); 255 } 256 257 ret = ddi_intr_get_nintrs(dip, DDI_INTR_TYPE_FIXED, &count); 258 259 /* 260 * Fixed interrupts can only have one interrupt. Check to make 261 * sure that number of supported interrupts and number of 262 * available interrupts are both equal to 1. 263 */ 264 if ((ret != DDI_SUCCESS) || (count != 1)) { 265 USB_DPRINTF_L1(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 266 "No Fixed interrupts found"); 267 usb_free_log_hdl(uhcip->uhci_log_hdl); 268 ddi_soft_state_free(uhci_statep, instance); 269 270 return (DDI_FAILURE); 271 } 272 273 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 274 "Supported Intr types = 0x%x, #Intrs = 0x%x", type, count); 275 uhcip->uhci_htable = kmem_zalloc(count * sizeof (ddi_intr_handle_t), 276 KM_SLEEP); 277 278 ret = ddi_intr_alloc(dip, uhcip->uhci_htable, DDI_INTR_TYPE_FIXED, 0, 279 count, 280 &actual, 0); 281 if ((ret != DDI_SUCCESS) || (actual != 1)) { 282 USB_DPRINTF_L1(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 283 "ddi_intr_alloc failed 0x%x", ret); 284 kmem_free(uhcip->uhci_htable, sizeof (ddi_intr_handle_t)); 285 usb_free_log_hdl(uhcip->uhci_log_hdl); 286 ddi_soft_state_free(uhci_statep, instance); 287 288 return (DDI_FAILURE); 289 } 290 291 ret = ddi_intr_get_pri(uhcip->uhci_htable[0], &intr_pri); 292 if (ret != DDI_SUCCESS) { 293 USB_DPRINTF_L1(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 294 "ddi_intr_get_pri failed 0x%x", ret); 295 (void) ddi_intr_free(uhcip->uhci_htable[0]); 296 kmem_free(uhcip->uhci_htable, sizeof (ddi_intr_handle_t)); 297 usb_free_log_hdl(uhcip->uhci_log_hdl); 298 ddi_soft_state_free(uhci_statep, instance); 299 300 return (DDI_FAILURE); 301 } 302 303 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 304 "Supported Interrupt priority = 0x%x", intr_pri); 305 306 if (intr_pri >= ddi_intr_get_hilevel_pri()) { 307 USB_DPRINTF_L1(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 308 "Hi level interrupt not supported"); 309 (void) ddi_intr_free(uhcip->uhci_htable[0]); 310 kmem_free(uhcip->uhci_htable, sizeof (ddi_intr_handle_t)); 311 usb_free_log_hdl(uhcip->uhci_log_hdl); 312 ddi_soft_state_free(uhci_statep, instance); 313 314 return (DDI_FAILURE); 315 } 316 317 /* Initialize the mutex */ 318 mutex_init(&uhcip->uhci_int_mutex, NULL, MUTEX_DRIVER, 319 (void *)(uintptr_t)intr_pri); 320 321 /* Create prototype condition variable */ 322 cv_init(&uhcip->uhci_cv_SOF, NULL, CV_DRIVER, NULL); 323 324 ret = ddi_intr_add_handler(uhcip->uhci_htable[0], 325 (ddi_intr_handler_t *)uhci_intr, (caddr_t)uhcip, NULL); 326 if (ret != DDI_SUCCESS) { 327 USB_DPRINTF_L1(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 328 "ddi_intr_add_handler failed 0x%x", ret); 329 330 goto fail; 331 } 332 333 /* Initialize the DMA attributes */ 334 uhci_set_dma_attributes(uhcip); 335 336 /* Initialize the kstat structures */ 337 uhci_create_stats(uhcip); 338 339 /* Create the td and ed pools */ 340 if (uhci_allocate_pools(uhcip) != USB_SUCCESS) { 341 342 goto fail; 343 } 344 345 /* Map the registers */ 346 if (uhci_map_regs(uhcip) != USB_SUCCESS) { 347 348 goto fail; 349 } 350 351 /* Set the flag that uhci controller has not been initialized. */ 352 uhcip->uhci_ctlr_init_flag = B_FALSE; 353 354 /* finally enable the interrupt */ 355 ret = ddi_intr_enable(uhcip->uhci_htable[0]); 356 if (ret != DDI_SUCCESS) { 357 USB_DPRINTF_L1(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 358 "ddi_intr_enable failed 0x%x", ret); 359 360 goto fail; 361 } 362 363 /* Initialize the controller */ 364 if (uhci_init_ctlr(uhcip) != USB_SUCCESS) { 365 366 goto fail; 367 } 368 369 /* 370 * At this point, the hardware will be okay. 371 * Initialize the usba_hcdi structure 372 */ 373 uhcip->uhci_hcdi_ops = uhci_alloc_hcdi_ops(uhcip); 374 375 /* 376 * Make this HCD instance known to USBA 377 * (dma_attr must be passed for USBA busctl's) 378 */ 379 hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION; 380 hcdi_args.usba_hcdi_register_dip = dip; 381 hcdi_args.usba_hcdi_register_ops = uhcip->uhci_hcdi_ops; 382 hcdi_args.usba_hcdi_register_dma_attr = &uhcip->uhci_dma_attr; 383 hcdi_args.usba_hcdi_register_iblock_cookie = 384 (ddi_iblock_cookie_t)(uintptr_t)intr_pri; 385 386 if (usba_hcdi_register(&hcdi_args, 0) != USB_SUCCESS) { 387 388 goto fail; 389 } 390 391 #ifndef __sparc 392 /* 393 * On NCR system, the driver seen failure of some commands 394 * while booting. This delay mysteriously solved the problem. 395 */ 396 delay(drv_usectohz(uhci_attach_wait*1000000)); 397 #endif 398 399 /* 400 * Create another timeout handler to check whether any 401 * control/bulk/interrupt commands failed. 402 * This gets called every second. 403 */ 404 uhcip->uhci_cmd_timeout_id = timeout(uhci_cmd_timeout_hdlr, 405 (void *)uhcip, UHCI_ONE_SECOND); 406 407 mutex_enter(&uhcip->uhci_int_mutex); 408 409 /* 410 * Set HcInterruptEnable to enable all interrupts except Root 411 * Hub Status change and SOF interrupts. 412 */ 413 Set_OpReg16(USBINTR, ENABLE_ALL_INTRS); 414 415 /* Test the SOF interrupt */ 416 if (uhci_wait_for_sof(uhcip) != USB_SUCCESS) { 417 USB_DPRINTF_L0(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 418 "No SOF interrupts have been received, this USB UHCI host" 419 " controller is unusable"); 420 mutex_exit(&uhcip->uhci_int_mutex); 421 422 goto fail; 423 } 424 425 mutex_exit(&uhcip->uhci_int_mutex); 426 427 /* This should be the last step which might fail during attaching */ 428 if (uhci_init_root_hub(uhcip) != USB_SUCCESS) { 429 430 goto fail; 431 } 432 433 /* Display information in the banner */ 434 ddi_report_dev(dip); 435 436 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 437 "uhci_attach successful"); 438 439 return (DDI_SUCCESS); 440 441 fail: 442 USB_DPRINTF_L1(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 443 "failed to attach"); 444 445 (void) uhci_cleanup(uhcip); 446 447 return (DDI_FAILURE); 448 } 449 450 451 /* 452 * Function Name: uhci_detach 453 * Description: Detach entry point - called by the Kernel. 454 * Deallocates all the memory 455 * Unregisters the interrupt handle and other resources. 456 * Output: DDI_SUCCESS / DDI_FAILURE 457 */ 458 static int 459 uhci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 460 { 461 uhci_state_t *uhcip = uhci_obtain_state(dip); 462 463 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 464 "uhci_detach:"); 465 466 switch (cmd) { 467 case DDI_DETACH: 468 469 return (uhci_cleanup(uhcip) == USB_SUCCESS ? 470 DDI_SUCCESS : DDI_FAILURE); 471 case DDI_SUSPEND: 472 USB_DPRINTF_L1(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, 473 "uhci_detach: Suspend not supported"); 474 475 return (DDI_FAILURE); 476 default: 477 478 return (DDI_FAILURE); 479 } 480 } 481 482 483 /* 484 * Function Name: uhci_reset 485 * Description: Reset entry point - called by the Kernel 486 * on the way down. 487 * The Toshiba laptop has been observed to hang 488 * on reboot when BIOS is set to suspend/resume. 489 * The resetting uhci on the way down solves the 490 * problem. 491 * Output: DDI_SUCCESS / DDI_FAILURE 492 */ 493 /* ARGSUSED */ 494 static int 495 uhci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd) 496 { 497 uhci_state_t *uhcip = uhci_obtain_state(dip); 498 499 /* Disable all HC ED list processing */ 500 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); 501 Set_OpReg16(USBCMD, 0); 502 503 return (DDI_SUCCESS); 504 } 505 506 507 /* 508 * uhci_info: 509 */ 510 /* ARGSUSED */ 511 static int 512 uhci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 513 { 514 dev_t dev; 515 int instance; 516 int error = DDI_FAILURE; 517 uhci_state_t *uhcip; 518 519 switch (infocmd) { 520 case DDI_INFO_DEVT2DEVINFO: 521 dev = (dev_t)arg; 522 instance = UHCI_UNIT(dev); 523 uhcip = ddi_get_soft_state(uhci_statep, instance); 524 if (uhcip != NULL) { 525 *result = (void *)uhcip->uhci_dip; 526 if (*result != NULL) { 527 error = DDI_SUCCESS; 528 } 529 } else { 530 *result = NULL; 531 } 532 533 break; 534 case DDI_INFO_DEVT2INSTANCE: 535 dev = (dev_t)arg; 536 instance = UHCI_UNIT(dev); 537 *result = (void *)(uintptr_t)instance; 538 error = DDI_SUCCESS; 539 540 break; 541 default: 542 break; 543 } 544 545 return (error); 546 } 547 548 549 /* 550 * uhci_cleanup: 551 * Cleanup on attach failure or detach 552 */ 553 static int 554 uhci_cleanup(uhci_state_t *uhcip) 555 { 556 USB_DPRINTF_L4(PRINT_MASK_ATTA, uhcip->uhci_log_hdl, "uhci_cleanup:"); 557 558 if (usba_hubdi_unbind_root_hub(uhcip->uhci_dip) != USB_SUCCESS) { 559 560 return (USB_FAILURE); 561 } 562 563 mutex_enter(&uhcip->uhci_int_mutex); 564 565 if (uhcip->uhci_cmd_timeout_id) { 566 timeout_id_t timeout_id = uhcip->uhci_cmd_timeout_id; 567 uhcip->uhci_cmd_timeout_id = 0; 568 mutex_exit(&uhcip->uhci_int_mutex); 569 (void) untimeout(timeout_id); 570 mutex_enter(&uhcip->uhci_int_mutex); 571 } 572 573 uhci_uninit_ctlr(uhcip); 574 575 mutex_exit(&uhcip->uhci_int_mutex); 576 577 /* do interrupt cleanup */ 578 if (uhcip->uhci_htable[0]) { 579 /* disable interrupt */ 580 (void) ddi_intr_disable(uhcip->uhci_htable[0]); 581 582 /* remove interrupt handler */ 583 (void) ddi_intr_remove_handler(uhcip->uhci_htable[0]); 584 585 /* free interrupt handle */ 586 (void) ddi_intr_free(uhcip->uhci_htable[0]); 587 588 /* free memory */ 589 kmem_free(uhcip->uhci_htable, sizeof (ddi_intr_handle_t)); 590 } 591 592 mutex_enter(&uhcip->uhci_int_mutex); 593 594 usba_hcdi_unregister(uhcip->uhci_dip); 595 596 uhci_unmap_regs(uhcip); 597 598 uhci_free_pools(uhcip); 599 600 mutex_exit(&uhcip->uhci_int_mutex); 601 602 mutex_destroy(&uhcip->uhci_int_mutex); 603 cv_destroy(&uhcip->uhci_cv_SOF); 604 sema_destroy(&uhcip->uhci_ocsem); 605 606 /* cleanup kstat structures */ 607 uhci_destroy_stats(uhcip); 608 609 usba_free_hcdi_ops(uhcip->uhci_hcdi_ops); 610 usb_free_log_hdl(uhcip->uhci_log_hdl); 611 ddi_prop_remove_all(uhcip->uhci_dip); 612 ddi_soft_state_free(uhci_statep, uhcip->uhci_instance); 613 614 return (USB_SUCCESS); 615 } 616 617 618 /* 619 * uhci_intr: 620 * uhci interrupt handling routine. 621 */ 622 static uint_t 623 uhci_intr(caddr_t arg) 624 { 625 ushort_t intr_status, cmd_reg; 626 uhci_state_t *uhcip = (uhci_state_t *)arg; 627 628 mutex_enter(&uhcip->uhci_int_mutex); 629 630 /* Get the status of the interrupts */ 631 intr_status = Get_OpReg16(USBSTS); 632 633 USB_DPRINTF_L4(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 634 "uhci_intr: intr_status = %x", intr_status); 635 636 /* 637 * If the intr is not from our controller, just return unclaimed 638 */ 639 if (!(intr_status & UHCI_INTR_MASK)) { 640 641 USB_DPRINTF_L3(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 642 "uhci_intr: unclaimed interrupt"); 643 mutex_exit(&uhcip->uhci_int_mutex); 644 645 return (DDI_INTR_UNCLAIMED); 646 } 647 648 /* Update kstat values */ 649 uhci_do_intrs_stats(uhcip, intr_status); 650 651 /* Acknowledge the interrupt */ 652 Set_OpReg16(USBSTS, intr_status); 653 654 /* 655 * If uhci controller has not been initialized, just clear the 656 * interrupter status and return claimed. 657 */ 658 if (uhcip->uhci_ctlr_init_flag != B_TRUE) { 659 660 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 661 "uhci_intr: uhci controller has not been fully" 662 "initialized"); 663 mutex_exit(&uhcip->uhci_int_mutex); 664 665 return (DDI_INTR_CLAIMED); 666 } 667 668 /* 669 * We configured the hw incorrectly, disable future interrupts. 670 */ 671 if ((intr_status & USBSTS_REG_HOST_SYS_ERR)) { 672 USB_DPRINTF_L1(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 673 "uhci_intr: Sys Err Disabling Interrupt"); 674 Set_OpReg16(USBINTR, DISABLE_ALL_INTRS); 675 mutex_exit(&uhcip->uhci_int_mutex); 676 677 return (DDI_INTR_CLAIMED); 678 } 679 680 /* 681 * Check whether a frame number overflow occurred. 682 * if so, update the sw frame number. 683 */ 684 uhci_isoc_update_sw_frame_number(uhcip); 685 686 /* 687 * Check whether any commands got completed. If so, process them. 688 */ 689 uhci_process_submitted_td_queue(uhcip); 690 691 /* 692 * This should not occur. It occurs only if a HC controller 693 * experiences internal problem. 694 */ 695 if (intr_status & USBSTS_REG_HC_HALTED) { 696 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 697 "uhci_intr: Controller halted"); 698 cmd_reg = Get_OpReg16(USBCMD); 699 Set_OpReg16(USBCMD, (cmd_reg | USBCMD_REG_HC_RUN)); 700 } 701 702 /* 703 * Wake up all the threads which are waiting for the Start of Frame 704 */ 705 if (uhcip->uhci_cv_signal == B_TRUE) { 706 cv_broadcast(&uhcip->uhci_cv_SOF); 707 uhcip->uhci_cv_signal = B_FALSE; 708 } 709 710 mutex_exit(&uhcip->uhci_int_mutex); 711 712 return (DDI_INTR_CLAIMED); 713 } 714 715 716 /* 717 * uhci_process_submitted_td_queue: 718 * Traverse thru the submitted queue and process the completed ones. 719 */ 720 void 721 uhci_process_submitted_td_queue(uhci_state_t *uhcip) 722 { 723 uhci_td_t *head = uhcip->uhci_outst_tds_head; 724 uhci_trans_wrapper_t *tw; 725 726 while (head != NULL) { 727 if ((!(GetTD_status(uhcip, head) & UHCI_TD_ACTIVE)) && 728 (head->tw->tw_claim == UHCI_NOT_CLAIMED)) { 729 tw = head->tw; 730 731 /* 732 * Call the corresponding handle_td routine 733 */ 734 (*tw->tw_handle_td)(uhcip, head); 735 736 /* restart at the beginning again */ 737 head = uhcip->uhci_outst_tds_head; 738 } else { 739 head = head->outst_td_next; 740 } 741 } 742 } 743 744 745 /* 746 * uhci_handle_intr_td: 747 * handles the completed interrupt transfer TD's. 748 */ 749 void 750 uhci_handle_intr_td(uhci_state_t *uhcip, uhci_td_t *td) 751 { 752 usb_req_attrs_t attrs; 753 uint_t bytes_xfered; 754 usb_cr_t usb_err; 755 uhci_trans_wrapper_t *tw = td->tw; 756 uhci_pipe_private_t *pp = tw->tw_pipe_private; 757 usb_intr_req_t *intr_reqp = 758 (usb_intr_req_t *)tw->tw_curr_xfer_reqp; 759 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 760 761 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 762 "uhci_handle_intr_td: intr_reqp = 0x%p", (void *)intr_reqp); 763 764 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 765 766 /* set tw->tw_claim flag, so that nobody else works on this td. */ 767 tw->tw_claim = UHCI_INTR_HDLR_CLAIMED; 768 769 /* Interrupt OUT */ 770 if (UHCI_XFER_DIR(&ph->p_ep) == USB_EP_DIR_OUT) { 771 772 /* process errors first */ 773 usb_err = uhci_parse_td_error(uhcip, pp, td); 774 775 /* get the actual xfered data size */ 776 bytes_xfered = GetTD_alen(uhcip, td); 777 778 /* check data underrun error */ 779 if ((usb_err == USB_CR_OK) && (bytes_xfered != 780 GetTD_mlen(uhcip, td))) { 781 782 USB_DPRINTF_L2(PRINT_MASK_LISTS, 783 uhcip->uhci_log_hdl, "uhci_handle_intr_td:" 784 " Intr out pipe, data underrun occurred"); 785 786 usb_err = USB_CR_DATA_UNDERRUN; 787 788 } 789 790 bytes_xfered = (bytes_xfered == ZERO_LENGTH) ? 791 0 : bytes_xfered+1; 792 tw->tw_bytes_xfered += bytes_xfered; 793 uhci_do_byte_stats(uhcip, tw->tw_bytes_xfered, 794 ph->p_ep.bmAttributes, ph->p_ep.bEndpointAddress); 795 796 797 /* 798 * If error occurred or all data xfered, delete the current td, 799 * free tw, do the callback. Otherwise wait for the next td. 800 */ 801 if (usb_err != USB_CR_OK) { 802 803 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 804 "uhci_handle_intr_td: Intr out pipe error"); 805 806 /* update the element pointer */ 807 SetQH32(uhcip, pp->pp_qh->element_ptr, GetTD32( 808 uhcip, tw->tw_hctd_tail->link_ptr)); 809 810 811 } else if (tw->tw_bytes_xfered == tw->tw_length) { 812 813 /* all data xfered */ 814 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 815 "uhci_handle_intr_td: Intr out pipe," 816 " all data xfered"); 817 818 } else { 819 820 /* remove the current td and wait for the next one. */ 821 uhci_delete_td(uhcip, td); 822 tw->tw_claim = UHCI_NOT_CLAIMED; 823 824 return; 825 } 826 827 uhci_delete_td(uhcip, td); 828 uhci_hcdi_callback(uhcip, pp, ph, tw, usb_err); 829 uhci_deallocate_tw(uhcip, tw->tw_pipe_private, tw); 830 831 return; 832 } 833 834 /* Interrupt IN */ 835 836 /* Get the actual received data size */ 837 tw->tw_bytes_xfered = GetTD_alen(uhcip, td); 838 if (tw->tw_bytes_xfered == ZERO_LENGTH) { 839 tw->tw_bytes_xfered = 0; 840 } else { 841 tw->tw_bytes_xfered++; 842 } 843 844 /* process errors first */ 845 if (GetTD_status(uhcip, td) & TD_STATUS_MASK) { 846 SetQH32(uhcip, pp->pp_qh->element_ptr, 847 GetTD32(uhcip, td->link_ptr)); 848 849 uhci_handle_intr_td_errors(uhcip, td, tw, pp); 850 851 return; 852 } 853 854 /* 855 * Check for data underruns. 856 * For data underrun case, the host controller does not update 857 * element pointer. So, we update here. 858 */ 859 if (GetTD_alen(uhcip, td) != GetTD_mlen(uhcip, td)) { 860 SetQH32(uhcip, pp->pp_qh->element_ptr, 861 GetTD32(uhcip, td->link_ptr)); 862 } 863 864 /* 865 * Call uhci_sendup_td_message to send message upstream. 866 * The function uhci_sendup_td_message returns USB_NO_RESOURCES 867 * if allocb fails and also sends error message to upstream by 868 * calling USBA callback function. Under error conditions just 869 * drop the current message. 870 */ 871 872 /* Get the interrupt xfer attributes */ 873 attrs = intr_reqp->intr_attributes; 874 875 /* 876 * Check usb flag whether USB_FLAGS_ONE_XFER flag is set 877 * and if so, free duplicate request. 878 */ 879 if (attrs & USB_ATTRS_ONE_XFER) { 880 uhci_handle_one_xfer_completion(uhcip, USB_CR_OK, td); 881 882 return; 883 } 884 885 /* save it temporarily */ 886 if (tw->tw_bytes_xfered != 0) { 887 uhci_sendup_td_message(uhcip, USB_CR_OK, tw); 888 } 889 890 /* Clear the tw->tw_claim flag */ 891 tw->tw_claim = UHCI_NOT_CLAIMED; 892 893 uhci_delete_td(uhcip, td); 894 895 /* allocate another interrupt periodic resource */ 896 if (pp->pp_state == UHCI_PIPE_STATE_ACTIVE) { 897 if (uhci_allocate_periodic_in_resource(uhcip, pp, tw, 0) != 898 USB_SUCCESS) { 899 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 900 "uhci_insert_intr_req: Interrupt request structure" 901 "allocation failed"); 902 903 uhci_hcdi_callback(uhcip, pp, ph, 904 tw, USB_CR_NO_RESOURCES); 905 906 return; 907 } 908 909 /* Insert another interrupt TD */ 910 if (uhci_insert_hc_td(uhcip, tw->tw_cookie.dmac_address, 911 tw->tw_length, pp, tw, PID_IN, attrs) != USB_SUCCESS) { 912 913 uhci_deallocate_periodic_in_resource(uhcip, pp, tw); 914 915 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 916 "uhci_handle_intr_td: TD exhausted"); 917 918 uhci_hcdi_callback(uhcip, pp, ph, 919 tw, USB_CR_NO_RESOURCES); 920 } 921 } 922 } 923 924 925 /* 926 * uhci_sendup_td_message: 927 * 928 * Get a message block and send the received message upstream. 929 */ 930 void 931 uhci_sendup_td_message( 932 uhci_state_t *uhcip, 933 usb_cr_t usb_err, 934 uhci_trans_wrapper_t *tw) 935 { 936 mblk_t *mp = NULL; 937 size_t length = 0; 938 size_t skip_len = 0; 939 uchar_t *buf; 940 usb_opaque_t curr_xfer_reqp = tw->tw_curr_xfer_reqp; 941 uhci_pipe_private_t *pp = tw->tw_pipe_private; 942 usb_ep_descr_t *ept = &pp->pp_pipe_handle->p_ep; 943 944 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 945 946 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 947 "uhci_sendup_td_message: bytes transferred=0x%x, " 948 "bytes pending=0x%x", 949 tw->tw_bytes_xfered, tw->tw_bytes_pending); 950 951 length = tw->tw_bytes_xfered; 952 953 switch (UHCI_XFER_TYPE(ept)) { 954 case USB_EP_ATTR_CONTROL: 955 skip_len = SETUP_SIZE; /* length of the buffer to skip */ 956 mp = ((usb_ctrl_req_t *)curr_xfer_reqp)->ctrl_data; 957 break; 958 case USB_EP_ATTR_INTR: 959 mp = ((usb_intr_req_t *)curr_xfer_reqp)->intr_data; 960 break; 961 case USB_EP_ATTR_BULK: 962 mp = ((usb_bulk_req_t *)curr_xfer_reqp)->bulk_data; 963 break; 964 case USB_EP_ATTR_ISOCH: 965 length = tw->tw_length; 966 mp = ((usb_isoc_req_t *)curr_xfer_reqp)->isoc_data; 967 break; 968 default: 969 break; 970 } 971 972 /* Copy the data into the mblk_t */ 973 buf = (uchar_t *)tw->tw_buf + skip_len; 974 975 ASSERT(mp != NULL); 976 977 /* 978 * Update kstat byte counts 979 * The control endpoints don't have direction bits so in 980 * order for control stats to be counted correctly an IN 981 * bit must be faked on a control read. 982 */ 983 uhci_do_byte_stats(uhcip, length, ept->bmAttributes, 984 (UHCI_XFER_TYPE(ept) == USB_EP_ATTR_CONTROL) ? 985 USB_EP_DIR_IN : ept->bEndpointAddress); 986 987 if (length) { 988 int rval; 989 990 /* Sync the streaming buffer */ 991 rval = ddi_dma_sync(tw->tw_dmahandle, 0, length, 992 DDI_DMA_SYNC_FORCPU); 993 ASSERT(rval == DDI_SUCCESS); 994 995 /* Copy the data into the message */ 996 ddi_rep_get8(tw->tw_accesshandle, 997 mp->b_rptr, buf, length, DDI_DEV_AUTOINCR); 998 999 /* Increment the write pointer */ 1000 mp->b_wptr += length; 1001 } else { 1002 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1003 "uhci_sendup_td_message: Zero length packet"); 1004 } 1005 1006 /* Do the callback */ 1007 uhci_hcdi_callback(uhcip, pp, pp->pp_pipe_handle, tw, usb_err); 1008 } 1009 1010 1011 /* 1012 * uhci_handle_ctrl_td: 1013 * Handle a control Transfer Descriptor (TD). 1014 */ 1015 void 1016 uhci_handle_ctrl_td(uhci_state_t *uhcip, uhci_td_t *td) 1017 { 1018 ushort_t direction; 1019 ushort_t bytes_for_xfer; 1020 ushort_t bytes_xfered; 1021 ushort_t MaxPacketSize; 1022 usb_cr_t error; 1023 uhci_trans_wrapper_t *tw = td->tw; 1024 uhci_pipe_private_t *pp = tw->tw_pipe_private; 1025 usba_pipe_handle_data_t *usb_pp = pp->pp_pipe_handle; 1026 usb_ep_descr_t *eptd = &usb_pp->p_ep; 1027 usb_ctrl_req_t *reqp = (usb_ctrl_req_t *)tw->tw_curr_xfer_reqp; 1028 1029 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1030 "uhci_handle_ctrl_td: pp = 0x%p tw = 0x%p td = 0x%p " 1031 "state = 0x%x len = 0x%lx", (void *)pp, (void *)tw, 1032 (void *)td, tw->tw_ctrl_state, tw->tw_length); 1033 1034 ASSERT(mutex_owned(&uhcip->uhci_int_mutex)); 1035 1036 error = uhci_parse_td_error(uhcip, pp, td); 1037 1038 /* 1039 * In case of control transfers, the device can send NAK when it 1040 * is busy. If a NAK is received, then send the status TD again. 1041 */ 1042 if (error != USB_CR_OK) { 1043 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1044 "uhci_handle_ctrl_td: Ctrl cmd failed, error = %x", error); 1045 1046 SetQH32(uhcip, pp->pp_qh->element_ptr, 1047 GetTD32(uhcip, td->link_ptr)); 1048 uhci_delete_td(uhcip, td); 1049 1050 /* Return number of bytes xfered */ 1051 if (GetTD_alen(uhcip, td) != ZERO_LENGTH) { 1052 tw->tw_bytes_xfered = GetTD_alen(uhcip, td) + 1; 1053 } 1054 1055 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1056 "uhci_handle_ctrl_td: Bytes transferred = %x", 1057 tw->tw_bytes_xfered); 1058 1059 if ((tw->tw_ctrl_state == DATA) && 1060 (tw->tw_direction == PID_IN)) { 1061 uhci_sendup_td_message(uhcip, error, tw); 1062 } else { 1063 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, error); 1064 1065 uhci_deallocate_tw(uhcip, pp, tw); 1066 } 1067 1068 return; 1069 } 1070 1071 /* 1072 * A control transfer consists of three phases: 1073 * - Setup 1074 * - Data (optional) 1075 * - Status 1076 * 1077 * There is a TD per phase. A TD for a given phase isn't 1078 * enqueued until the previous phase is finished. 1079 */ 1080 switch (tw->tw_ctrl_state) { 1081 case SETUP: 1082 /* 1083 * Enqueue either the data or the status 1084 * phase depending on the length. 1085 */ 1086 pp->pp_data_toggle = 1; 1087 uhci_delete_td(uhcip, td); 1088 1089 /* 1090 * If the length is 0, move to the status. 1091 * If length is not 0, then we have some data 1092 * to move on the bus to device either IN or OUT. 1093 */ 1094 if ((tw->tw_length - SETUP_SIZE) == 0) { 1095 /* 1096 * There is no data stage, then 1097 * initiate status phase from the host. 1098 */ 1099 if ((uhci_insert_hc_td(uhcip, NULL, 0, pp, tw, PID_IN, 1100 reqp->ctrl_attributes)) != USB_SUCCESS) { 1101 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1102 uhcip->uhci_log_hdl, 1103 "uhci_handle_ctrl_td: No resources"); 1104 1105 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, 1106 USB_CR_NO_RESOURCES); 1107 1108 return; 1109 } 1110 1111 tw->tw_ctrl_state = STATUS; 1112 } else { 1113 uint_t xx; 1114 1115 /* 1116 * Each USB device can send/receive 8/16/32/64 1117 * depending on wMaxPacketSize's implementation. 1118 * We need to insert 'N = Number of byte/ 1119 * MaxpktSize" TD's in the lattice to send/ 1120 * receive the data. Though the USB protocol 1121 * allows to insert more than one TD in the same 1122 * frame, we are inserting only one TD in one 1123 * frame. This is bcos OHCI has seen some problem 1124 * when multiple TD's are inserted at the same time. 1125 */ 1126 tw->tw_length -= 8; 1127 MaxPacketSize = eptd->wMaxPacketSize; 1128 1129 /* 1130 * We dont know the maximum packet size that 1131 * the device can handle(MaxPAcketSize=0). 1132 * In that case insert a data phase with 1133 * eight bytes or less. 1134 */ 1135 if (MaxPacketSize == 0) { 1136 xx = (tw->tw_length > 8) ? 8 : tw->tw_length; 1137 } else { 1138 xx = (tw->tw_length > MaxPacketSize) ? 1139 MaxPacketSize : tw->tw_length; 1140 } 1141 1142 tw->tw_tmp = xx; 1143 1144 /* 1145 * Create the TD. If this is an OUT 1146 * transaction, the data is already 1147 * in the buffer of the TW. 1148 * Get first 8 bytes of the command only. 1149 */ 1150 if ((uhci_insert_hc_td(uhcip, 1151 tw->tw_cookie.dmac_address + SETUP_SIZE, xx, 1152 pp, tw, tw->tw_direction, 1153 reqp->ctrl_attributes)) != USB_SUCCESS) { 1154 1155 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1156 uhcip->uhci_log_hdl, 1157 "uhci_handle_ctrl_td: No resources"); 1158 1159 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, 1160 USB_CR_NO_RESOURCES); 1161 1162 return; 1163 } 1164 1165 tw->tw_ctrl_state = DATA; 1166 } 1167 1168 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1169 "Setup complete: pp 0x%p td 0x%p", (void *)pp, (void *)td); 1170 1171 break; 1172 case DATA: 1173 uhci_delete_td(uhcip, td); 1174 1175 MaxPacketSize = eptd->wMaxPacketSize; 1176 1177 /* 1178 * Decrement pending bytes and increment the total 1179 * number bytes transferred by the actual number of bytes 1180 * transferred in this TD. If the number of bytes transferred 1181 * is less than requested, that means an underrun has 1182 * occurred. Set the tw_tmp varible to indicate UNDER run. 1183 */ 1184 bytes_xfered = GetTD_alen(uhcip, td); 1185 if (bytes_xfered == ZERO_LENGTH) { 1186 bytes_xfered = 0; 1187 } else { 1188 bytes_xfered++; 1189 } 1190 1191 tw->tw_bytes_pending -= bytes_xfered; 1192 tw->tw_bytes_xfered += bytes_xfered; 1193 1194 if (bytes_xfered < tw->tw_tmp) { 1195 tw->tw_bytes_pending = 0; 1196 tw->tw_tmp = UHCI_UNDERRUN_OCCURRED; 1197 1198 /* 1199 * Controller does not update the queue head 1200 * element pointer when a data underrun occurs. 1201 */ 1202 SetQH32(uhcip, pp->pp_qh->element_ptr, 1203 GetTD32(uhcip, td->link_ptr)); 1204 } 1205 1206 if (bytes_xfered > tw->tw_tmp) { 1207 tw->tw_bytes_pending = 0; 1208 tw->tw_tmp = UHCI_OVERRUN_OCCURRED; 1209 } 1210 1211 /* 1212 * If no more bytes are pending, insert status 1213 * phase. Otherwise insert data phase. 1214 */ 1215 if (tw->tw_bytes_pending) { 1216 bytes_for_xfer = (tw->tw_bytes_pending > 1217 MaxPacketSize) ? MaxPacketSize : 1218 tw->tw_bytes_pending; 1219 1220 tw->tw_tmp = bytes_for_xfer; 1221 1222 if ((uhci_insert_hc_td(uhcip, 1223 tw->tw_cookie.dmac_address + SETUP_SIZE + 1224 tw->tw_bytes_xfered, bytes_for_xfer, pp, tw, 1225 tw->tw_direction, 1226 reqp->ctrl_attributes)) != USB_SUCCESS) { 1227 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1228 uhcip->uhci_log_hdl, 1229 "uhci_handle_ctrl_td: No TD"); 1230 1231 uhci_hcdi_callback(uhcip, pp, usb_pp, 1232 tw, USB_NO_RESOURCES); 1233 1234 return; 1235 } 1236 1237 tw->tw_ctrl_state = DATA; 1238 1239 break; 1240 } 1241 1242 pp->pp_data_toggle = 1; 1243 direction = (tw->tw_direction == PID_IN) ? PID_OUT : PID_IN; 1244 1245 if ((uhci_insert_hc_td(uhcip, NULL, 0, pp, tw, direction, 1246 reqp->ctrl_attributes)) != USB_SUCCESS) { 1247 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1248 "uhci_handle_ctrl_td: TD exhausted"); 1249 1250 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, 1251 USB_NO_RESOURCES); 1252 1253 return; 1254 } 1255 1256 tw->tw_ctrl_state = STATUS; 1257 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1258 "Data complete: pp 0x%p td 0x%p", (void *)pp, (void *)td); 1259 1260 break; 1261 case STATUS: 1262 /* 1263 * Send the data to the client if it is a DATA IN, 1264 * else send just return status for DATA OUT commnads. 1265 * And set the tw_claim flag. 1266 */ 1267 tw->tw_claim = UHCI_INTR_HDLR_CLAIMED; 1268 1269 if ((tw->tw_length != 0) && (tw->tw_direction == PID_IN)) { 1270 usb_req_attrs_t attrs = ((usb_ctrl_req_t *) 1271 tw->tw_curr_xfer_reqp)->ctrl_attributes; 1272 /* 1273 * Call uhci_sendup_td_message to send message 1274 * upstream. The function uhci_sendup_td_message 1275 * returns USB_NO_RESOURCES if allocb fails and 1276 * also sends error message to upstream by calling 1277 * USBA callback function. 1278 * 1279 * Under error conditions just drop the current msg. 1280 */ 1281 if ((tw->tw_tmp == UHCI_UNDERRUN_OCCURRED) && 1282 (!(attrs & USB_ATTRS_SHORT_XFER_OK))) { 1283 error = USB_CR_DATA_UNDERRUN; 1284 } else if (tw->tw_tmp == UHCI_OVERRUN_OCCURRED) { 1285 error = USB_CR_DATA_OVERRUN; 1286 } 1287 uhci_sendup_td_message(uhcip, error, tw); 1288 1289 } else { 1290 uhci_do_byte_stats(uhcip, tw->tw_length, 1291 eptd->bmAttributes, eptd->bEndpointAddress); 1292 1293 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, USB_CR_OK); 1294 } 1295 1296 USB_DPRINTF_L3(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1297 "Status complete: pp 0x%p td 0x%p", pp, td); 1298 1299 uhci_delete_td(uhcip, td); 1300 uhci_deallocate_tw(uhcip, pp, tw); 1301 1302 break; 1303 default: 1304 USB_DPRINTF_L2(PRINT_MASK_INTR, uhcip->uhci_log_hdl, 1305 "uhci_handle_ctrl_td: Bad control state"); 1306 1307 uhci_hcdi_callback(uhcip, pp, usb_pp, tw, 1308 USB_CR_UNSPECIFIED_ERR); 1309 } 1310 } 1311 1312 1313 /* 1314 * uhci_handle_intr_td_errors: 1315 * Handles the errors encountered for the interrupt transfers. 1316 */ 1317 static void 1318 uhci_handle_intr_td_errors(uhci_state_t *uhcip, uhci_td_t *td, 1319 uhci_trans_wrapper_t *tw, uhci_pipe_private_t *pp) 1320 { 1321 usb_cr_t usb_err; 1322 usb_intr_req_t *intr_reqp = 1323 (usb_intr_req_t *)tw->tw_curr_xfer_reqp; 1324 1325 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1326 "uhci_handle_intr_td_errors: td = 0x%p tw = 0x%p", td, tw); 1327 1328 usb_err = uhci_parse_td_error(uhcip, pp, td); 1329 1330 if (intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER) { 1331 uhci_handle_one_xfer_completion(uhcip, usb_err, td); 1332 1333 return; 1334 } 1335 1336 uhci_delete_td(uhcip, td); 1337 uhci_sendup_td_message(uhcip, usb_err, tw); 1338 uhci_deallocate_tw(uhcip, tw->tw_pipe_private, tw); 1339 } 1340 1341 1342 /* 1343 * uhci_handle_one_xfer_completion: 1344 */ 1345 static void 1346 uhci_handle_one_xfer_completion( 1347 uhci_state_t *uhcip, 1348 usb_cr_t usb_err, 1349 uhci_td_t *td) 1350 { 1351 uhci_trans_wrapper_t *tw = td->tw; 1352 uhci_pipe_private_t *pp = tw->tw_pipe_private; 1353 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1354 usb_intr_req_t *intr_reqp = 1355 (usb_intr_req_t *)tw->tw_curr_xfer_reqp; 1356 1357 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1358 "uhci_handle_one_xfer_completion: td = 0x%p", td); 1359 1360 ASSERT(intr_reqp->intr_attributes & USB_ATTRS_ONE_XFER); 1361 1362 /* set state to idle */ 1363 pp->pp_state = UHCI_PIPE_STATE_IDLE; 1364 1365 ((usb_intr_req_t *)(pp->pp_client_periodic_in_reqp))-> 1366 intr_data = ((usb_intr_req_t *)(tw->tw_curr_xfer_reqp))->intr_data; 1367 1368 ((usb_intr_req_t *)tw->tw_curr_xfer_reqp)->intr_data = NULL; 1369 1370 /* now free duplicate current request */ 1371 usb_free_intr_req((usb_intr_req_t *)tw->tw_curr_xfer_reqp); 1372 mutex_enter(&ph->p_mutex); 1373 ph->p_req_count--; 1374 mutex_exit(&ph->p_mutex); 1375 1376 /* make client's request the current request */ 1377 tw->tw_curr_xfer_reqp = pp->pp_client_periodic_in_reqp; 1378 pp->pp_client_periodic_in_reqp = NULL; 1379 1380 uhci_sendup_td_message(uhcip, usb_err, tw); 1381 /* Clear the tw->tw_claim flag */ 1382 tw->tw_claim = UHCI_NOT_CLAIMED; 1383 1384 uhci_delete_td(uhcip, td); 1385 uhci_deallocate_tw(uhcip, pp, tw); 1386 } 1387 1388 1389 /* 1390 * uhci_parse_td_error 1391 * Parses the Transfer Descriptors error 1392 */ 1393 usb_cr_t 1394 uhci_parse_td_error(uhci_state_t *uhcip, uhci_pipe_private_t *pp, uhci_td_t *td) 1395 { 1396 uint_t status; 1397 1398 status = GetTD_status(uhcip, td) & TD_STATUS_MASK; 1399 1400 USB_DPRINTF_L4(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1401 "uhci_parse_td_error: status_bits=0x%x", status); 1402 1403 if (UHCI_XFER_TYPE(&pp->pp_pipe_handle->p_ep) == USB_EP_ATTR_ISOCH) { 1404 1405 return (USB_CR_OK); 1406 } 1407 1408 if (!status) { 1409 1410 return (USB_CR_OK); 1411 } 1412 1413 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1414 "uhci_parse_td_error: status_bits=0x%x", status); 1415 1416 1417 if (status & UHCI_TD_BITSTUFF_ERR) { 1418 1419 return (USB_CR_BITSTUFFING); 1420 } 1421 1422 if (status & UHCI_TD_CRC_TIMEOUT) { 1423 pp->pp_data_toggle = GetTD_dtogg(uhcip, td); 1424 1425 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1426 "uhci_parse_td_error: timeout & data toggle reset; " 1427 "data toggle: %x", pp->pp_data_toggle); 1428 1429 return ((GetTD_PID(uhcip, td) == PID_IN) ? USB_CR_DEV_NOT_RESP : 1430 USB_CR_TIMEOUT); 1431 } 1432 1433 if (status & UHCI_TD_BABBLE_ERR) { 1434 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1435 "babble error"); 1436 1437 return (USB_CR_UNSPECIFIED_ERR); 1438 } 1439 1440 if (status & UHCI_TD_DATA_BUFFER_ERR) { 1441 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1442 "buffer error"); 1443 1444 return ((GetTD_PID(uhcip, td) == PID_IN) ? 1445 USB_CR_BUFFER_OVERRUN : USB_CR_BUFFER_UNDERRUN); 1446 } 1447 1448 if (status & UHCI_TD_STALLED) { 1449 pp->pp_data_toggle = 0; 1450 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1451 "uhci_parse_td_error: stall; data toggle reset; " 1452 "data toggle: %x", pp->pp_data_toggle); 1453 1454 return (USB_CR_STALL); 1455 } 1456 1457 if (status) { 1458 USB_DPRINTF_L2(PRINT_MASK_LISTS, uhcip->uhci_log_hdl, 1459 "unspecified error=0x%x", status); 1460 } 1461 1462 return (USB_CR_OK); 1463 } 1464 1465 1466 static dev_info_t * 1467 uhci_get_dip(dev_t dev) 1468 { 1469 int instance = UHCI_UNIT(dev); 1470 uhci_state_t *uhcip = ddi_get_soft_state(uhci_statep, instance); 1471 1472 return (uhcip ? uhcip->uhci_dip : NULL); 1473 } 1474 1475 1476 /* 1477 * cb_ops entry points 1478 */ 1479 static int 1480 uhci_open(dev_t *devp, int flags, int otyp, cred_t *credp) 1481 { 1482 dev_info_t *dip = uhci_get_dip(*devp); 1483 1484 return (usba_hubdi_open(dip, devp, flags, otyp, credp)); 1485 } 1486 1487 1488 static int 1489 uhci_close(dev_t dev, int flag, int otyp, cred_t *credp) 1490 { 1491 dev_info_t *dip = uhci_get_dip(dev); 1492 1493 return (usba_hubdi_close(dip, dev, flag, otyp, credp)); 1494 } 1495 1496 1497 static int 1498 uhci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 1499 cred_t *credp, int *rvalp) 1500 { 1501 dev_info_t *dip = uhci_get_dip(dev); 1502 1503 return (usba_hubdi_ioctl(dip, dev, cmd, arg, mode, credp, rvalp)); 1504 } 1505