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