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 /**   Asix Class                                                          */
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_host_class_asix.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_asix_setup                           PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function prepares the Asix chip Phy and rx and xmit registers. */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    asix                                         Pointer to asix class  */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    Completion Status                                                   */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _ux_host_stack_transfer_request       Transfer request              */
57 /*    _ux_utility_memory_allocate           Allocate memory               */
58 /*    _ux_utility_memory_free               Free memory                   */
59 /*                                                                        */
60 /*  CALLED BY                                                             */
61 /*                                                                        */
62 /*    _ux_host_class_asix_activate                                        */
63 /*                                                                        */
64 /*  RELEASE HISTORY                                                       */
65 /*                                                                        */
66 /*    DATE              NAME                      DESCRIPTION             */
67 /*                                                                        */
68 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
69 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
70 /*                                            verified memset and memcpy  */
71 /*                                            cases,                      */
72 /*                                            resulting in version 6.1    */
73 /*                                                                        */
74 /**************************************************************************/
_ux_host_class_asix_setup(UX_HOST_CLASS_ASIX * asix)75 UINT  _ux_host_class_asix_setup(UX_HOST_CLASS_ASIX *asix)
76 {
77 
78 UCHAR                       *setup_buffer;
79 UX_ENDPOINT                 *control_endpoint;
80 UX_TRANSFER                 *transfer_request;
81 ULONG                        phy_register_value;
82 UINT                        status;
83 
84     /* We need to get the default control endpoint transfer request pointer.  */
85     control_endpoint =  &asix -> ux_host_class_asix_device -> ux_device_control_endpoint;
86     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
87 
88     /* Need to allocate memory for the buffer.  */
89     setup_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_SETUP_BUFFER_SIZE);
90     if (setup_buffer == UX_NULL)
91         return(UX_MEMORY_INSUFFICIENT);
92 
93     /* Get the Ethernet Phy Address register.  */
94     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
95     transfer_request -> ux_transfer_request_requested_length    =  2;
96     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_READ_PHY_ID;
97     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
98     transfer_request -> ux_transfer_request_value               =  0;
99     transfer_request -> ux_transfer_request_index               =  0;
100 
101     /* Send request to HCD layer.  */
102     status =  _ux_host_stack_transfer_request(transfer_request);
103 
104     /* Check status, if error, do not proceed.  */
105     if ((status != UX_SUCCESS) || (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) ||
106             (transfer_request -> ux_transfer_request_actual_length != 2))
107     {
108 
109         /* Free all used resources.  */
110         _ux_utility_memory_free(setup_buffer);
111 
112         /* Return completion status.  */
113         return(UX_TRANSFER_ERROR);
114 
115     }
116 
117     /* Extract the  PHY IDs and the type.  */
118     asix -> ux_host_class_asix_primary_phy_id = *(setup_buffer + UX_HOST_CLASS_ASIX_PHY_ID_PRIMARY) & UX_HOST_CLASS_ASIX_PHY_ID_MASK;
119     asix -> ux_host_class_asix_primary_phy_type = (*(setup_buffer + UX_HOST_CLASS_ASIX_PHY_ID_PRIMARY)  >> UX_HOST_CLASS_ASIX_PHY_TYPE_SHIFT) & UX_HOST_CLASS_ASIX_PHY_TYPE_MASK;
120 
121     asix -> ux_host_class_asix_secondary_phy_id = *(setup_buffer + UX_HOST_CLASS_ASIX_PHY_ID_SECONDARY) & UX_HOST_CLASS_ASIX_PHY_ID_MASK;
122     asix -> ux_host_class_asix_secondary_phy_type = (*(setup_buffer + UX_HOST_CLASS_ASIX_PHY_ID_SECONDARY)  >> UX_HOST_CLASS_ASIX_PHY_TYPE_SHIFT) & UX_HOST_CLASS_ASIX_PHY_TYPE_MASK;
123 
124     /* Set the GPIO 2 register.  */
125     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
126     transfer_request -> ux_transfer_request_requested_length    =  0;
127     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_WRITE_GPIO_STATUS;
128     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
129     transfer_request -> ux_transfer_request_value               =  (UX_HOST_CLASS_ASIX_GPIO_RSE | UX_HOST_CLASS_ASIX_GPIO_GPO2EN | UX_HOST_CLASS_ASIX_GPIO_GPO_2);
130     transfer_request -> ux_transfer_request_index               =  0;
131 
132     /* Send request to HCD layer.  */
133     status =  _ux_host_stack_transfer_request(transfer_request);
134 
135     /* Check status, if error, do not proceed.  */
136     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
137     {
138 
139         /* Free all used resources.  */
140         _ux_utility_memory_free(setup_buffer);
141 
142         /* Return completion status.  */
143         return(UX_TRANSFER_ERROR);
144 
145     }
146 
147     /* Set the Software PHY Select register.  */
148     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
149     transfer_request -> ux_transfer_request_requested_length    =  0;
150     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_WRITE_SW_PHY_SELECT_STATUS;
151     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
152     transfer_request -> ux_transfer_request_value               =  1;
153     transfer_request -> ux_transfer_request_index               =  0;
154 
155     /* Send request to HCD layer.  */
156     status =  _ux_host_stack_transfer_request(transfer_request);
157 
158     /* Check status, if error, do not proceed.  */
159     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
160     {
161 
162         /* Free all used resources.  */
163         _ux_utility_memory_free(setup_buffer);
164 
165         /* Return completion status.  */
166         return(UX_TRANSFER_ERROR);
167 
168     }
169 
170     /* Perform a software reset of IPPD.  */
171     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
172     transfer_request -> ux_transfer_request_requested_length    =  0;
173     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_SW_RESET;
174     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
175     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_ASIX_SW_RESET_IPPD;
176     transfer_request -> ux_transfer_request_index               =  0;
177 
178     /* Send request to HCD layer.  */
179     status =  _ux_host_stack_transfer_request(transfer_request);
180 
181     /* Check status, if error, do not proceed.  */
182     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
183     {
184 
185         /* Free all used resources.  */
186         _ux_utility_memory_free(setup_buffer);
187 
188         /* Return completion status.  */
189         return(UX_TRANSFER_ERROR);
190 
191     }
192 
193     /* Perform a software reset.  */
194     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
195     transfer_request -> ux_transfer_request_requested_length    =  0;
196     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_SW_RESET;
197     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
198     transfer_request -> ux_transfer_request_value               =  0;
199     transfer_request -> ux_transfer_request_index               =  0;
200 
201     /* Send request to HCD layer.  */
202     status =  _ux_host_stack_transfer_request(transfer_request);
203 
204     /* Check status, if error, do not proceed.  */
205     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
206     {
207 
208         /* Free all used resources.  */
209         _ux_utility_memory_free(setup_buffer);
210 
211         /* Return completion status.  */
212         return(UX_TRANSFER_ERROR);
213 
214     }
215 
216 
217     /* Perform a software reset of IPRL and PRL.  */
218     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
219     transfer_request -> ux_transfer_request_requested_length    =  0;
220     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_SW_RESET;
221     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
222     transfer_request -> ux_transfer_request_value               =  (UX_HOST_CLASS_ASIX_SW_RESET_IPRL | UX_HOST_CLASS_ASIX_SW_RESET_PRL);
223     transfer_request -> ux_transfer_request_index               =  0;
224 
225     /* Send request to HCD layer.  */
226     status =  _ux_host_stack_transfer_request(transfer_request);
227 
228     /* Check status, if error, do not proceed.  */
229     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
230     {
231 
232         /* Free all used resources.  */
233         _ux_utility_memory_free(setup_buffer);
234 
235         /* Return completion status.  */
236         return(UX_TRANSFER_ERROR);
237 
238     }
239 
240     /* Write the value of the Receive Control register.  */
241     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
242     transfer_request -> ux_transfer_request_requested_length    =  0;
243     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_WRITE_RX_CTL;
244     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
245     transfer_request -> ux_transfer_request_value               =  0;
246     transfer_request -> ux_transfer_request_index               =  UX_HOST_CLASS_ASIX_RXCR_MFB_2048;
247 
248     /* Send request to HCD layer.  */
249     status =  _ux_host_stack_transfer_request(transfer_request);
250 
251     /* Check status, if error, do not proceed.  */
252     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
253     {
254 
255         /* Free all used resources.  */
256         _ux_utility_memory_free(setup_buffer);
257 
258         /* Return completion status.  */
259         return(UX_TRANSFER_ERROR);
260 
261     }
262 
263     /* Get the Ethernet Phy Address register.  */
264     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
265     transfer_request -> ux_transfer_request_requested_length    =  UX_HOST_CLASS_ASIX_NODE_ID_LENGTH;
266     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_READ_NODE_ID;
267     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
268     transfer_request -> ux_transfer_request_value               =  0;
269     transfer_request -> ux_transfer_request_index               =  0;
270 
271     /* Send request to HCD layer.  */
272     status =  _ux_host_stack_transfer_request(transfer_request);
273 
274     /* Check status, if error, do not proceed.  */
275     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS ||
276         transfer_request -> ux_transfer_request_actual_length != UX_HOST_CLASS_ASIX_NODE_ID_LENGTH)
277     {
278 
279         /* Free all used resources.  */
280         _ux_utility_memory_free(setup_buffer);
281 
282         /* Return completion status.  */
283         return(UX_TRANSFER_ERROR);
284 
285     }
286 
287 
288     /* Copy the node id into the Asix instance.  */
289     _ux_utility_memory_copy(asix -> ux_host_class_asix_node_id, setup_buffer, UX_HOST_CLASS_ASIX_NODE_ID_LENGTH); /* Use case of memcpy is verified. */
290 
291     /* Request ownership of Serial Management Interface.  */
292     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
293     transfer_request -> ux_transfer_request_requested_length    =  0;
294     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_OWN_SMI ;
295     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
296     transfer_request -> ux_transfer_request_value               =  0;
297     transfer_request -> ux_transfer_request_index               =  0;
298 
299     /* Send request to HCD layer.  */
300     status =  _ux_host_stack_transfer_request(transfer_request);
301 
302     /* Check status, if error, do not proceed.  */
303     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
304     {
305 
306         /* Free all used resources.  */
307         _ux_utility_memory_free(setup_buffer);
308 
309         /* Return completion status.  */
310         return(UX_TRANSFER_ERROR);
311 
312     }
313 
314 
315     /* Get the value of the PHYIDR1 in the PHY register.  */
316     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
317     transfer_request -> ux_transfer_request_requested_length    =  2;
318     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_READ_PHY_REG;
319     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
320     transfer_request -> ux_transfer_request_value               =  asix -> ux_host_class_asix_primary_phy_id;
321     transfer_request -> ux_transfer_request_index               =  UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1;
322 
323     /* Send request to HCD layer.  */
324     status =  _ux_host_stack_transfer_request(transfer_request);
325 
326     /* Check status, if error, do not proceed.  */
327     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS ||
328         transfer_request -> ux_transfer_request_actual_length != 2)
329     {
330 
331         /* Free all used resources.  */
332         _ux_utility_memory_free(setup_buffer);
333 
334         /* Return completion status.  */
335         return(UX_TRANSFER_ERROR);
336 
337     }
338 
339     /* Extract the Vendor model number and model revision number.  First get the value
340        in proper 16 bit little endian.  */
341     phy_register_value = _ux_utility_short_get(setup_buffer);
342 
343     /* Get the model revision number.  */
344     asix -> ux_host_class_asix_model_revision_number = (phy_register_value >> UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_MDL_REV_SHIFT) & UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_MDL_REV_MASK;
345 
346     /* Get the vendor model number.  */
347     asix -> ux_host_class_asix_vendor_model_number   = (phy_register_value >> UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_VNDR_REV_SHIFT) & UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_VNDR_REV_MASK ;
348 
349 
350     /* Perform a software reset.  External Phy Reset Pin level. */
351     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
352     transfer_request -> ux_transfer_request_requested_length    =  0;
353     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_SW_RESET;
354     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
355     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_ASIX_SW_RESET_PRL;
356     transfer_request -> ux_transfer_request_index               =  0;
357 
358     /* Send request to HCD layer.  */
359     status =  _ux_host_stack_transfer_request(transfer_request);
360 
361     /* Check status, if error, do not proceed.  */
362     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
363     {
364 
365         /* Free all used resources.  */
366         _ux_utility_memory_free(setup_buffer);
367 
368         /* Return completion status.  */
369         return(UX_TRANSFER_ERROR);
370 
371     }
372 
373     /* Perform a software reset.  Internal Phy reset Control and external Phy Reset Pin level. */
374     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
375     transfer_request -> ux_transfer_request_requested_length    =  0;
376     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_SW_RESET;
377     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
378     transfer_request -> ux_transfer_request_value               =  (UX_HOST_CLASS_ASIX_SW_RESET_IPRL | UX_HOST_CLASS_ASIX_SW_RESET_PRL);
379     transfer_request -> ux_transfer_request_index               =  0;
380 
381     /* Send request to HCD layer.  */
382     status =  _ux_host_stack_transfer_request(transfer_request);
383 
384     /* Check status, if error, do not proceed.  */
385     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
386     {
387 
388         /* Free all used resources.  */
389         _ux_utility_memory_free(setup_buffer);
390 
391         /* Return completion status.  */
392         return(UX_TRANSFER_ERROR);
393 
394     }
395 
396 
397     /* Write the value of the BMCR register in the PHY register.  */
398     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
399     transfer_request -> ux_transfer_request_requested_length    =  2;
400     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_WRITE_PHY_REG;
401     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
402     transfer_request -> ux_transfer_request_value               =  asix -> ux_host_class_asix_primary_phy_id;
403     transfer_request -> ux_transfer_request_index               =  UX_HOST_CLASS_ASIX_PHY_REG_BMCR;
404 
405     /* Set the value for the PHY reg. */
406     phy_register_value =  UX_HOST_CLASS_ASIX_PHY_REG_BMCR_RESET;
407 
408     /* Insert the value into the target buffer.  */
409     _ux_utility_short_put(setup_buffer, (USHORT)phy_register_value);
410 
411     /* Send request to HCD layer.  */
412     status =  _ux_host_stack_transfer_request(transfer_request);
413 
414     /* Check status, if error, do not proceed.  */
415     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS ||
416         transfer_request -> ux_transfer_request_actual_length != 2)
417     {
418 
419         /* Free all used resources.  */
420         _ux_utility_memory_free(setup_buffer);
421 
422         /* Return completion status.  */
423         return(UX_TRANSFER_ERROR);
424 
425     }
426 
427 
428     /* Read the value of the BMCR register in the PHY register.  */
429     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
430     transfer_request -> ux_transfer_request_requested_length    =  2;
431     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_READ_PHY_REG;
432     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
433     transfer_request -> ux_transfer_request_value               =  asix -> ux_host_class_asix_primary_phy_id;
434     transfer_request -> ux_transfer_request_index               =  UX_HOST_CLASS_ASIX_PHY_REG_BMCR;
435 
436     /* Send request to HCD layer.  */
437     status =  _ux_host_stack_transfer_request(transfer_request);
438 
439     /* Check status, if error, do not proceed.  */
440     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || transfer_request -> ux_transfer_request_actual_length != 2)
441     {
442 
443         /* Free all used resources.  */
444         _ux_utility_memory_free(setup_buffer);
445 
446         /* Return completion status.  */
447         return(UX_TRANSFER_ERROR);
448 
449     }
450 
451     /* Extract the speed selected by the PHY.  */
452     phy_register_value = _ux_utility_short_get(setup_buffer);
453 
454     /* Isolate the speed and memorize it.  */
455     if (phy_register_value & UX_HOST_CLASS_ASIX_PHY_REG_BMCR_SPEED_100MBS)
456 
457         /* Select 100 MBPS as our speed.  */
458         asix -> ux_host_class_asix_speed_selected = UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS;
459 
460     else
461 
462         /* Select 10 MBPS as our speed.  */
463         asix -> ux_host_class_asix_speed_selected = UX_HOST_CLASS_ASIX_SPEED_SELECTED_10MPBS;
464 
465     /* Set the value of the ANAR in the PHY register.  */
466     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
467     transfer_request -> ux_transfer_request_requested_length    =  2;
468     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_WRITE_PHY_REG;
469     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
470     transfer_request -> ux_transfer_request_value               =  asix -> ux_host_class_asix_primary_phy_id;
471     transfer_request -> ux_transfer_request_index               =  UX_HOST_CLASS_ASIX_PHY_REG_ANAR;
472 
473     /* Set the value for the PHY reg. */
474     phy_register_value =  (UX_HOST_CLASS_ASIX_PHY_REG_ANAR_DEFAULT_SELECTOR |
475                           UX_HOST_CLASS_ASIX_PHY_REG_ANAR_10_HD             |
476                           UX_HOST_CLASS_ASIX_PHY_REG_ANAR_10_FD             |
477                           UX_HOST_CLASS_ASIX_PHY_REG_ANAR_TX_HD             |
478                           UX_HOST_CLASS_ASIX_PHY_REG_ANAR_TX_FD             |
479                           UX_HOST_CLASS_ASIX_PHY_REG_ANAR_PAUSE);
480 
481     /* Insert the value into the target buffer.  */
482     _ux_utility_short_put(setup_buffer, (USHORT)phy_register_value);
483 
484 
485     /* Send request to HCD layer.  */
486     status =  _ux_host_stack_transfer_request(transfer_request);
487 
488     /* Check status, if error, do not proceed.  */
489     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS ||
490         transfer_request -> ux_transfer_request_actual_length != 2)
491     {
492 
493         /* Free all used resources.  */
494         _ux_utility_memory_free(setup_buffer);
495 
496         /* Return completion status.  */
497         return(UX_TRANSFER_ERROR);
498 
499     }
500 
501     /* Set the value of the BMCR in the PHY register.  */
502     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
503     transfer_request -> ux_transfer_request_requested_length    =  2;
504     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_WRITE_PHY_REG;
505     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
506     transfer_request -> ux_transfer_request_value               =  asix -> ux_host_class_asix_primary_phy_id;
507     transfer_request -> ux_transfer_request_index               =  UX_HOST_CLASS_ASIX_PHY_REG_BMCR;
508 
509     /* Check speed.  */
510     if (asix -> ux_host_class_asix_speed_selected == UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS)
511 
512         /* Set speed at 100MBPS.  */
513         phy_register_value =  UX_HOST_CLASS_ASIX_PHY_REG_BMCR_SPEED_100MBS;
514 
515     /* Set the value for the PHY reg. */
516     phy_register_value |=  (UX_HOST_CLASS_ASIX_PHY_REG_BMCR_AUTO_NEGOTIATION | UX_HOST_CLASS_ASIX_PHY_REG_BMCR_RESTART_NEG |
517                             UX_HOST_CLASS_ASIX_PHY_REG_BMCR_DUPLEX_MODE);
518 
519     /* Insert the value into the target buffer.  */
520     _ux_utility_short_put(setup_buffer, (USHORT)phy_register_value);
521 
522     /* Send request to HCD layer.  */
523     status =  _ux_host_stack_transfer_request(transfer_request);
524 
525     /* Check status, if error, do not proceed.  */
526     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS ||
527         transfer_request -> ux_transfer_request_actual_length != 2)
528     {
529 
530         /* Free all used resources.  */
531         _ux_utility_memory_free(setup_buffer);
532 
533         /* Return completion status.  */
534         return(UX_TRANSFER_ERROR);
535 
536     }
537 
538 
539     /* Check speed.  */
540     if (asix -> ux_host_class_asix_speed_selected == UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS)
541 
542         /* Set speed at 100MBPS.  */
543         transfer_request -> ux_transfer_request_value =  UX_HOST_CLASS_ASIX_MEDIUM_PS;
544 
545     /* Write the value of the Medium Mode. */
546     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
547     transfer_request -> ux_transfer_request_requested_length    =  0;
548     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_WRITE_MEDIUM_MODE;
549     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
550     transfer_request -> ux_transfer_request_value               |=  (UX_HOST_CLASS_ASIX_MEDIUM_FD | UX_HOST_CLASS_ASIX_MEDIUM_BIT2 | UX_HOST_CLASS_ASIX_MEDIUM_RFC_ENABLED |
551                                                                     UX_HOST_CLASS_ASIX_MEDIUM_TFC_ENABLED | UX_HOST_CLASS_ASIX_MEDIUM_RE_ENABLED);
552     transfer_request -> ux_transfer_request_index               =  0;
553 
554     /* Send request to HCD layer.  */
555     status =  _ux_host_stack_transfer_request(transfer_request);
556 
557     /* Check status, if error, do not proceed.  */
558     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
559     {
560 
561         /* Free all used resources.  */
562         _ux_utility_memory_free(setup_buffer);
563 
564         /* Return completion status.  */
565         return(UX_TRANSFER_ERROR);
566 
567     }
568 
569 
570     /* Write the value of the IPG0/IPG1/IPG2. */
571     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
572     transfer_request -> ux_transfer_request_requested_length    =  0;
573     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_WRITE_IPG012;
574     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
575     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_ASIX_PPG0_IPG1;
576     transfer_request -> ux_transfer_request_index               =  UX_HOST_CLASS_ASIX_PPG2;
577 
578     /* Send request to HCD layer.  */
579     status =  _ux_host_stack_transfer_request(transfer_request);
580 
581     /* Check status, if error, do not proceed.  */
582     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
583     {
584 
585         /* Free all used resources.  */
586         _ux_utility_memory_free(setup_buffer);
587 
588         /* Return completion status.  */
589         return(UX_TRANSFER_ERROR);
590 
591     }
592 
593     /* Release SMI ownership. */
594     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
595     transfer_request -> ux_transfer_request_requested_length    =  0;
596     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_RELEASE_SMI;
597     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
598     transfer_request -> ux_transfer_request_value               =  0;
599     transfer_request -> ux_transfer_request_index               =  0;
600 
601     /* Send request to HCD layer.  */
602     status =  _ux_host_stack_transfer_request(transfer_request);
603 
604     /* Check status, if error, do not proceed.  */
605     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
606     {
607 
608         /* Free all used resources.  */
609         _ux_utility_memory_free(setup_buffer);
610 
611         /* Return completion status.  */
612         return(UX_TRANSFER_ERROR);
613 
614     }
615 
616     /* Set the Rx Control register value.  */
617     transfer_request -> ux_transfer_request_data_pointer        =  UX_NULL;
618     transfer_request -> ux_transfer_request_requested_length    =  0;
619     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_ASIX_REQ_WRITE_RX_CTL;
620     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
621     transfer_request -> ux_transfer_request_value               =  (UX_HOST_CLASS_ASIX_RXCR_AB | UX_HOST_CLASS_ASIX_RXCR_SO | UX_HOST_CLASS_ASIX_RXCR_MFB_2048);
622     transfer_request -> ux_transfer_request_index               =  0;
623 
624     /* Send request to HCD layer.  */
625     status =  _ux_host_stack_transfer_request(transfer_request);
626 
627     /* Check status, if error, do not proceed.  */
628     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
629     {
630 
631         /* Free all used resources.  */
632         _ux_utility_memory_free(setup_buffer);
633 
634         /* Return completion status.  */
635         return(UX_TRANSFER_ERROR);
636 
637     }
638 
639     /* Free all used resources.  */
640     _ux_utility_memory_free(setup_buffer);
641 
642     /* Return completion status.  */
643     return(status);
644 }
645 
646