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