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