1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** USBX Component                                                        */
16 /**                                                                       */
17 /**   EHCI Controller Driver                                              */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary system files.  */
24 
25 #define UX_SOURCE_CODE
26 
27 #include "ux_api.h"
28 #include "ux_hcd_ehci.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_hcd_ehci_done_queue_process                     PORTABLE C      */
37 /*                                                           6.1.11       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function process the isochronous, periodic and asynchronous    */
45 /*    lists in search for transfers that occurred in the past             */
46 /*    (micro-)frame.                                                      */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    hcd_ehci                              Pointer to EHCI controller    */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    None                                                                */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _ux_hcd_ehci_asynch_td_process        Process asynch TD             */
59 /*    _ux_hcd_ehci_hsisochronous_tds_process                              */
60 /*                                          Process high speed            */
61 /*                                          isochronous TDs               */
62 /*    _ux_hcd_ehci_fsisochronous_tds_process                              */
63 /*                                          Process full speed (split)    */
64 /*                                          isochronous TDs               */
65 /*    _ux_utility_virtual_address           Get virtual address           */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    EHCI Controller Driver                                              */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
76 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
77 /*                                            resulting in version 6.1    */
78 /*  11-09-2020     Chaoqiong Xiao           Modified comment(s),          */
79 /*                                            fixed compile warning,      */
80 /*                                            resulting in version 6.1.2  */
81 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
82 /*                                            fixed standalone compile,   */
83 /*                                            resulting in version 6.1.11 */
84 /*                                                                        */
85 /**************************************************************************/
_ux_hcd_ehci_done_queue_process(UX_HCD_EHCI * hcd_ehci)86 VOID  _ux_hcd_ehci_done_queue_process(UX_HCD_EHCI *hcd_ehci)
87 {
88 
89 UX_EHCI_TD                      *td;
90 UX_EHCI_PERIODIC_LINK_POINTER   ed;
91 UX_EHCI_ED                      *start_ed;
92 
93 
94 #if UX_MAX_ISO_TD
95 UX_EHCI_PERIODIC_LINK_POINTER   lp;
96 
97     /* We scan the active isochronous list first.  */
98     _ux_host_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
99     lp.itd_ptr = hcd_ehci -> ux_hcd_ehci_hsiso_scan_list;
100     while(lp.itd_ptr != UX_NULL)
101     {
102 
103         /* Process the iTD, return next active TD.  */
104         lp.itd_ptr = _ux_hcd_ehci_hsisochronous_tds_process(hcd_ehci, lp.itd_ptr);
105     }
106     _ux_host_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
107 
108 #if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE)
109 
110     /* We scan the split isochronous list then.  */
111     _ux_host_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
112     lp.sitd_ptr = hcd_ehci -> ux_hcd_ehci_fsiso_scan_list;
113     while(lp.sitd_ptr != UX_NULL)
114     {
115 
116         /* Process the iTD, return next active TD.  */
117         lp.sitd_ptr = _ux_hcd_ehci_fsisochronous_tds_process(hcd_ehci, lp.sitd_ptr);
118     }
119     _ux_host_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
120 
121 #endif
122 #endif
123 
124     /* We scan the linked interrupt list then.  */
125     _ux_host_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
126     ed.ed_ptr = hcd_ehci -> ux_hcd_ehci_interrupt_ed_list;
127     while(ed.ed_ptr != UX_NULL)
128     {
129 
130         /* Retrieve the fist TD attached to this ED.  */
131         td =  ed.ed_ptr -> ux_ehci_ed_first_td;
132 
133         /* Process TD until there is no next available.  */
134         while (td != UX_NULL)
135             td =  _ux_hcd_ehci_asynch_td_process(ed.ed_ptr, td);
136 
137         /* Next ED.  */
138         ed.ed_ptr = ed.ed_ptr -> ux_ehci_ed_next_ed;
139     }
140     _ux_host_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
141 
142     /* Now we can parse the asynchronous list. The head ED is always empty and
143        used as an anchor only.  */
144     start_ed =  hcd_ehci -> ux_hcd_ehci_asynch_head_list;
145 
146     /* Point to the next ED in the asynchronous tree.  */
147     ed.ed_ptr = start_ed -> ux_ehci_ed_queue_head;
148     ed.value &= UX_EHCI_LINK_ADDRESS_MASK;
149 
150     /* Obtain the virtual address from the element.  */
151     ed.void_ptr = _ux_utility_virtual_address(ed.void_ptr);
152 
153     /* Now traverse this list until we have found a non anchor endpoint that
154        has transfers done.  */
155     while (ed.ed_ptr != start_ed)
156     {
157 
158         /* Retrieve the fist TD attached to this ED.  */
159         td =  ed.ed_ptr -> ux_ehci_ed_first_td;
160         while (td != UX_NULL)
161         {
162 
163             td =  _ux_hcd_ehci_asynch_td_process(ed.ed_ptr, td);
164         }
165 
166         /* Point to the next ED in the asynchronous tree.  */
167         ed.ed_ptr = ed.ed_ptr -> ux_ehci_ed_queue_head;
168         ed.value &= UX_EHCI_LINK_ADDRESS_MASK;
169 
170         /* Obtain the virtual address from the element.  */
171         ed.void_ptr = _ux_utility_virtual_address(ed.void_ptr);
172     }
173 }
174 
175