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_request_transfer_add                   PORTABLE C      */
38 /*                                                           6.1          */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*     This function adds a component of a transfer to an existing ED.    */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    hcd_ehci                              Pointer to EHCI controller    */
50 /*    ed                                    Pointer to the ED             */
51 /*    phase                                 Phase (for control transfers) */
52 /*    pid                                   PID to be used with this      */
53 /*                                            request (SETUP,IN,OUT)      */
54 /*    toggle                                Toggle value 0 or 1           */
55 /*    buffer_address                        Buffer address for transfer   */
56 /*    buffer_length                         Buffer length                 */
57 /*    transfer_request                      Pointer to transfer request   */
58 /*                                                                        */
59 /*  OUTPUT                                                                */
60 /*                                                                        */
61 /*    Completion Status                                                   */
62 /*                                                                        */
63 /*  CALLS                                                                 */
64 /*                                                                        */
65 /*    _ux_hcd_ehci_regular_td_obtain        Obtain regular TD             */
66 /*    _ux_utility_physical_address          Get physical address          */
67 /*                                                                        */
68 /*  CALLED BY                                                             */
69 /*                                                                        */
70 /*    EHCI Controller Driver                                              */
71 /*                                                                        */
72 /*  RELEASE HISTORY                                                       */
73 /*                                                                        */
74 /*    DATE              NAME                      DESCRIPTION             */
75 /*                                                                        */
76 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
77 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
78 /*                                            resulting in version 6.1    */
79 /*                                                                        */
80 /**************************************************************************/
_ux_hcd_ehci_request_transfer_add(UX_HCD_EHCI * hcd_ehci,UX_EHCI_ED * ed,ULONG phase,ULONG pid,ULONG toggle,UCHAR * buffer_address,ULONG buffer_length,UX_TRANSFER * transfer_request)81 UINT  _ux_hcd_ehci_request_transfer_add(UX_HCD_EHCI *hcd_ehci, UX_EHCI_ED *ed, ULONG phase, ULONG pid,
82                                     ULONG toggle, UCHAR * buffer_address, ULONG buffer_length, UX_TRANSFER *transfer_request)
83 {
84 
85 UX_EHCI_TD              *last_td;
86 UX_EHCI_TD              *td;
87 UX_EHCI_LINK_POINTER    lp;
88 UX_EHCI_POINTER         bp;
89 
90 
91     /* Obtain a TD for this transaction.  */
92     td =  _ux_hcd_ehci_regular_td_obtain(hcd_ehci);
93     if (td == UX_NULL)
94         return(UX_NO_TD_AVAILABLE);
95 
96     /* Store the transfer request associated with this TD.  */
97     td -> ux_ehci_td_transfer_request =  transfer_request;
98 
99     /* Store the ED associated with this TD.  */
100     td -> ux_ehci_td_ed =  ed;
101 
102     /* Mark the TD with the phase.  */
103     td -> ux_ehci_td_phase |=  phase;
104 
105     /* Set the PID in the control DWORD of the TD.  */
106     td -> ux_ehci_td_control =  pid;
107 
108     /* Set the buffer address if there is a data payload.  */
109     bp.void_ptr = _ux_utility_physical_address(buffer_address);
110     td -> ux_ehci_td_bp0 = bp.void_ptr; /* with offset.  */
111 
112     /* Fill in the next pages addresses if required.  */
113     bp.value &=  UX_EHCI_PAGE_ALIGN;
114     td -> ux_ehci_td_bp1 =  bp.u8_ptr + UX_EHCI_PAGE_SIZE;
115     td -> ux_ehci_td_bp2 =  bp.u8_ptr + UX_EHCI_PAGE_SIZE * 2;
116     td -> ux_ehci_td_bp3 =  bp.u8_ptr + UX_EHCI_PAGE_SIZE * 3;
117     td -> ux_ehci_td_bp4 =  bp.u8_ptr + UX_EHCI_PAGE_SIZE * 4;
118 
119     /* Set the length of the data transfer. We keep its original value.  */
120     td -> ux_ehci_td_control |=  buffer_length << UX_EHCI_TD_LG_LOC;
121     td -> ux_ehci_td_length =    buffer_length;
122 
123     /* Add the completion trigger, the default error count, the active bit.  */
124     td -> ux_ehci_td_control |=  UX_EHCI_TD_CERR | UX_EHCI_TD_ACTIVE;
125 
126     /* Add the toggle value. This value is only used for control transfers.  */
127     td -> ux_ehci_td_control |=  toggle;
128 
129     /* Recall the last TD hooked to the ED. If the value is NULL, this will be the
130        first TD and should be hooked to the ED itself..  */
131     last_td =  ed -> ux_ehci_ed_last_td;
132 
133     /* Do we hook this TD to the ED?  */
134     if (last_td == UX_NULL)
135     {
136 
137         /* The TD is hooked to the ED. We set the T bit so that the controller will
138            not transfer this TD on hook up but when all the TDs have been hooked.
139            We memorize this TD as the first TD as well.  */
140         ed -> ux_ehci_ed_first_td =  td;
141         lp.void_ptr = _ux_utility_physical_address(td);
142         lp.value |= UX_EHCI_TD_T;
143         ed -> ux_ehci_ed_queue_element = lp.td_ptr;
144     }
145     else
146     {
147 
148         /* The TD is hooked to the end of the linked TDs.  */
149         last_td -> ux_ehci_td_link_pointer =  _ux_utility_physical_address(td);
150     }
151 
152     /* Memorize the last TD hooked.  */
153     ed -> ux_ehci_ed_last_td =  td;
154 
155     /* Return successful completion.  */
156     return(UX_SUCCESS);
157 }
158 
159