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