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