1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   EHCI Controller Driver                                              */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_hcd_ehci.h"
30 #include "ux_host_stack.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_hcd_ehci_interrupt_handler                      PORTABLE C      */
38 /*                                                           6.1.10       */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function is the interrupt handler for the EHCI interrupts.     */
46 /*    Normally an interrupt occurs from the controller when there is      */
47 /*    either a EOF signal and there has been transfers within the frame   */
48 /*    or when there is a change on one of the downstream ports, a         */
49 /*    doorbell signal or an unrecoverable error.                          */
50 /*                                                                        */
51 /*    All we need to do in the ISR is scan the controllers to find out    */
52 /*    which one has issued a IRQ. If there is work to do for this         */
53 /*    controller we need to wake up the corresponding thread to take care */
54 /*    of the job.                                                         */
55 /*                                                                        */
56 /*  INPUT                                                                 */
57 /*                                                                        */
58 /*    None                                                                */
59 /*                                                                        */
60 /*  OUTPUT                                                                */
61 /*                                                                        */
62 /*    None                                                                */
63 /*                                                                        */
64 /*  CALLS                                                                 */
65 /*                                                                        */
66 /*    _ux_hcd_ehci_controller_disable       Disable controller            */
67 /*    _ux_hcd_ehci_register_read            Read EHCI register            */
68 /*    _ux_hcd_ehci_register_write           Write EHCI register           */
69 /*    _ux_host_semaphore_put                Put semaphore                 */
70 /*                                                                        */
71 /*  CALLED BY                                                             */
72 /*                                                                        */
73 /*    EHCI Controller Driver                                              */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
80 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
81 /*                                            resulting in version 6.1    */
82 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
83 /*                                            refined macros names,       */
84 /*                                            resulting in version 6.1.10 */
85 /*                                                                        */
86 /**************************************************************************/
_ux_hcd_ehci_interrupt_handler(VOID)87 VOID  _ux_hcd_ehci_interrupt_handler(VOID)
88 {
89 
90 UINT            hcd_index;
91 UX_HCD          *hcd;
92 UX_HCD_EHCI     *hcd_ehci;
93 ULONG           ehci_register;
94 ULONG           ehci_register_port_status;
95 ULONG           root_hub_thread_wakeup = 0;
96 ULONG           port_index;
97 
98 
99     /* We need to parse the controller driver table to find all controllers that registered
100        as EHCI.  */
101     for (hcd_index = 0; hcd_index < _ux_system_host -> ux_system_host_registered_hcd; hcd_index++)
102     {
103 
104         /* Check type of controller.  */
105         if (_ux_system_host -> ux_system_host_hcd_array[hcd_index].ux_hcd_controller_type == UX_EHCI_CONTROLLER)
106         {
107 
108             /* Get the pointers to the generic HCD and EHCI specific areas.  */
109             hcd =  &_ux_system_host -> ux_system_host_hcd_array[hcd_index];
110             hcd_ehci =  (UX_HCD_EHCI *) hcd -> ux_hcd_controller_hardware;
111 
112             /* Check if the controller is operational, if not, skip it.  */
113             if (hcd -> ux_hcd_status == UX_HCD_STATUS_OPERATIONAL)
114             {
115 
116                 /* For debugging purposes, increment the interrupt count.  */
117                 hcd_ehci -> ux_hcd_ehci_interrupt_count++;
118 
119                 /* We get the current interrupt status for this controller.  */
120                 ehci_register =  _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_STATUS);
121 
122                 /* We  acknowledge the interrupts for this controller so that it
123                    can continue to work.  */
124                 _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_STATUS, ehci_register);
125 
126                 /* Examine the source of interrupts.  */
127                 if ((ehci_register & EHCI_HC_STS_USB_INT) || (ehci_register & EHCI_HC_STS_USB_ERR_INT))
128                 {
129 
130                     /* We have some transactions done in the past frame/micro-frame.
131                        The controller thread needs to wake up and process them.  */
132                     hcd -> ux_hcd_thread_signal++;
133                     _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore);
134                 }
135 
136                 if (ehci_register & EHCI_HC_STS_HSE)
137                 {
138 
139                     /* The controller has issued a Host System Error which is fatal.
140                        The controller will be reset now, and we wake up the HCD thread.  */
141                     _ux_hcd_ehci_controller_disable(hcd_ehci);
142                     hcd -> ux_hcd_thread_signal++;
143                     hcd -> ux_hcd_status =  UX_HCD_STATUS_DEAD;
144                     hcd -> ux_hcd_thread_signal++;
145                     _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore);
146 
147                     /* Error trap. */
148                     _ux_system_error_handler(UX_SYSTEM_LEVEL_INTERRUPT, UX_SYSTEM_CONTEXT_HCD, UX_CONTROLLER_DEAD);
149 
150                 }
151 
152                 if (ehci_register & EHCI_HC_STS_PCD)
153                 {
154 
155                     /* The controller has issued a Root hub status change signal. Scan all ports.  */
156                     for (port_index = 0; port_index < hcd_ehci -> ux_hcd_ehci_nb_root_hubs; port_index++)
157                     {
158 
159                         /* Read the port status.  */
160                         ehci_register_port_status =  _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index);
161 
162                         /* Check for Connect Status Change signal.  */
163                         if (ehci_register_port_status &  EHCI_HC_PS_CSC)
164                         {
165                             /* Something happened on this port. Signal it to the root hub thread.  */
166                             hcd -> ux_hcd_root_hub_signal[port_index]++;
167 
168                             /* Memorize wake up signal.  */
169                             root_hub_thread_wakeup ++;
170 
171                         }
172 
173                     }
174 
175                     /* We only wake up the root hub thread if there has been device insertion/extraction.  */
176                     if (root_hub_thread_wakeup != 0)
177 
178                         /* The controller has issued a Root hub status change signal.
179                            We need to resume the thread in charge of the USB topology.  */
180                         _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
181                 }
182 
183                 if (ehci_register & EHCI_HC_STS_IAA)
184                 {
185 
186                     /* The controller has issued a Door Bell status change signal.
187                        We need to resume the thread who raised the doorbell.  */
188                     _ux_host_semaphore_put(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore);
189                 }
190             }
191         }
192     }
193 }
194 
195