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 /**   EHCI Controller Driver                                              */
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_hcd_ehci.h"
30 #include "ux_host_stack.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_hcd_ehci_asynchronous_endpoint_create           PORTABLE C      */
38 /*                                                           6.1.2        */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function will create an asynchronous endpoint. The control     */
46 /*    and bulk endpoints fall into this category.                         */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    hcd_ehci                              Pointer to EHCI controller    */
51 /*    endpoint                              Pointer to endpoint           */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    Completion Status                                                   */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _ux_hcd_ehci_ed_obtain                Obtain EHCI ED                */
60 /*    _ux_utility_physical_address          Get physical address          */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    EHCI Controller Driver                                              */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
71 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
72 /*                                            optimized based on compile  */
73 /*                                            definitions,                */
74 /*                                            resulting in version 6.1    */
75 /*  11-09-2020     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            fixed compile warnings,     */
77 /*                                            resulting in version 6.1.2  */
78 /*                                                                        */
79 /**************************************************************************/
_ux_hcd_ehci_asynchronous_endpoint_create(UX_HCD_EHCI * hcd_ehci,UX_ENDPOINT * endpoint)80 UINT  _ux_hcd_ehci_asynchronous_endpoint_create(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint)
81 {
82 
83 UX_DEVICE               *device;
84 UX_EHCI_ED              *ed;
85 UX_EHCI_LINK_POINTER    queue_head;
86 
87 
88     /* We need to take into account the nature of the HCD to define the max size
89        of any transfer in the transfer request.  */
90     endpoint -> ux_endpoint_transfer_request.ux_transfer_request_maximum_length =  UX_EHCI_MAX_PAYLOAD;
91 
92     /* Obtain a ED for this new endpoint. This ED will live as long as the endpoint is active
93        and will be the container for the tds.  */
94     ed =  _ux_hcd_ehci_ed_obtain(hcd_ehci);
95     if (ed == UX_NULL)
96         return(UX_NO_ED_AVAILABLE);
97 
98     /* Attach the ED to the endpoint container.  */
99     endpoint -> ux_endpoint_ed =  (VOID *) ed;
100 
101     /* Now do the opposite, attach the ED container to the physical ED.  */
102     ed -> REF_AS.INTR.ux_ehci_ed_endpoint =  endpoint;
103 
104     /* Set the default MPS Capability info in the ED.  */
105     ed -> ux_ehci_ed_cap0 =  endpoint -> ux_endpoint_descriptor.wMaxPacketSize << UX_EHCI_QH_MPS_LOC;
106 
107     /* Set the default NAK reload count.  */
108     ed -> ux_ehci_ed_cap0 |=  UX_EHCI_QH_NCR;
109 
110     /* If the device is not high speed and the endpoint is control, then the CEF bit must be set to on.  */
111     device =  endpoint -> ux_endpoint_device;
112     if ((device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) &&
113         ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_CONTROL_ENDPOINT))
114         ed -> ux_ehci_ed_cap0 |=  UX_EHCI_QH_CEF;
115 
116     /* Set the device address.  */
117     ed -> ux_ehci_ed_cap0 |=  device -> ux_device_address;
118 
119     /* Add the endpoint address.  */
120     ed -> ux_ehci_ed_cap0 |=  (endpoint -> ux_endpoint_descriptor.bEndpointAddress &
121                                             ~UX_ENDPOINT_DIRECTION) << UX_EHCI_QH_ED_AD_LOC;
122 
123     /* Set the High Bandwidth Pipe Multiplier to 1.  */
124     ed -> ux_ehci_ed_cap1 |=  UX_EHCI_QH_HBPM;
125 
126     /* Set the device speed for full and low speed devices behind a hub the hub address and the
127        port index must be stored in the endpoint.  */
128     switch (device -> ux_device_speed)
129     {
130 
131     case  UX_HIGH_SPEED_DEVICE:
132 
133         ed -> ux_ehci_ed_cap0 |=  UX_EHCI_QH_HIGH_SPEED;
134         break;
135 
136 
137     case  UX_LOW_SPEED_DEVICE:
138 
139         ed -> ux_ehci_ed_cap0 |=  UX_EHCI_QH_LOW_SPEED;
140         break;
141 
142     case  UX_FULL_SPEED_DEVICE:
143 
144 #if UX_MAX_DEVICES > 1
145         /* The device must be on a hub for this code to execute. We still do a sanity check.  */
146         if (device -> ux_device_parent != UX_NULL)
147         {
148 
149             /* Store the parent hub device address.  */
150             ed -> ux_ehci_ed_cap1 |=  device -> ux_device_parent -> ux_device_address << UX_EHCI_QH_HUB_ADDR_LOC;
151 
152             /* And the port index onto which this device is attached.  */
153             ed -> ux_ehci_ed_cap1 |=  device -> ux_device_port_location << UX_EHCI_QH_PORT_NUMBER_LOC;
154         }
155 #endif
156         break;
157     }
158 
159     /* We need to insert this new endpoint into the asynchronous list. All new EDs are inserted at the
160        end of the list. The current ED will be pointing to the first ED in the list.  */
161     queue_head.void_ptr = _ux_utility_physical_address(hcd_ehci -> ux_hcd_ehci_asynch_first_list);
162     queue_head.value |= UX_EHCI_QH_TYP_QH;
163     ed -> ux_ehci_ed_queue_head =  queue_head.ed_ptr;
164     ed -> ux_ehci_ed_next_ed =     hcd_ehci -> ux_hcd_ehci_asynch_first_list;
165 
166     /* Now we compute the address and the data type to fill the QH pointer with.  */
167     queue_head.void_ptr = _ux_utility_physical_address(ed);
168     queue_head.value |= UX_EHCI_QH_TYP_QH;
169     hcd_ehci -> ux_hcd_ehci_asynch_last_list -> ux_ehci_ed_queue_head = queue_head.ed_ptr;
170     ed -> ux_ehci_ed_previous_ed =  hcd_ehci -> ux_hcd_ehci_asynch_last_list;
171 
172     /* Update the link of the previous ED.  */
173     ed -> ux_ehci_ed_previous_ed -> ux_ehci_ed_next_ed =  ed;
174 
175     /* Remember the new last QH.  */
176     hcd_ehci -> ux_hcd_ehci_asynch_last_list =  ed;
177 
178     /* Return successful completion.  */
179     return(UX_SUCCESS);
180 }
181 
182