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.
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 }
|
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.
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 }
|