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