xref: /illumos-gate/usr/src/uts/common/io/usb/hcd/ehci/ehci.c (revision 9c75c6bf)
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  * EHCI Host Controller Driver (EHCI)
31  *
32  * The EHCI driver is a software driver which interfaces to the Universal
33  * Serial Bus layer (USBA) and the Host Controller (HC). The interface to
34  * the Host Controller is defined by the EHCI Host Controller Interface.
35  *
36  * This file contains code for Auto-configuration and HCDI entry points.
37  *
38  * NOTE:
39  *
40  * Currently EHCI driver does not support the following features
41  *
42  * - usb 2.0 or high speed usb isochronous devices.
43  * - usb 1.1 or full speed usb isochronous devices behind usb 2.0
44  *   or high speed hub.
45  * - Alternate QTD for short xfer condition is only used in Bulk xfers.
46  * - Frame Span Traversal Nodes (FSTN).
47  * - Bandwidth allocation scheme needs to be updated for FSTN and USB2.0
48  *   or High speed hub with multiple TT implementation. Currently bandwidth
49  *   allocation scheme assumes one TT per USB2.0 or High speed hub.
50  * - 64 bit addressing capability.
51  * - Programmable periodic frame list size like 256, 512, 1024.
52  *   It supports only 1024 periodic frame list size.
53  */
54 
55 #include <sys/usb/hcd/ehci/ehcid.h>
56 #include <sys/usb/hcd/ehci/ehci_xfer.h>
57 #include <sys/usb/hcd/ehci/ehci_intr.h>
58 #include <sys/usb/hcd/ehci/ehci_util.h>
59 #include <sys/usb/hcd/ehci/ehci_isoch.h>
60 
61 /* Pointer to the state structure */
62 void *ehci_statep;
63 
64 /* Number of instances */
65 #define	EHCI_INSTS	1
66 
67 /* Debugging information */
68 uint_t ehci_errmask	= (uint_t)PRINT_MASK_ALL;
69 uint_t ehci_errlevel	= USB_LOG_L2;
70 uint_t ehci_instance_debug = (uint_t)-1;
71 
72 /* Enable all workarounds for VIA VT62x2 */
73 uint_t ehci_vt62x2_workaround = EHCI_VIA_WORKAROUNDS;
74 
75 /*
76  * EHCI Auto-configuration entry points.
77  *
78  * Device operations (dev_ops) entries function prototypes.
79  *
80  * We use the hub cbops since all nexus ioctl operations defined so far will
81  * be executed by the root hub. The following are the Host Controller Driver
82  * (HCD) entry points.
83  *
84  * the open/close/ioctl functions call the corresponding usba_hubdi_*
85  * calls after looking up the dip thru the dev_t.
86  */
87 static int	ehci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
88 static int	ehci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
89 static int	ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd);
90 static int	ehci_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
91 				void *arg, void **result);
92 
93 static int	ehci_open(dev_t	*devp, int flags, int otyp, cred_t *credp);
94 static int	ehci_close(dev_t dev, int flag, int otyp, cred_t *credp);
95 static int	ehci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode,
96     cred_t *credp, int *rvalp);
97 
98 int		usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level);
99 
100 static struct cb_ops ehci_cb_ops = {
101 	ehci_open,			/* EHCI */
102 	ehci_close,			/* Close */
103 	nodev,				/* Strategy */
104 	nodev,				/* Print */
105 	nodev,				/* Dump */
106 	nodev,				/* Read */
107 	nodev,				/* Write */
108 	ehci_ioctl,			/* Ioctl */
109 	nodev,				/* Devmap */
110 	nodev,				/* Mmap */
111 	nodev,				/* Segmap */
112 	nochpoll,			/* Poll */
113 	ddi_prop_op,			/* cb_prop_op */
114 	NULL,				/* Streamtab */
115 	D_NEW | D_MP | D_HOTPLUG	/* Driver compatibility flag */
116 };
117 
118 static struct dev_ops ehci_ops = {
119 	DEVO_REV,			/* Devo_rev */
120 	0,				/* Refcnt */
121 	ehci_info,			/* Info */
122 	nulldev,			/* Identify */
123 	nulldev,			/* Probe */
124 	ehci_attach,			/* Attach */
125 	ehci_detach,			/* Detach */
126 	ehci_reset,			/* Reset */
127 	&ehci_cb_ops,			/* Driver operations */
128 	&usba_hubdi_busops,		/* Bus operations */
129 	usba_hubdi_root_hub_power	/* Power */
130 };
131 
132 /*
133  * The USBA library must be loaded for this driver.
134  */
135 static struct modldrv modldrv = {
136 	&mod_driverops, 	/* Type of module. This one is a driver */
137 	"USB EHCI Driver %I%", /* Name of the module. */
138 	&ehci_ops,		/* Driver ops */
139 };
140 
141 static struct modlinkage modlinkage = {
142 	MODREV_1, (void *)&modldrv, NULL
143 };
144 
145 
146 int
147 _init(void)
148 {
149 	int error;
150 
151 	/* Initialize the soft state structures */
152 	if ((error = ddi_soft_state_init(&ehci_statep, sizeof (ehci_state_t),
153 	    EHCI_INSTS)) != 0) {
154 		return (error);
155 	}
156 
157 	/* Install the loadable module */
158 	if ((error = mod_install(&modlinkage)) != 0) {
159 		ddi_soft_state_fini(&ehci_statep);
160 	}
161 
162 	return (error);
163 }
164 
165 
166 int
167 _info(struct modinfo *modinfop)
168 {
169 	return (mod_info(&modlinkage, modinfop));
170 }
171 
172 
173 int
174 _fini(void)
175 {
176 	int error;
177 
178 	if ((error = mod_remove(&modlinkage)) == 0) {
179 
180 		/* Release per module resources */
181 		ddi_soft_state_fini(&ehci_statep);
182 	}
183 
184 	return (error);
185 }
186 
187 
188 /*
189  * EHCI Auto configuration entry points.
190  */
191 
192 /*
193  * ehci_attach:
194  *
195  * Description: Attach entry point is called by the Kernel.
196  *		Allocates resources for each EHCI host controller instance.
197  *		Initializes the EHCI Host Controller.
198  *
199  * Return     : DDI_SUCCESS / DDI_FAILURE.
200  */
201 static int
202 ehci_attach(dev_info_t		*dip,
203 	ddi_attach_cmd_t	cmd)
204 {
205 	int			instance;
206 	ehci_state_t		*ehcip = NULL;
207 	usba_hcdi_register_args_t hcdi_args;
208 
209 	switch (cmd) {
210 	case DDI_ATTACH:
211 		break;
212 	case DDI_RESUME:
213 		ehcip = ehci_obtain_state(dip);
214 
215 		return (ehci_cpr_resume(ehcip));
216 	default:
217 		return (DDI_FAILURE);
218 	}
219 
220 	/* Get the instance and create soft state */
221 	instance = ddi_get_instance(dip);
222 
223 	if (ddi_soft_state_zalloc(ehci_statep, instance) != 0) {
224 
225 		return (DDI_FAILURE);
226 	}
227 
228 	ehcip = ddi_get_soft_state(ehci_statep, instance);
229 	if (ehcip == NULL) {
230 
231 		return (DDI_FAILURE);
232 	}
233 
234 	ehcip->ehci_flags = EHCI_ATTACH;
235 
236 	ehcip->ehci_log_hdl = usb_alloc_log_hdl(dip, "ehci", &ehci_errlevel,
237 	    &ehci_errmask, &ehci_instance_debug, 0);
238 
239 	ehcip->ehci_flags |= EHCI_ZALLOC;
240 
241 	/* Set host controller soft state to initialization */
242 	ehcip->ehci_hc_soft_state = EHCI_CTLR_INIT_STATE;
243 
244 	USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
245 	    "ehcip = 0x%p", (void *)ehcip);
246 
247 	/* Initialize the DMA attributes */
248 	ehci_set_dma_attributes(ehcip);
249 
250 	/* Save the dip and instance */
251 	ehcip->ehci_dip = dip;
252 	ehcip->ehci_instance = instance;
253 
254 	/* Initialize the DMA attributes */
255 	ehci_create_stats(ehcip);
256 
257 	/* Create the qtd and qh pools */
258 	if (ehci_allocate_pools(ehcip) != DDI_SUCCESS) {
259 		(void) ehci_cleanup(ehcip);
260 
261 		return (DDI_FAILURE);
262 	}
263 
264 	/* Initialize the isochronous resources */
265 	if (ehci_isoc_init(ehcip) != DDI_SUCCESS) {
266 		(void) ehci_cleanup(ehcip);
267 
268 		return (DDI_FAILURE);
269 	}
270 
271 	/* Map the registers */
272 	if (ehci_map_regs(ehcip) != DDI_SUCCESS) {
273 		(void) ehci_cleanup(ehcip);
274 
275 		return (DDI_FAILURE);
276 	}
277 
278 	/* Get the ehci chip vendor and device id */
279 	ehcip->ehci_vendor_id = pci_config_get16(
280 	    ehcip->ehci_config_handle, PCI_CONF_VENID);
281 	ehcip->ehci_device_id = pci_config_get16(
282 	    ehcip->ehci_config_handle, PCI_CONF_DEVID);
283 	ehcip->ehci_rev_id = pci_config_get8(
284 	    ehcip->ehci_config_handle, PCI_CONF_REVID);
285 
286 	/* Register interrupts */
287 	if (ehci_register_intrs_and_init_mutex(ehcip) != DDI_SUCCESS) {
288 		(void) ehci_cleanup(ehcip);
289 
290 		return (DDI_FAILURE);
291 	}
292 
293 	mutex_enter(&ehcip->ehci_int_mutex);
294 
295 	/* Initialize the controller */
296 	if (ehci_init_ctlr(ehcip) != DDI_SUCCESS) {
297 		mutex_exit(&ehcip->ehci_int_mutex);
298 		(void) ehci_cleanup(ehcip);
299 
300 		return (DDI_FAILURE);
301 	}
302 
303 	/*
304 	 * At this point, the hardware will be okay.
305 	 * Initialize the usba_hcdi structure
306 	 */
307 	ehcip->ehci_hcdi_ops = ehci_alloc_hcdi_ops(ehcip);
308 
309 	mutex_exit(&ehcip->ehci_int_mutex);
310 
311 	/*
312 	 * Make this HCD instance known to USBA
313 	 * (dma_attr must be passed for USBA busctl's)
314 	 */
315 	hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION;
316 	hcdi_args.usba_hcdi_register_dip = dip;
317 	hcdi_args.usba_hcdi_register_ops = ehcip->ehci_hcdi_ops;
318 	hcdi_args.usba_hcdi_register_dma_attr = &ehcip->ehci_dma_attr;
319 
320 	/*
321 	 * Priority and iblock_cookie are one and the same
322 	 * (However, retaining hcdi_soft_iblock_cookie for now
323 	 * assigning it w/ priority. In future all iblock_cookie
324 	 * could just go)
325 	 */
326 	hcdi_args.usba_hcdi_register_iblock_cookie =
327 	    (ddi_iblock_cookie_t)(uintptr_t)ehcip->ehci_intr_pri;
328 
329 	if (usba_hcdi_register(&hcdi_args, 0) != DDI_SUCCESS) {
330 		(void) ehci_cleanup(ehcip);
331 
332 		return (DDI_FAILURE);
333 	}
334 
335 	ehcip->ehci_flags |= EHCI_USBAREG;
336 
337 	mutex_enter(&ehcip->ehci_int_mutex);
338 
339 	if ((ehci_init_root_hub(ehcip)) != USB_SUCCESS) {
340 		mutex_exit(&ehcip->ehci_int_mutex);
341 		(void) ehci_cleanup(ehcip);
342 
343 		return (DDI_FAILURE);
344 	}
345 
346 	mutex_exit(&ehcip->ehci_int_mutex);
347 
348 	/* Finally load the root hub driver */
349 	if (ehci_load_root_hub_driver(ehcip) != USB_SUCCESS) {
350 		(void) ehci_cleanup(ehcip);
351 
352 		return (DDI_FAILURE);
353 	}
354 	ehcip->ehci_flags |= EHCI_RHREG;
355 
356 	/* Display information in the banner */
357 	ddi_report_dev(dip);
358 
359 	mutex_enter(&ehcip->ehci_int_mutex);
360 
361 	/* Reset the ehci initialization flag */
362 	ehcip->ehci_flags &= ~EHCI_ATTACH;
363 
364 	/* Print the Host Control's Operational registers */
365 	ehci_print_caps(ehcip);
366 	ehci_print_regs(ehcip);
367 
368 	(void) pci_report_pmcap(dip, PCI_PM_IDLESPEED, (void *)4000);
369 
370 	mutex_exit(&ehcip->ehci_int_mutex);
371 
372 	USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
373 	    "ehci_attach: dip = 0x%p done", (void *)dip);
374 
375 	return (DDI_SUCCESS);
376 }
377 
378 
379 /*
380  * ehci_detach:
381  *
382  * Description: Detach entry point is called by the Kernel.
383  *		Deallocates all resource allocated.
384  *		Unregisters the interrupt handler.
385  *
386  * Return     : DDI_SUCCESS / DDI_FAILURE
387  */
388 int
389 ehci_detach(dev_info_t		*dip,
390 	ddi_detach_cmd_t	cmd)
391 {
392 	ehci_state_t		*ehcip = ehci_obtain_state(dip);
393 
394 	USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, "ehci_detach:");
395 
396 	switch (cmd) {
397 	case DDI_DETACH:
398 
399 		return (ehci_cleanup(ehcip));
400 	case DDI_SUSPEND:
401 
402 		return (ehci_cpr_suspend(ehcip));
403 	default:
404 
405 		return (DDI_FAILURE);
406 	}
407 }
408 
409 /*
410  * ehci_reset:
411  *
412  * Description:	Reset entry point - called by the Kernel
413  *		on the way down.
414  *		Toshiba Tecra laptop has been observed to hang
415  *		on soft reboot. The resetting ehci on the way
416  *		down solves the problem.
417  *
418  * Return	: DDI_SUCCESS / DDI_FAILURE
419  */
420 /* ARGSUSED */
421 static int
422 ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd)
423 {
424 	ehci_state_t		*ehcip = ehci_obtain_state(dip);
425 
426 	mutex_enter(&ehcip->ehci_int_mutex);
427 
428 	/*
429 	 * To reset the host controller, the HCRESET bit should be set to one.
430 	 * Software should not set this bit to a one when the HCHalted bit in
431 	 * the USBSTS register is a zero. Attempting to reset an actively
432 	 * running host controller will result in undefined behavior.
433 	 * see EHCI SPEC. for more information.
434 	 */
435 	if (!(Get_OpReg(ehci_status) & EHCI_STS_HOST_CTRL_HALTED)) {
436 
437 		/* Stop the EHCI host controller */
438 		Set_OpReg(ehci_command,
439 		    Get_OpReg(ehci_command) & ~EHCI_CMD_HOST_CTRL_RUN);
440 		/*
441 		 * When this bit is set to 0, the Host Controller completes the
442 		 * current and any actively pipelined transactions on the USB
443 		 * and then halts. The Host Controller must halt within 16
444 		 * micro-frames after software clears the Run bit.
445 		 * The HC Halted bit in the status register indicates when the
446 		 * Host Controller has finished its pending pipelined
447 		 * transactions and has entered the stopped state.
448 		 */
449 		drv_usecwait(EHCI_RESET_TIMEWAIT);
450 	}
451 
452 	/* Reset the EHCI host controller */
453 	Set_OpReg(ehci_command,
454 	    Get_OpReg(ehci_command) | EHCI_CMD_HOST_CTRL_RESET);
455 
456 	mutex_exit(&ehcip->ehci_int_mutex);
457 
458 	return (DDI_SUCCESS);
459 }
460 
461 /*
462  * ehci_info:
463  */
464 /* ARGSUSED */
465 static int
466 ehci_info(dev_info_t		*dip,
467 	ddi_info_cmd_t		infocmd,
468 	void			*arg,
469 	void			**result)
470 {
471 	dev_t			dev;
472 	ehci_state_t		*ehcip;
473 	int			instance;
474 	int			error = DDI_FAILURE;
475 
476 	switch (infocmd) {
477 	case DDI_INFO_DEVT2DEVINFO:
478 		dev = (dev_t)arg;
479 		instance = EHCI_UNIT(dev);
480 		ehcip = ddi_get_soft_state(ehci_statep, instance);
481 		if (ehcip != NULL) {
482 			*result = (void *)ehcip->ehci_dip;
483 			if (*result != NULL) {
484 				error = DDI_SUCCESS;
485 			}
486 		} else {
487 			*result = NULL;
488 		}
489 
490 		break;
491 	case DDI_INFO_DEVT2INSTANCE:
492 		dev = (dev_t)arg;
493 		instance = EHCI_UNIT(dev);
494 		*result = (void *)(uintptr_t)instance;
495 		error = DDI_SUCCESS;
496 		break;
497 	default:
498 		break;
499 	}
500 
501 	return (error);
502 }
503 
504 
505 /*
506  * EHCI CB_OPS entry points.
507  */
508 static dev_info_t *
509 ehci_get_dip(dev_t	dev)
510 {
511 	int		instance = EHCI_UNIT(dev);
512 	ehci_state_t	*ehcip = ddi_get_soft_state(ehci_statep, instance);
513 
514 	if (ehcip) {
515 
516 		return (ehcip->ehci_dip);
517 	} else {
518 
519 		return (NULL);
520 	}
521 }
522 
523 
524 static int
525 ehci_open(dev_t		*devp,
526 	int		flags,
527 	int		otyp,
528 	cred_t		*credp)
529 {
530 	dev_info_t	*dip = ehci_get_dip(*devp);
531 
532 	return (usba_hubdi_open(dip, devp, flags, otyp, credp));
533 }
534 
535 
536 static int
537 ehci_close(dev_t	dev,
538 	int		flag,
539 	int		otyp,
540 	cred_t		*credp)
541 {
542 	dev_info_t	*dip = ehci_get_dip(dev);
543 
544 	return (usba_hubdi_close(dip, dev, flag, otyp, credp));
545 }
546 
547 
548 static int
549 ehci_ioctl(dev_t	dev,
550 	int		cmd,
551 	intptr_t	arg,
552 	int		mode,
553 	cred_t		*credp,
554 	int		*rvalp)
555 {
556 	dev_info_t	*dip = ehci_get_dip(dev);
557 
558 	return (usba_hubdi_ioctl(dip,
559 	    dev, cmd, arg, mode, credp, rvalp));
560 }
561 
562 /*
563  * EHCI Interrupt Handler entry point.
564  */
565 
566 /*
567  * ehci_intr:
568  *
569  * EHCI (EHCI) interrupt handling routine.
570  */
571 uint_t
572 ehci_intr(caddr_t arg1, caddr_t arg2)
573 {
574 	uint_t			intr;
575 	ehci_state_t		*ehcip = (ehci_state_t *)arg1;
576 
577 	USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
578 	    "ehci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p", arg1, arg2);
579 
580 	/* Get the ehci global mutex */
581 	mutex_enter(&ehcip->ehci_int_mutex);
582 
583 	/*
584 	 * Now process the actual ehci interrupt events  that caused
585 	 * invocation of this ehci interrupt handler.
586 	 */
587 	intr = (Get_OpReg(ehci_status) & Get_OpReg(ehci_interrupt));
588 
589 	/* Update kstat values */
590 	ehci_do_intrs_stats(ehcip, intr);
591 
592 	/*
593 	 * We could have gotten a spurious interrupts. If so, do not
594 	 * claim it.  This is quite  possible on some  architectures
595 	 * where more than one PCI slots share the IRQs.  If so, the
596 	 * associated driver's interrupt routine may get called even
597 	 * if the interrupt is not meant for them.
598 	 *
599 	 * By unclaiming the interrupt, the other driver gets chance
600 	 * to service its interrupt.
601 	 */
602 	if (!intr) {
603 		mutex_exit(&ehcip->ehci_int_mutex);
604 
605 		return (DDI_INTR_UNCLAIMED);
606 	}
607 
608 	/* Acknowledge the interrupt */
609 	Set_OpReg(ehci_status, intr);
610 
611 	if (ehcip->ehci_hc_soft_state == EHCI_CTLR_ERROR_STATE) {
612 		mutex_exit(&ehcip->ehci_int_mutex);
613 
614 		return (DDI_INTR_CLAIMED);
615 	}
616 
617 	USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
618 	    "Interrupt status 0x%x", intr);
619 
620 	/*
621 	 * If necessary broadcast that an interrupt has occured.  This
622 	 * is only necessary during controller init.
623 	 */
624 	if (ehcip->ehci_flags & EHCI_CV_INTR) {
625 		ehcip->ehci_flags &= ~EHCI_CV_INTR;
626 		cv_broadcast(&ehcip->ehci_async_schedule_advance_cv);
627 	}
628 
629 	/* Check for Frame List Rollover */
630 	if (intr & EHCI_INTR_FRAME_LIST_ROLLOVER) {
631 		USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
632 		    "ehci_intr: Frame List Rollover");
633 
634 		ehci_handle_frame_list_rollover(ehcip);
635 
636 		/* VIA VT6202 looses EHCI_INTR_USB interrupts, workaround. */
637 		if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) &&
638 		    (ehci_vt62x2_workaround & EHCI_VIA_LOST_INTERRUPTS)) {
639 			ehcip->ehci_missed_intr_sts |= EHCI_INTR_USB;
640 		}
641 	}
642 
643 	/* Check for Advance on Asynchronous Schedule */
644 	if (intr & EHCI_INTR_ASYNC_ADVANCE) {
645 		USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
646 		    "ehci_intr: Asynchronous Schedule Advance Notification");
647 
648 		/* Disable async list advance interrupt */
649 		Set_OpReg(ehci_interrupt,
650 		    (Get_OpReg(ehci_interrupt) & ~EHCI_INTR_ASYNC_ADVANCE));
651 
652 		/*
653 		 * Call cv_broadcast on every this interrupt to wakeup
654 		 * all the threads that are waiting the async list advance
655 		 * event.
656 		 */
657 		cv_broadcast(&ehcip->ehci_async_schedule_advance_cv);
658 	}
659 
660 	/* Always process completed itds */
661 	ehci_traverse_active_isoc_list(ehcip);
662 
663 	/*
664 	 * Check for any USB transaction completion notification. Also
665 	 * process any missed USB transaction completion interrupts.
666 	 */
667 	if ((intr & EHCI_INTR_USB) || (intr & EHCI_INTR_USB_ERROR) ||
668 	    (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB) ||
669 	    (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB_ERROR)) {
670 
671 		USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
672 		    "ehci_intr: USB Transaction Completion Notification");
673 
674 		/* Clear missed interrupts */
675 		if (ehcip->ehci_missed_intr_sts) {
676 			ehcip->ehci_missed_intr_sts = 0;
677 		}
678 
679 		/* Process completed qtds */
680 		ehci_traverse_active_qtd_list(ehcip);
681 	}
682 
683 	/* Process endpoint reclamation list */
684 	if (ehcip->ehci_reclaim_list) {
685 		ehci_handle_endpoint_reclaimation(ehcip);
686 	}
687 
688 	/* Check for Host System Error */
689 	if (intr & EHCI_INTR_HOST_SYSTEM_ERROR) {
690 		USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl,
691 		    "ehci_intr: Unrecoverable error");
692 
693 		ehci_handle_ue(ehcip);
694 	}
695 
696 	/*
697 	 * Read interrupt status register to make sure that any PIO
698 	 * store to clear the ISR has made it on the PCI bus before
699 	 * returning from its interrupt handler.
700 	 */
701 	(void) Get_OpReg(ehci_status);
702 
703 	/* Release the ehci global mutex */
704 	mutex_exit(&ehcip->ehci_int_mutex);
705 
706 	USB_DPRINTF_L3(PRINT_MASK_INTR,  ehcip->ehci_log_hdl,
707 	    "Interrupt handling completed");
708 
709 	return (DDI_INTR_CLAIMED);
710 }
711 
712 
713 /*
714  * EHCI HCDI entry points
715  *
716  * The Host Controller Driver Interfaces (HCDI) are the software interfaces
717  * between the Universal Serial Bus Layer (USBA) and the Host Controller
718  * Driver (HCD). The HCDI interfaces or entry points are subject to change.
719  */
720 
721 /*
722  * ehci_hcdi_pipe_open:
723  *
724  * Member of HCD Ops structure and called during client specific pipe open
725  * Add the pipe to the data structure representing the device and allocate
726  * bandwidth for the pipe if it is a interrupt or isochronous endpoint.
727  */
728 int
729 ehci_hcdi_pipe_open(
730 	usba_pipe_handle_data_t	*ph,
731 	usb_flags_t		flags)
732 {
733 	ehci_state_t		*ehcip = ehci_obtain_state(
734 				    ph->p_usba_device->usb_root_hub_dip);
735 	usb_ep_descr_t		*epdt = &ph->p_ep;
736 	int			rval, error = USB_SUCCESS;
737 	int			kmflag = (flags & USB_FLAGS_SLEEP) ?
738 				KM_SLEEP : KM_NOSLEEP;
739 	uchar_t			smask = 0;
740 	uchar_t			cmask = 0;
741 	uint_t			pnode = 0;
742 	ehci_pipe_private_t	*pp;
743 
744 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
745 	    "ehci_hcdi_pipe_open: addr = 0x%x, ep%d",
746 	    ph->p_usba_device->usb_addr,
747 	    epdt->bEndpointAddress & USB_EP_NUM_MASK);
748 
749 	mutex_enter(&ehcip->ehci_int_mutex);
750 	rval = ehci_state_is_operational(ehcip);
751 	mutex_exit(&ehcip->ehci_int_mutex);
752 
753 	if (rval != USB_SUCCESS) {
754 
755 		return (rval);
756 	}
757 
758 	/*
759 	 * Check and handle root hub pipe open.
760 	 */
761 	if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
762 
763 		mutex_enter(&ehcip->ehci_int_mutex);
764 		error = ehci_handle_root_hub_pipe_open(ph, flags);
765 		mutex_exit(&ehcip->ehci_int_mutex);
766 
767 		return (error);
768 	}
769 
770 	/*
771 	 * Opening of other pipes excluding root hub pipe are
772 	 * handled below. Check whether pipe is already opened.
773 	 */
774 	if (ph->p_hcd_private) {
775 		USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
776 		    "ehci_hcdi_pipe_open: Pipe is already opened");
777 
778 		return (USB_FAILURE);
779 	}
780 
781 	/*
782 	 * A portion of the bandwidth is reserved for the non-periodic
783 	 * transfers, i.e control and bulk transfers in each of one
784 	 * millisecond frame period & usually it will be 20% of frame
785 	 * period. Hence there is no need to check for the available
786 	 * bandwidth before adding the control or bulk endpoints.
787 	 *
788 	 * There is a need to check for the available bandwidth before
789 	 * adding the periodic transfers, i.e interrupt & isochronous,
790 	 * since all these periodic transfers are guaranteed transfers.
791 	 * Usually 80% of the total frame time is reserved for periodic
792 	 * transfers.
793 	 */
794 	if (EHCI_PERIODIC_ENDPOINT(epdt)) {
795 
796 		mutex_enter(&ehcip->ehci_int_mutex);
797 		mutex_enter(&ph->p_mutex);
798 
799 		error = ehci_allocate_bandwidth(ehcip,
800 		    ph, &pnode, &smask, &cmask);
801 
802 		if (error != USB_SUCCESS) {
803 
804 			USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
805 			    "ehci_hcdi_pipe_open: Bandwidth allocation failed");
806 
807 			mutex_exit(&ph->p_mutex);
808 			mutex_exit(&ehcip->ehci_int_mutex);
809 
810 			return (error);
811 		}
812 
813 		mutex_exit(&ph->p_mutex);
814 		mutex_exit(&ehcip->ehci_int_mutex);
815 	}
816 
817 	/* Create the HCD pipe private structure */
818 	pp = kmem_zalloc(sizeof (ehci_pipe_private_t), kmflag);
819 
820 	/*
821 	 * Return failure if ehci pipe private
822 	 * structure allocation fails.
823 	 */
824 	if (pp == NULL) {
825 
826 		mutex_enter(&ehcip->ehci_int_mutex);
827 
828 		/* Deallocate bandwidth */
829 		if (EHCI_PERIODIC_ENDPOINT(epdt)) {
830 
831 			mutex_enter(&ph->p_mutex);
832 			ehci_deallocate_bandwidth(ehcip,
833 			    ph, pnode, smask, cmask);
834 			mutex_exit(&ph->p_mutex);
835 		}
836 
837 		mutex_exit(&ehcip->ehci_int_mutex);
838 
839 		return (USB_NO_RESOURCES);
840 	}
841 
842 	mutex_enter(&ehcip->ehci_int_mutex);
843 
844 	/* Save periodic nodes */
845 	pp->pp_pnode = pnode;
846 
847 	/* Save start and complete split mask values */
848 	pp->pp_smask = smask;
849 	pp->pp_cmask = cmask;
850 
851 	/* Create prototype for xfer completion condition variable */
852 	cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL);
853 
854 	/* Set the state of pipe as idle */
855 	pp->pp_state = EHCI_PIPE_STATE_IDLE;
856 
857 	/* Store a pointer to the pipe handle */
858 	pp->pp_pipe_handle = ph;
859 
860 	mutex_enter(&ph->p_mutex);
861 
862 	/* Store the pointer in the pipe handle */
863 	ph->p_hcd_private = (usb_opaque_t)pp;
864 
865 	/* Store a copy of the pipe policy */
866 	bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t));
867 
868 	mutex_exit(&ph->p_mutex);
869 
870 	/* Allocate the host controller endpoint descriptor */
871 	pp->pp_qh = ehci_alloc_qh(ehcip, ph, NULL);
872 
873 	/* Initialize the halting flag */
874 	pp->pp_halt_state = EHCI_HALT_STATE_FREE;
875 
876 	/* Create prototype for halt completion condition variable */
877 	cv_init(&pp->pp_halt_cmpl_cv, NULL, CV_DRIVER, NULL);
878 
879 	/* Isoch does not use QH, so ignore this */
880 	if ((pp->pp_qh == NULL) && !(EHCI_ISOC_ENDPOINT(epdt))) {
881 		ASSERT(pp->pp_qh == NULL);
882 
883 		USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
884 		    "ehci_hcdi_pipe_open: QH allocation failed");
885 
886 		mutex_enter(&ph->p_mutex);
887 
888 		/* Deallocate bandwidth */
889 		if (EHCI_PERIODIC_ENDPOINT(epdt)) {
890 
891 			ehci_deallocate_bandwidth(ehcip,
892 			    ph, pnode, smask, cmask);
893 		}
894 
895 		/* Destroy the xfer completion condition variable */
896 		cv_destroy(&pp->pp_xfer_cmpl_cv);
897 
898 		/*
899 		 * Deallocate the hcd private portion
900 		 * of the pipe handle.
901 		 */
902 		kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t));
903 
904 		/*
905 		 * Set the private structure in the
906 		 * pipe handle equal to NULL.
907 		 */
908 		ph->p_hcd_private = NULL;
909 
910 		mutex_exit(&ph->p_mutex);
911 		mutex_exit(&ehcip->ehci_int_mutex);
912 
913 		return (USB_NO_RESOURCES);
914 	}
915 
916 	/*
917 	 * Isoch does not use QH so no need to
918 	 * restore data toggle or insert QH
919 	 */
920 	if (!(EHCI_ISOC_ENDPOINT(epdt))) {
921 		/* Restore the data toggle information */
922 		ehci_restore_data_toggle(ehcip, ph);
923 	}
924 
925 	/*
926 	 * Insert the endpoint onto the host controller's
927 	 * appropriate endpoint list. The host controller
928 	 * will not schedule this endpoint and will not have
929 	 * any QTD's to process.  It will also update the pipe count.
930 	 */
931 	ehci_insert_qh(ehcip, ph);
932 
933 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
934 	    "ehci_hcdi_pipe_open: ph = 0x%p", (void *)ph);
935 
936 	ehcip->ehci_open_pipe_count++;
937 
938 	mutex_exit(&ehcip->ehci_int_mutex);
939 
940 	return (USB_SUCCESS);
941 }
942 
943 
944 /*
945  * ehci_hcdi_pipe_close:
946  *
947  * Member of HCD Ops structure and called during the client  specific pipe
948  * close. Remove the pipe and the data structure representing the device.
949  * Deallocate  bandwidth for the pipe if it is a interrupt or isochronous
950  * endpoint.
951  */
952 /* ARGSUSED */
953 int
954 ehci_hcdi_pipe_close(
955 	usba_pipe_handle_data_t	*ph,
956 	usb_flags_t		flags)
957 {
958 	ehci_state_t		*ehcip = ehci_obtain_state(
959 				    ph->p_usba_device->usb_root_hub_dip);
960 	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
961 	usb_ep_descr_t		*eptd = &ph->p_ep;
962 	int			error = USB_SUCCESS;
963 
964 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
965 	    "ehci_hcdi_pipe_close: addr = 0x%x, ep%d",
966 	    ph->p_usba_device->usb_addr,
967 	    eptd->bEndpointAddress & USB_EP_NUM_MASK);
968 
969 	/* Check and handle root hub pipe close */
970 	if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
971 
972 		mutex_enter(&ehcip->ehci_int_mutex);
973 		error = ehci_handle_root_hub_pipe_close(ph);
974 		mutex_exit(&ehcip->ehci_int_mutex);
975 
976 		return (error);
977 	}
978 
979 	ASSERT(ph->p_hcd_private != NULL);
980 
981 	mutex_enter(&ehcip->ehci_int_mutex);
982 
983 	/* Set pipe state to pipe close */
984 	pp->pp_state = EHCI_PIPE_STATE_CLOSE;
985 
986 	ehci_pipe_cleanup(ehcip, ph);
987 
988 	/*
989 	 * Remove the endpoint descriptor from Host
990 	 * Controller's appropriate endpoint list.
991 	 */
992 	ehci_remove_qh(ehcip, pp, B_TRUE);
993 
994 	/* Deallocate bandwidth */
995 	if (EHCI_PERIODIC_ENDPOINT(eptd)) {
996 
997 		mutex_enter(&ph->p_mutex);
998 		ehci_deallocate_bandwidth(ehcip, ph, pp->pp_pnode,
999 		    pp->pp_smask, pp->pp_cmask);
1000 		mutex_exit(&ph->p_mutex);
1001 	}
1002 
1003 	mutex_enter(&ph->p_mutex);
1004 
1005 	/* Destroy the xfer completion condition variable */
1006 	cv_destroy(&pp->pp_xfer_cmpl_cv);
1007 
1008 
1009 	/* Destory halt completion condition variable */
1010 	cv_destroy(&pp->pp_halt_cmpl_cv);
1011 
1012 	/*
1013 	 * Deallocate the hcd private portion
1014 	 * of the pipe handle.
1015 	 */
1016 	kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t));
1017 	ph->p_hcd_private = NULL;
1018 
1019 	mutex_exit(&ph->p_mutex);
1020 
1021 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1022 	    "ehci_hcdi_pipe_close: ph = 0x%p", (void *)ph);
1023 
1024 	ehcip->ehci_open_pipe_count--;
1025 
1026 	mutex_exit(&ehcip->ehci_int_mutex);
1027 
1028 	return (error);
1029 }
1030 
1031 
1032 /*
1033  * ehci_hcdi_pipe_reset:
1034  */
1035 /* ARGSUSED */
1036 int
1037 ehci_hcdi_pipe_reset(
1038 	usba_pipe_handle_data_t	*ph,
1039 	usb_flags_t		usb_flags)
1040 {
1041 	ehci_state_t		*ehcip = ehci_obtain_state(
1042 				    ph->p_usba_device->usb_root_hub_dip);
1043 	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1044 	int			error = USB_SUCCESS;
1045 
1046 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1047 	    "ehci_hcdi_pipe_reset:");
1048 
1049 	/*
1050 	 * Check and handle root hub pipe reset.
1051 	 */
1052 	if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
1053 
1054 		error = ehci_handle_root_hub_pipe_reset(ph, usb_flags);
1055 		return (error);
1056 	}
1057 
1058 	mutex_enter(&ehcip->ehci_int_mutex);
1059 
1060 	/* Set pipe state to pipe reset */
1061 	pp->pp_state = EHCI_PIPE_STATE_RESET;
1062 
1063 	ehci_pipe_cleanup(ehcip, ph);
1064 
1065 	mutex_exit(&ehcip->ehci_int_mutex);
1066 
1067 	return (error);
1068 }
1069 
1070 /*
1071  * ehci_hcdi_pipe_ctrl_xfer:
1072  */
1073 int
1074 ehci_hcdi_pipe_ctrl_xfer(
1075 	usba_pipe_handle_data_t	*ph,
1076 	usb_ctrl_req_t		*ctrl_reqp,
1077 	usb_flags_t		usb_flags)
1078 {
1079 	ehci_state_t		*ehcip = ehci_obtain_state(
1080 				    ph->p_usba_device->usb_root_hub_dip);
1081 	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1082 	int			rval;
1083 	int			error = USB_SUCCESS;
1084 	ehci_trans_wrapper_t	*tw;
1085 
1086 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1087 	    "ehci_hcdi_pipe_ctrl_xfer: ph = 0x%p reqp = 0x%p flags = %x",
1088 	    (void *)ph, ctrl_reqp, usb_flags);
1089 
1090 	mutex_enter(&ehcip->ehci_int_mutex);
1091 	rval = ehci_state_is_operational(ehcip);
1092 	mutex_exit(&ehcip->ehci_int_mutex);
1093 
1094 	if (rval != USB_SUCCESS) {
1095 
1096 		return (rval);
1097 	}
1098 
1099 	/*
1100 	 * Check and handle root hub control request.
1101 	 */
1102 	if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) {
1103 
1104 		error = ehci_handle_root_hub_request(ehcip, ph, ctrl_reqp);
1105 
1106 		return (error);
1107 	}
1108 
1109 	mutex_enter(&ehcip->ehci_int_mutex);
1110 
1111 	/*
1112 	 *  Check whether pipe is in halted state.
1113 	 */
1114 	if (pp->pp_state == EHCI_PIPE_STATE_ERROR) {
1115 
1116 		USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1117 		    "ehci_hcdi_pipe_ctrl_xfer: "
1118 		    "Pipe is in error state, need pipe reset to continue");
1119 
1120 		mutex_exit(&ehcip->ehci_int_mutex);
1121 
1122 		return (USB_FAILURE);
1123 	}
1124 
1125 	/* Allocate a transfer wrapper */
1126 	if ((tw = ehci_allocate_ctrl_resources(ehcip, pp, ctrl_reqp,
1127 	    usb_flags)) == NULL) {
1128 
1129 		error = USB_NO_RESOURCES;
1130 	} else {
1131 		/* Insert the qtd's on the endpoint */
1132 		ehci_insert_ctrl_req(ehcip, ph, ctrl_reqp, tw, usb_flags);
1133 	}
1134 
1135 	mutex_exit(&ehcip->ehci_int_mutex);
1136 
1137 	return (error);
1138 }
1139 
1140 
1141 /*
1142  * ehci_hcdi_bulk_transfer_size:
1143  *
1144  * Return maximum bulk transfer size
1145  */
1146 
1147 /* ARGSUSED */
1148 int
1149 ehci_hcdi_bulk_transfer_size(
1150 	usba_device_t	*usba_device,
1151 	size_t		*size)
1152 {
1153 	ehci_state_t	*ehcip = ehci_obtain_state(
1154 			    usba_device->usb_root_hub_dip);
1155 	int		rval;
1156 
1157 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1158 	    "ehci_hcdi_bulk_transfer_size:");
1159 
1160 	mutex_enter(&ehcip->ehci_int_mutex);
1161 	rval = ehci_state_is_operational(ehcip);
1162 	mutex_exit(&ehcip->ehci_int_mutex);
1163 
1164 	if (rval != USB_SUCCESS) {
1165 
1166 		return (rval);
1167 	}
1168 
1169 	/* VIA VT6202 may not handle bigger xfers well, workaround. */
1170 	if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) &&
1171 	    (ehci_vt62x2_workaround & EHCI_VIA_REDUCED_MAX_BULK_XFER_SIZE)) {
1172 		*size = EHCI_VIA_MAX_BULK_XFER_SIZE;
1173 	} else {
1174 		*size = EHCI_MAX_BULK_XFER_SIZE;
1175 	}
1176 
1177 	return (USB_SUCCESS);
1178 }
1179 
1180 
1181 /*
1182  * ehci_hcdi_pipe_bulk_xfer:
1183  */
1184 int
1185 ehci_hcdi_pipe_bulk_xfer(
1186 	usba_pipe_handle_data_t	*ph,
1187 	usb_bulk_req_t		*bulk_reqp,
1188 	usb_flags_t		usb_flags)
1189 {
1190 	ehci_state_t		*ehcip = ehci_obtain_state(
1191 				    ph->p_usba_device->usb_root_hub_dip);
1192 	ehci_pipe_private_t	*pp = (ehci_pipe_private_t *)ph->p_hcd_private;
1193 	int			rval, error = USB_SUCCESS;
1194 	ehci_trans_wrapper_t	*tw;
1195 
1196 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1197 	    "ehci_hcdi_pipe_bulk_xfer: ph = 0x%p reqp = 0x%p flags = %x",
1198 	    (void *)ph, bulk_reqp, usb_flags);
1199 
1200 	mutex_enter(&ehcip->ehci_int_mutex);
1201 	rval = ehci_state_is_operational(ehcip);
1202 
1203 	if (rval != USB_SUCCESS) {
1204 		mutex_exit(&ehcip->ehci_int_mutex);
1205 
1206 		return (rval);
1207 	}
1208 
1209 	/*
1210 	 *  Check whether pipe is in halted state.
1211 	 */
1212 	if (pp->pp_state == EHCI_PIPE_STATE_ERROR) {
1213 
1214 		USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1215 		    "ehci_hcdi_pipe_bulk_xfer:"
1216 		    "Pipe is in error state, need pipe reset to continue");
1217 
1218 		mutex_exit(&ehcip->ehci_int_mutex);
1219 
1220 		return (USB_FAILURE);
1221 	}
1222 
1223 	/* Allocate a transfer wrapper */
1224 	if ((tw = ehci_allocate_bulk_resources(ehcip, pp, bulk_reqp,
1225 	    usb_flags)) == NULL) {
1226 
1227 		error = USB_NO_RESOURCES;
1228 	} else {
1229 		/* Add the QTD into the Host Controller's bulk list */
1230 		ehci_insert_bulk_req(ehcip, ph, bulk_reqp, tw, usb_flags);
1231 	}
1232 
1233 	mutex_exit(&ehcip->ehci_int_mutex);
1234 
1235 	return (error);
1236 }
1237 
1238 
1239 /*
1240  * ehci_hcdi_pipe_intr_xfer:
1241  */
1242 int
1243 ehci_hcdi_pipe_intr_xfer(
1244 	usba_pipe_handle_data_t	*ph,
1245 	usb_intr_req_t		*intr_reqp,
1246 	usb_flags_t		usb_flags)
1247 {
1248 	ehci_state_t		*ehcip = ehci_obtain_state(
1249 				    ph->p_usba_device->usb_root_hub_dip);
1250 	int			pipe_dir, rval, error = USB_SUCCESS;
1251 	ehci_trans_wrapper_t	*tw;
1252 
1253 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1254 	    "ehci_hcdi_pipe_intr_xfer: ph = 0x%p reqp = 0x%p flags = %x",
1255 	    (void *)ph, intr_reqp, usb_flags);
1256 
1257 	mutex_enter(&ehcip->ehci_int_mutex);
1258 	rval = ehci_state_is_operational(ehcip);
1259 
1260 	if (rval != USB_SUCCESS) {
1261 		mutex_exit(&ehcip->ehci_int_mutex);
1262 
1263 		return (rval);
1264 	}
1265 
1266 	/* Get the pipe direction */
1267 	pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
1268 
1269 	if (pipe_dir == USB_EP_DIR_IN) {
1270 		error = ehci_start_periodic_pipe_polling(ehcip, ph,
1271 		    (usb_opaque_t)intr_reqp, usb_flags);
1272 	} else {
1273 		/* Allocate transaction resources */
1274 		if ((tw = ehci_allocate_intr_resources(ehcip, ph,
1275 		    intr_reqp, usb_flags)) == NULL) {
1276 
1277 			error = USB_NO_RESOURCES;
1278 		} else {
1279 			ehci_insert_intr_req(ehcip,
1280 			    (ehci_pipe_private_t *)ph->p_hcd_private,
1281 			    tw, usb_flags);
1282 		}
1283 	}
1284 
1285 	mutex_exit(&ehcip->ehci_int_mutex);
1286 
1287 	return (error);
1288 }
1289 
1290 /*
1291  * ehci_hcdi_pipe_stop_intr_polling()
1292  */
1293 int
1294 ehci_hcdi_pipe_stop_intr_polling(
1295 	usba_pipe_handle_data_t	*ph,
1296 	usb_flags_t		flags)
1297 {
1298 	ehci_state_t		*ehcip = ehci_obtain_state(
1299 				    ph->p_usba_device->usb_root_hub_dip);
1300 	int			error = USB_SUCCESS;
1301 
1302 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1303 	    "ehci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x",
1304 	    (void *)ph, flags);
1305 
1306 	mutex_enter(&ehcip->ehci_int_mutex);
1307 
1308 	error = ehci_stop_periodic_pipe_polling(ehcip, ph, flags);
1309 
1310 	mutex_exit(&ehcip->ehci_int_mutex);
1311 
1312 	return (error);
1313 }
1314 
1315 
1316 /*
1317  * ehci_hcdi_get_current_frame_number:
1318  *
1319  * Return the current usb frame number
1320  */
1321 usb_frame_number_t
1322 ehci_hcdi_get_current_frame_number(usba_device_t	*usba_device)
1323 {
1324 	ehci_state_t		*ehcip = ehci_obtain_state(
1325 		usba_device->usb_root_hub_dip);
1326 	usb_frame_number_t	frame_number;
1327 	int			rval;
1328 
1329 	ehcip = ehci_obtain_state(usba_device->usb_root_hub_dip);
1330 
1331 	mutex_enter(&ehcip->ehci_int_mutex);
1332 	rval = ehci_state_is_operational(ehcip);
1333 
1334 	if (rval != USB_SUCCESS) {
1335 		mutex_exit(&ehcip->ehci_int_mutex);
1336 
1337 		return (rval);
1338 	}
1339 
1340 	frame_number = ehci_get_current_frame_number(ehcip);
1341 
1342 	mutex_exit(&ehcip->ehci_int_mutex);
1343 
1344 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1345 	    "ehci_hcdi_get_current_frame_number: "
1346 	    "Current frame number 0x%llx", frame_number);
1347 
1348 	return (frame_number);
1349 }
1350 
1351 
1352 /*
1353  * ehci_hcdi_get_max_isoc_pkts:
1354  *
1355  * Return maximum isochronous packets per usb isochronous request
1356  */
1357 uint_t
1358 ehci_hcdi_get_max_isoc_pkts(usba_device_t	*usba_device)
1359 {
1360 	ehci_state_t		*ehcip = ehci_obtain_state(
1361 		usba_device->usb_root_hub_dip);
1362 	uint_t			max_isoc_pkts_per_request;
1363 	int			rval;
1364 
1365 	mutex_enter(&ehcip->ehci_int_mutex);
1366 	rval = ehci_state_is_operational(ehcip);
1367 	mutex_exit(&ehcip->ehci_int_mutex);
1368 
1369 	if (rval != USB_SUCCESS) {
1370 
1371 		return (rval);
1372 	}
1373 
1374 	max_isoc_pkts_per_request = EHCI_MAX_ISOC_PKTS_PER_XFER;
1375 
1376 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1377 	    "ehci_hcdi_get_max_isoc_pkts: maximum isochronous"
1378 	    "packets per usb isochronous request = 0x%x",
1379 	    max_isoc_pkts_per_request);
1380 
1381 	return (max_isoc_pkts_per_request);
1382 }
1383 
1384 
1385 /*
1386  * ehci_hcdi_pipe_isoc_xfer:
1387  */
1388 int
1389 ehci_hcdi_pipe_isoc_xfer(
1390 	usba_pipe_handle_data_t	*ph,
1391 	usb_isoc_req_t		*isoc_reqp,
1392 	usb_flags_t		usb_flags)
1393 {
1394 	ehci_state_t		*ehcip = ehci_obtain_state(
1395 				    ph->p_usba_device->usb_root_hub_dip);
1396 
1397 	int			pipe_dir, rval;
1398 	ehci_isoc_xwrapper_t	*itw;
1399 
1400 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1401 	    "ehci_hcdi_pipe_isoc_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x",
1402 	    (void *)ph, isoc_reqp, usb_flags);
1403 
1404 	mutex_enter(&ehcip->ehci_int_mutex);
1405 	rval = ehci_state_is_operational(ehcip);
1406 
1407 	if (rval != USB_SUCCESS) {
1408 		mutex_exit(&ehcip->ehci_int_mutex);
1409 
1410 		return (rval);
1411 	}
1412 
1413 	/* Get the isochronous pipe direction */
1414 	pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
1415 
1416 	if (pipe_dir == USB_EP_DIR_IN) {
1417 		rval = ehci_start_periodic_pipe_polling(ehcip, ph,
1418 		    (usb_opaque_t)isoc_reqp, usb_flags);
1419 	} else {
1420 		/* Allocate transaction resources */
1421 		if ((itw = ehci_allocate_isoc_resources(ehcip, ph,
1422 		    isoc_reqp, usb_flags)) == NULL) {
1423 			rval = USB_NO_RESOURCES;
1424 		} else {
1425 			rval = ehci_insert_isoc_req(ehcip,
1426 			    (ehci_pipe_private_t *)ph->p_hcd_private,
1427 			    itw, usb_flags);
1428 		}
1429 	}
1430 
1431 	mutex_exit(&ehcip->ehci_int_mutex);
1432 
1433 	return (rval);
1434 }
1435 
1436 
1437 /*
1438  * ehci_hcdi_pipe_stop_isoc_polling()
1439  */
1440 /*ARGSUSED*/
1441 int
1442 ehci_hcdi_pipe_stop_isoc_polling(
1443 	usba_pipe_handle_data_t	*ph,
1444 	usb_flags_t		flags)
1445 {
1446 	ehci_state_t		*ehcip = ehci_obtain_state(
1447 				    ph->p_usba_device->usb_root_hub_dip);
1448 	int			rval;
1449 
1450 	USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl,
1451 	    "ehci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x",
1452 	    (void *)ph, flags);
1453 
1454 	mutex_enter(&ehcip->ehci_int_mutex);
1455 	rval = ehci_state_is_operational(ehcip);
1456 
1457 	if (rval != USB_SUCCESS) {
1458 		mutex_exit(&ehcip->ehci_int_mutex);
1459 
1460 		return (rval);
1461 	}
1462 
1463 	rval = ehci_stop_periodic_pipe_polling(ehcip, ph, flags);
1464 
1465 	mutex_exit(&ehcip->ehci_int_mutex);
1466 
1467 	return (rval);
1468 }
1469