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_endpoint_destroy             PORTABLE C      */
38 /*                                                           6.1.11       */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function will destroy an interrupt endpoint.                   */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    hcd_ehci                              Pointer to EHCI controller    */
50 /*    endpoint                              Pointer to endpoint           */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    Completion Status                                                   */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _ux_hcd_ehci_door_bell_wait           Setup doorbell wait           */
59 /*    _ux_utility_physical_address          Get physical address          */
60 /*    _ux_host_mutex_on                     Get mutex                     */
61 /*    _ux_host_mutex_off                    Put mutex                     */
62 /*    _ux_hcd_ehci_periodic_descriptor_link Link/unlink descriptor        */
63 /*                                                                        */
64 /*  CALLED BY                                                             */
65 /*                                                                        */
66 /*    EHCI Controller Driver                                              */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
73 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*  11-09-2020     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            fixed compile warnings,     */
77 /*                                            resulting in version 6.1.2  */
78 /*  04-02-2021     Chaoqiong Xiao           Modified comment(s),          */
79 /*                                            fixed compile issues with   */
80 /*                                            some macro options,         */
81 /*                                            resulting in version 6.1.6  */
82 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
83 /*                                            fixed standalone compile,   */
84 /*                                            resulting in version 6.1.11 */
85 /*                                                                        */
86 /**************************************************************************/
_ux_hcd_ehci_interrupt_endpoint_destroy(UX_HCD_EHCI * hcd_ehci,UX_ENDPOINT * endpoint)87 UINT  _ux_hcd_ehci_interrupt_endpoint_destroy(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint)
88 {
89 
90 UX_EHCI_ED                    *ed;
91 UX_EHCI_ED                    *prev_ed;
92 ULONG                         frindex;
93 ULONG                         max_packet_size;
94 
95 
96     /* From the endpoint container fetch the EHCI ED descriptor.  */
97     ed =  (UX_EHCI_ED *) endpoint -> ux_endpoint_ed;
98 
99     /* Access to periodic list.  */
100     _ux_host_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
101 
102     /* Unlink the periodic item.  */
103     _ux_hcd_ehci_periodic_descriptor_link(ed -> ux_ehci_ed_previous_ed,
104             UX_NULL, UX_NULL, ed -> ux_ehci_ed_queue_head);
105 
106     /* Update the interrupt ED scan list.  */
107     prev_ed = hcd_ehci -> ux_hcd_ehci_interrupt_ed_list;
108 
109     /* Check if ED in head of scan list.  */
110     if (prev_ed == ed)
111 
112         /* Point head to the next ED.  */
113         hcd_ehci -> ux_hcd_ehci_interrupt_ed_list = ed -> ux_ehci_ed_next_ed;
114     else
115     {
116 
117         /* Try to find previous ED in scan list.  */
118         /* It's at head now.  */
119         while(prev_ed -> ux_ehci_ed_next_ed)
120         {
121 
122             /* The expected ED is found.  */
123             if (prev_ed -> ux_ehci_ed_next_ed == ed)
124             {
125 
126                 /* Point next to next of the ED.  */
127                 prev_ed -> ux_ehci_ed_next_ed = ed -> ux_ehci_ed_next_ed;
128                 break;
129             }
130 
131             /* Try next ED.  */
132             prev_ed = prev_ed -> ux_ehci_ed_next_ed;
133         }
134     }
135 
136     /* Update micro-frame loads of anchor.  */
137 
138     /* Calculate max packet size.  */
139 #if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE)
140     if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE)
141         max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK;
142     else
143 #endif
144     {
145         max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK;
146         max_packet_size >>= UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT;
147         if (max_packet_size < 3)
148             max_packet_size ++;
149         max_packet_size *= endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK;
150     }
151 
152     /* Update according to ED S-Mask.  */
153     for(frindex = 0; frindex < 8; frindex ++)
154     {
155 
156         /* Check schedule mask.  */
157         if ((ed -> ux_ehci_ed_cap1 & (UX_EHCI_SMASK_0 << frindex)))
158         {
159 
160 #if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE)
161 
162             /* Start split check.  */
163             if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE)
164             {
165 
166                 /* Decrement the start split count.  */
167                 ed -> REF_AS.INTR.ux_ehci_ed_anchor -> REF_AS.ANCHOR.ux_ehci_ed_microframe_ssplit_count[frindex] --;
168 
169                 /* Check next endpoint if it's IN (load in C-Mask).  */
170                 if (endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION)
171                     continue;
172             }
173 #endif
174             /* Decrement the microframe load.  */
175             ed -> REF_AS.INTR.ux_ehci_ed_anchor -> REF_AS.ANCHOR.ux_ehci_ed_microframe_load[frindex] = (USHORT)(ed -> REF_AS.INTR.ux_ehci_ed_anchor -> REF_AS.ANCHOR.ux_ehci_ed_microframe_load[frindex] - max_packet_size);
176 
177             /* S-Mask found, no C-Mask at the same time, skip C-Mask check.  */
178             continue;
179         }
180 
181 #if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE)
182 
183         /* Complete split interrupt IN check in C-Mask.  */
184         if ((endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) &&
185             (endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) &&
186             (ed -> ux_ehci_ed_cap1 & (UX_EHCI_CMASK_0 << frindex)))
187         {
188 
189             /* Decrement the microframe load.  */
190             ed -> REF_AS.INTR.ux_ehci_ed_anchor -> REF_AS.ANCHOR.ux_ehci_ed_microframe_load[frindex] = (USHORT)(ed -> REF_AS.INTR.ux_ehci_ed_anchor -> REF_AS.ANCHOR.ux_ehci_ed_microframe_load[frindex] - max_packet_size);
191         }
192 #endif
193     }
194 
195     /* Release periodic list.  */
196     _ux_host_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
197 
198     /* Arm the doorbell and wait for its completion.  */
199     _ux_hcd_ehci_door_bell_wait(hcd_ehci);
200 
201     /* Now we can safely make the ED free.  */
202     ed -> ux_ehci_ed_status =  UX_UNUSED;
203 
204     /* Return successful completion.  */
205     return(UX_SUCCESS);
206 }
207 
208