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