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