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