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 /**   OHCI 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_ohci.h"
30 #include "ux_host_stack.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_hcd_ohci_asynchronous_endpoint_create           PORTABLE C      */
38 /*                                                           6.1.12       */
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_ohci                              Pointer to OHCI HCD           */
51 /*    endpoint                              Pointer to endpoint           */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    Completion Status                                                   */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _ux_hcd_ohci_ed_obtain                Obtain a new ED               */
60 /*    _ux_hcd_ohci_register_read            Read OHCI register            */
61 /*    _ux_hcd_ohci_register_write           Write OHCI register           */
62 /*    _ux_utility_physical_address          Get physical address          */
63 /*                                                                        */
64 /*  CALLED BY                                                             */
65 /*                                                                        */
66 /*    OHCI Controller Driver                                              */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
73 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            fixed an addressing issue,  */
77 /*                                            resulting in version 6.1.11 */
78 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
79 /*                                            fixed addressing issues,    */
80 /*                                            resulting in version 6.1.12 */
81 /*                                                                        */
82 /**************************************************************************/
_ux_hcd_ohci_asynchronous_endpoint_create(UX_HCD_OHCI * hcd_ohci,UX_ENDPOINT * endpoint)83 UINT  _ux_hcd_ohci_asynchronous_endpoint_create(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint)
84 {
85 
86 UX_DEVICE       *device;
87 UX_OHCI_ED      *ed;
88 UX_OHCI_ED      *head_ed;
89 UX_OHCI_TD      *td;
90 ULONG           ohci_register;
91 
92 
93     /* We need to take into account the nature of the HCD to define the max size
94        of any transfer in the transfer request.  */
95     endpoint -> ux_endpoint_transfer_request.ux_transfer_request_maximum_length =  UX_OHCI_MAX_PAYLOAD;
96 
97     /* Obtain a ED for this new endpoint. This ED will live as long as the endpoint is active and
98        will be the container for the TDs.  */
99     ed =  _ux_hcd_ohci_ed_obtain(hcd_ohci);
100     if (ed == UX_NULL)
101         return(UX_NO_ED_AVAILABLE);
102 
103     /* Obtain a dummy TD for terminating the ED transfer chain.  */
104     td =  _ux_hcd_ohci_regular_td_obtain(hcd_ohci);
105     if (td == UX_NULL)
106     {
107 
108         ed -> ux_ohci_ed_status =  UX_UNUSED;
109         return(UX_NO_TD_AVAILABLE);
110     }
111 
112     /* Attach the ED to the endpoint container.  */
113     endpoint -> ux_endpoint_ed =  (VOID *) ed;
114 
115     /* Now do the opposite, attach the ED container to the physical ED.  */
116     ed -> ux_ohci_ed_endpoint =  endpoint;
117 
118     /* Program the ED for subsequent transfers. We need to set the following things:
119         1) Address of the device
120         2) endpoint number
121         3) speed
122         4) format of TD
123         5) maximum packet size */
124     device =  endpoint -> ux_endpoint_device;
125     ed -> ux_ohci_ed_dw0 =  device -> ux_device_address |
126                             ((ULONG) (endpoint -> ux_endpoint_descriptor.bEndpointAddress & ~UX_ENDPOINT_DIRECTION)) << 7 |
127                             ((ULONG) endpoint -> ux_endpoint_descriptor.wMaxPacketSize) << 16;
128 
129     if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE)
130         ed -> ux_ohci_ed_dw0 |=  UX_OHCI_ED_LOW_SPEED;
131 
132     /* Hook the TD to both the tail and head of the ED.  */
133     ed -> ux_ohci_ed_tail_td =  _ux_utility_physical_address(td);
134     ed -> ux_ohci_ed_head_td =  _ux_utility_physical_address(td);
135 
136     /* We now need to get the type of transfer (control or bulk) to hook this ED to the appropriate list.
137        We also enable the appropriate list.  */
138     switch ((endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE)
139     {
140 
141     case UX_CONTROL_ENDPOINT:
142 
143         head_ed =  (UX_OHCI_ED *) _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_CONTROL_HEAD_ED);
144         ed -> ux_ohci_ed_next_ed =  head_ed;
145         _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL_HEAD_ED, (ULONG) _ux_utility_physical_address(ed));
146         ohci_register =  _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_CONTROL);
147         ohci_register |=  OHCI_HC_CR_CLE;
148         _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL, ohci_register);
149         break;
150 
151 
152     case UX_BULK_ENDPOINT:
153 
154         head_ed =  (UX_OHCI_ED *) _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_BULK_HEAD_ED);
155         ed -> ux_ohci_ed_next_ed =  head_ed;
156         _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_BULK_HEAD_ED, (ULONG) _ux_utility_physical_address(ed));
157         ohci_register =  _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_CONTROL);
158         ohci_register |=  OHCI_HC_CR_BLE;
159         _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL, ohci_register);
160         break;
161 
162     default:
163 
164         head_ed =  UX_NULL;
165     }
166 
167     /* Build the back chaining pointer. The previous head ED needs to know about the
168        inserted ED. */
169     if (head_ed != UX_NULL)
170     {
171         head_ed = _ux_utility_virtual_address(head_ed);
172         head_ed -> ux_ohci_ed_previous_ed =  ed;
173     }
174 
175     /* Return successful completion.  */
176     return(UX_SUCCESS);
177 }
178 
179