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