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