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