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