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 /** Asix Class */
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_host_class_asix.h"
30 #include "ux_host_stack.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _ux_host_class_asix_activate PORTABLE C */
38 /* 6.2.0 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function creates the asix instance, configure the device. */
46 /* WARNING !!!! The NX_PHYSICAL_HEADER should be set to 20 in nx_api.h */
47 /* */
48 /* INPUT */
49 /* */
50 /* command Asix class command pointer */
51 /* */
52 /* OUTPUT */
53 /* */
54 /* Completion Status */
55 /* */
56 /* CALLS */
57 /* */
58 /* _ux_host_class_asix_configure Configure asix class */
59 /* _ux_host_class_asix_endpoints_get Get endpoints of asix */
60 /* _ux_host_class_asix_setup Set up asix */
61 /* _ux_host_stack_class_instance_create Create class instance */
62 /* _ux_host_stack_class_instance_destroy Destroy the class instance */
63 /* _ux_host_stack_transfer_request Transfer request */
64 /* _ux_utility_memory_allocate Allocate memory block */
65 /* _ux_utility_memory_free Free memory block */
66 /* _ux_host_semaphore_create Create semaphore */
67 /* _ux_host_semaphore_delete Delete semaphore */
68 /* _ux_utility_thread_create Create thread */
69 /* _ux_utility_thread_delete Delete thread */
70 /* nx_packet_pool_create Create NetX packet pool */
71 /* */
72 /* CALLED BY */
73 /* */
74 /* _ux_host_class_asix_entry Entry of asix class */
75 /* */
76 /* RELEASE HISTORY */
77 /* */
78 /* DATE NAME DESCRIPTION */
79 /* */
80 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
81 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
82 /* used UX prefix to refer to */
83 /* TX symbols instead of using */
84 /* them directly, */
85 /* resulting in version 6.1 */
86 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
87 /* refined macros names, */
88 /* resulting in version 6.1.10 */
89 /* 10-31-2022 Chaoqiong Xiao Modified comment(s), */
90 /* moved NX driver activate, */
91 /* added reception buffer, */
92 /* removed internal NX pool, */
93 /* resulting in version 6.2.0 */
94 /* */
95 /**************************************************************************/
_ux_host_class_asix_activate(UX_HOST_CLASS_COMMAND * command)96 UINT _ux_host_class_asix_activate(UX_HOST_CLASS_COMMAND *command)
97 {
98 #if NX_PHYSICAL_HEADER < 20
99
100 UX_PARAMETER_NOT_USED(command);
101
102 /* Error trap - function not supported due to NX lib settings. */
103 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED);
104 return(UX_FUNCTION_NOT_SUPPORTED);
105 #else
106 UX_DEVICE *device;
107 UX_HOST_CLASS_ASIX *asix;
108 UINT status;
109 UX_TRANSFER *transfer_request;
110 ULONG physical_address_msw;
111 ULONG physical_address_lsw;
112
113
114 /* We need to make sure that the value of the NX_PHYSICAL_HEADER is at least 20.
115 This should be changed in the nx_user.h file */
116
117
118 /* The asix class is always activated by the device descriptor. */
119 device = (UX_DEVICE *) command -> ux_host_class_command_container;
120
121 /* Obtain memory for this class instance. */
122 asix = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_HOST_CLASS_ASIX));
123 if (asix == UX_NULL)
124 return(UX_MEMORY_INSUFFICIENT);
125
126 /* Store the class container into this instance. */
127 asix -> ux_host_class_asix_class = command -> ux_host_class_command_class_ptr;
128
129 /* Store the device container into the asix class instance. */
130 asix -> ux_host_class_asix_device = device;
131
132 /* Store the instance in the device container, this is for the USBX stack
133 when it needs to invoke the class for deactivation. */
134 device -> ux_device_class_instance = (VOID *) asix;
135
136 /* Create this class instance. */
137 _ux_host_stack_class_instance_create(asix -> ux_host_class_asix_class, (VOID *) asix);
138
139 /* Configure the asix class. */
140 status = _ux_host_class_asix_configure(asix);
141
142 /* Get the asix endpoint(s). We need to search for Bulk Out and Bulk In endpoints
143 and the interrupt endpoint. */
144 if (status == UX_SUCCESS)
145 status = _ux_host_class_asix_endpoints_get(asix);
146
147 /* Create the semaphore to protect 2 threads from accessing the same asix instance. */
148 if (status == UX_SUCCESS)
149 {
150 status = _ux_host_semaphore_create(&asix -> ux_host_class_asix_semaphore, "ux_host_class_asix_semaphore", 1);
151 if (status != UX_SUCCESS)
152 status = UX_SEMAPHORE_ERROR;
153 }
154
155 /* Create the semaphore to wake up the Asix thread. */
156 if(status == UX_SUCCESS)
157 {
158 status = _ux_host_semaphore_create(&asix -> ux_host_class_asix_interrupt_notification_semaphore, "ux_host_class_asix_interrupt_notification_semaphore", 0);
159 if (status != UX_SUCCESS)
160 status = UX_SEMAPHORE_ERROR;
161 }
162
163 /* Allocate a Thread stack. */
164 if (status == UX_SUCCESS)
165 {
166 asix -> ux_host_class_asix_thread_stack =
167 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
168
169 /* Check the completion status. */
170 if (asix -> ux_host_class_asix_thread_stack == UX_NULL)
171 status = UX_MEMORY_INSUFFICIENT;
172 }
173
174 /* Create the asix class thread. */
175 if (status == UX_SUCCESS)
176 {
177 status = _ux_utility_thread_create(&asix -> ux_host_class_asix_thread,
178 "ux_asix_thread", _ux_host_class_asix_thread,
179 (ULONG) asix,
180 asix -> ux_host_class_asix_thread_stack,
181 UX_THREAD_STACK_SIZE,
182 UX_THREAD_PRIORITY_CLASS,
183 UX_THREAD_PRIORITY_CLASS,
184 TX_NO_TIME_SLICE, UX_AUTO_START);
185
186 /* Check the completion status. */
187 if (status != UX_SUCCESS)
188 status = UX_THREAD_ERROR;
189 }
190
191 UX_THREAD_EXTENSION_PTR_SET(&(asix -> ux_host_class_asix_thread), asix)
192
193 /* The asix chip needs to be setup properly. */
194 if (status == UX_SUCCESS)
195 status = _ux_host_class_asix_setup(asix);
196
197 /* Go on if there is no error. */
198 if (status == UX_SUCCESS)
199 {
200
201 /* The ethernet link is down by default. */
202 asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_DOWN;
203
204 /* Start the interrupt pipe now. */
205 transfer_request = &asix -> ux_host_class_asix_interrupt_endpoint -> ux_endpoint_transfer_request;
206 status = _ux_host_stack_transfer_request(transfer_request);
207 }
208
209 /* Allocate some memory for reception. */
210 if (status == UX_SUCCESS)
211 {
212 asix -> ux_host_class_asix_receive_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_RECEIVE_BUFFER_SIZE);
213 if (asix -> ux_host_class_asix_receive_buffer == UX_NULL)
214 status = UX_MEMORY_INSUFFICIENT;
215 }
216
217 /* Activate network driver. */
218 if (status == UX_SUCCESS)
219 {
220
221 /* Setup the physical address of this IP instance. */
222 physical_address_msw = (ULONG)((asix -> ux_host_class_asix_node_id[0] << 8) | (asix -> ux_host_class_asix_node_id[1]));
223 physical_address_lsw = (ULONG)((asix -> ux_host_class_asix_node_id[2] << 24) | (asix -> ux_host_class_asix_node_id[3] << 16) |
224 (asix -> ux_host_class_asix_node_id[4] << 8) | (asix -> ux_host_class_asix_node_id[5]));
225
226 /* Register this interface to the NetX USB interface broker. */
227 status = _ux_network_driver_activate((VOID *) asix, _ux_host_class_asix_write,
228 &asix -> ux_host_class_asix_network_handle,
229 physical_address_msw,
230 physical_address_lsw);
231 }
232
233 /* Do final things if success. */
234 if (status == UX_SUCCESS)
235 {
236
237 /* Mark the asix instance as live now. */
238 asix -> ux_host_class_asix_state = UX_HOST_CLASS_INSTANCE_LIVE;
239
240 /* If all is fine and the device is mounted, we need to inform the application
241 if a function has been programmed in the system structure. */
242 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
243 {
244
245 /* Call system change function. */
246 _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, asix -> ux_host_class_asix_class, (VOID *) asix);
247 }
248
249 /* If trace is enabled, insert this event into the trace buffer. */
250 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_ASIX_ACTIVATE, asix, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
251
252 /* If trace is enabled, register this object. */
253 UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, asix, 0, 0, 0)
254
255 /* Return completion status. */
256 return(UX_SUCCESS);
257 }
258
259 /* There was a problem, so free the resources. */
260
261 /* Free asix -> ux_host_class_asix_receive_buffer. */
262 if (asix -> ux_host_class_asix_receive_buffer)
263 _ux_utility_memory_free(asix -> ux_host_class_asix_receive_buffer);
264
265 /* Free asix -> ux_host_class_asix_thread. */
266 if (asix -> ux_host_class_asix_thread.tx_thread_id)
267 _ux_utility_thread_delete(&asix -> ux_host_class_asix_thread);
268
269 /* Free asix -> ux_host_class_asix_thread_stack. */
270 if (asix -> ux_host_class_asix_thread_stack)
271 _ux_utility_memory_free(asix -> ux_host_class_asix_thread_stack);
272
273 /* Free asix -> ux_host_class_asix_interrupt_notification_semaphore. */
274 if (asix -> ux_host_class_asix_interrupt_notification_semaphore.tx_semaphore_id != 0)
275 _ux_host_semaphore_delete(&asix -> ux_host_class_asix_interrupt_notification_semaphore);
276
277 /* Free asix -> ux_host_class_asix_semaphore. */
278 if (asix -> ux_host_class_asix_semaphore.tx_semaphore_id != 0)
279 _ux_host_semaphore_delete(&asix -> ux_host_class_asix_semaphore);
280
281 /* Destroy class instance. */
282 _ux_host_stack_class_instance_destroy(asix -> ux_host_class_asix_class, (VOID *) asix);
283
284 /* Detach instance. */
285 device -> ux_device_class_instance = UX_NULL;
286
287 /* Free instance memory. */
288 _ux_utility_memory_free(asix);
289
290 /* Return completion status. */
291 return(status);
292 #endif
293 }
294
295