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