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