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