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