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