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 /** Host Simulator Controller Driver */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define UX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "ux_api.h"
28 #include "ux_hcd_sim_host.h"
29 #include "ux_dcd_sim_slave.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_hcd_sim_host_initialize PORTABLE C */
37 /* 6.3.0 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function initializes the simulated host controller */
45 /* */
46 /* INPUT */
47 /* */
48 /* HCD Pointer to HCD */
49 /* */
50 /* OUTPUT */
51 /* */
52 /* Completion Status */
53 /* */
54 /* CALLS */
55 /* */
56 /* _ux_hcd_sim_host_periodic_tree_create Create periodic tree */
57 /* _ux_utility_memory_allocate Allocate memory block */
58 /* _ux_utility_semaphore_put Semaphore put */
59 /* _ux_utility_timer_create Create timer */
60 /* */
61 /* CALLED BY */
62 /* */
63 /* Host Simulator Controller Driver */
64 /* */
65 /* RELEASE HISTORY */
66 /* */
67 /* DATE NAME DESCRIPTION */
68 /* */
69 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
70 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
71 /* optimized based on compile */
72 /* definitions, used UX prefix */
73 /* to refer to TX symbols */
74 /* instead of using them */
75 /* directly, */
76 /* resulting in version 6.1 */
77 /* 04-02-2021 Chaoqiong Xiao Modified comment(s), */
78 /* added link with DCD, */
79 /* resulting in version 6.1.6 */
80 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
81 /* added standalone support, */
82 /* resulting in version 6.1.10 */
83 /* 10-31-2023 Yajun Xia Modified comment(s), */
84 /* refined memory management, */
85 /* resulting in version 6.3.0 */
86 /* */
87 /**************************************************************************/
_ux_hcd_sim_host_initialize(UX_HCD * hcd)88 UINT _ux_hcd_sim_host_initialize(UX_HCD *hcd)
89 {
90
91 UX_SLAVE_DCD *dcd;
92 UX_DCD_SIM_SLAVE *dcd_sim_slave;
93 UX_HCD_SIM_HOST *hcd_sim_host;
94 UINT status = UX_ERROR;
95
96
97 /* The controller initialized here is of host simulator type. */
98 hcd -> ux_hcd_controller_type = UX_HCD_SIM_HOST_CONTROLLER;
99
100 /* Allocate memory for this host simulator HCD instance. */
101 hcd_sim_host = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HCD_SIM_HOST));
102 if (hcd_sim_host == UX_NULL)
103 return(UX_MEMORY_INSUFFICIENT);
104
105 /* Set the pointer to the host simulator HCD. */
106 hcd -> ux_hcd_controller_hardware = (VOID *) hcd_sim_host;
107
108 /* Set the generic HCD owner for the host simulator HCD. */
109 hcd_sim_host -> ux_hcd_sim_host_hcd_owner = hcd;
110
111 /* Initialize the function collector for this HCD. */
112 hcd -> ux_hcd_entry_function = _ux_hcd_sim_host_entry;
113
114 #if UX_MAX_DEVICES > 1
115 /* Initialize the max bandwidth for periodic endpoints. In simulation this is
116 not very important. */
117 hcd -> ux_hcd_available_bandwidth = UX_HCD_SIM_HOST_AVAILABLE_BANDWIDTH;
118 #endif
119
120 /* Set the state of the controller to HALTED first. */
121 hcd -> ux_hcd_status = UX_HCD_STATUS_HALTED;
122
123 /* Allocate the list of EDs. All EDs are allocated on 16 byte memory boundary. */
124 if (_ux_system_host -> ux_system_host_max_ed != 0)
125 {
126 hcd_sim_host -> ux_hcd_sim_host_ed_list = _ux_utility_memory_allocate(UX_ALIGN_16, UX_REGULAR_MEMORY, (ULONG)sizeof(UX_HCD_SIM_HOST_ED) * _ux_system_host -> ux_system_host_max_ed);
127 if (hcd_sim_host -> ux_hcd_sim_host_ed_list == UX_NULL)
128 status = UX_MEMORY_INSUFFICIENT;
129 else
130 status = UX_SUCCESS;
131 }
132
133 /* Allocate the list of TDs. All TDs are allocated on 32 byte memory boundary. */
134 if ((status == UX_SUCCESS) && (_ux_system_host -> ux_system_host_max_td != 0))
135 {
136 hcd_sim_host -> ux_hcd_sim_host_td_list = _ux_utility_memory_allocate(UX_ALIGN_32, UX_REGULAR_MEMORY, (ULONG)sizeof(UX_HCD_SIM_HOST_TD) * _ux_system_host -> ux_system_host_max_td);
137 if (hcd_sim_host -> ux_hcd_sim_host_td_list == UX_NULL)
138 status = UX_MEMORY_INSUFFICIENT;
139 }
140
141 /* Allocate the list of isochronous TDs. All TDs are allocated on 32 byte memory boundary. */
142 if ((status == UX_SUCCESS) && (_ux_system_host -> ux_system_host_max_iso_td != 0))
143 {
144 hcd_sim_host -> ux_hcd_sim_host_iso_td_list = _ux_utility_memory_allocate(UX_ALIGN_32, UX_REGULAR_MEMORY, (ULONG)sizeof(UX_HCD_SIM_HOST_ISO_TD) * _ux_system_host -> ux_system_host_max_iso_td);
145 if (hcd_sim_host -> ux_hcd_sim_host_iso_td_list == UX_NULL)
146 status = UX_MEMORY_INSUFFICIENT;
147 }
148
149 /* Initialize the periodic tree. */
150 if (status == UX_SUCCESS)
151 status = _ux_hcd_sim_host_periodic_tree_create(hcd_sim_host);
152
153 /* Initialize the scheduler. */
154 if (status == UX_SUCCESS)
155 {
156 /* Set the host controller into the operational state. */
157 hcd -> ux_hcd_status = UX_HCD_STATUS_OPERATIONAL;
158
159 /* The asynchronous queues are empty for now. */
160 hcd_sim_host -> ux_hcd_sim_host_queue_empty = UX_TRUE;
161
162 /* The periodic scheduler is not active. */
163 hcd_sim_host -> ux_hcd_sim_host_periodic_scheduler_active = 0;
164
165 /* We start a timer that will invoke the simulator every timer tick. */
166 status = _ux_host_timer_create(&hcd_sim_host -> ux_hcd_sim_host_timer, "USBX Simulation Timer",
167 _ux_hcd_sim_host_timer_function, (ULONG) (ALIGN_TYPE) hcd_sim_host, 1, 1, UX_AUTO_ACTIVATE);
168 }
169
170 UX_TIMER_EXTENSION_PTR_SET(&(hcd_sim_host -> ux_hcd_sim_host_timer), hcd_sim_host)
171
172 /* Free up resources and return when there is error. */
173 if (status != UX_SUCCESS)
174 {
175
176 /* Set the host controller into the halt state. */
177 hcd -> ux_hcd_status = UX_HCD_STATUS_HALTED;
178
179 /* The last resource, timer is not created or created error,
180 * no need to delete. */
181
182 if (hcd_sim_host -> ux_hcd_sim_host_iso_td_list)
183 _ux_utility_memory_free(hcd_sim_host -> ux_hcd_sim_host_iso_td_list);
184 if (hcd_sim_host -> ux_hcd_sim_host_td_list)
185 _ux_utility_memory_free(hcd_sim_host -> ux_hcd_sim_host_td_list);
186 if (hcd_sim_host -> ux_hcd_sim_host_ed_list)
187 _ux_utility_memory_free(hcd_sim_host -> ux_hcd_sim_host_ed_list);
188 _ux_utility_memory_free(hcd_sim_host);
189
190 return(status);
191 }
192
193 /* Link the HCD to DCD driver. */
194 if (_ux_system_slave)
195 {
196 dcd = &_ux_system_slave -> ux_system_slave_dcd;
197 if (dcd)
198 {
199 dcd_sim_slave = (UX_DCD_SIM_SLAVE *) dcd -> ux_slave_dcd_controller_hardware;
200 if (dcd_sim_slave)
201 dcd_sim_slave -> ux_dcd_sim_slave_hcd = (VOID *)hcd;
202 }
203 }
204
205 /* Get the number of ports on the controller. The number of ports needs to be reflected both
206 for the generic HCD container and the local sim_host container. In the simulator,
207 the number of ports is hardwired to 1 only. */
208 hcd -> ux_hcd_nb_root_hubs = 1;
209 hcd_sim_host -> ux_hcd_sim_host_nb_root_hubs = 1;
210 hcd_sim_host -> ux_hcd_sim_host_port_status[0] = UX_PS_CCS | UX_PS_DS_FS;
211
212 /* Something happened on this port. Signal it to the root hub thread. */
213 hcd -> ux_hcd_root_hub_signal[0] = 1;
214
215 /* We need to simulate a Root HUB Status Change for the USB stack since the simulator
216 has not root HUB per se. */
217 status = _ux_host_semaphore_put_rc(&_ux_system_host -> ux_system_host_enum_semaphore);
218 if (status != UX_SUCCESS)
219
220 /* Resources are still ready but
221 * failed to simulate Root HUB change! */
222 return(UX_SEMAPHORE_ERROR);
223
224 /* Return successful completion. */
225 return(UX_SUCCESS);
226 }
227
228