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 /** EHCI Controller Driver */
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_hcd_ehci.h"
29 #include "ux_host_stack.h"
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_hcd_ehci_periodic_descriptor_link PORTABLE C */
36 /* 6.1 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function link/unlink the iTD/siTD/QH descriptor in periodic */
44 /* lists for Host Controller (HC) to scan for transfers in the */
45 /* (micro-)frames. */
46 /* */
47 /* If link_desc is not NULL: */
48 /* prev_desc -> physical_next = link_lp */
49 /* link_desc -> physical_next = next_desc */
50 /* next_desc -> virtual_previous = link_desc */
51 /* Resulting sequence prev - link_lp ... link_desc - next_desc. */
52 /* */
53 /* If link_desc is not NULL: */
54 /* prev_desc -> physical_next = link_lp */
55 /* next_desc -> virtual_previous = link_desc */
56 /* Resulting unlink of things between prev_desc and next_desc. */
57 /* */
58 /* Note previous LP for linking item is not updated by this function. */
59 /* */
60 /* INPUT */
61 /* */
62 /* prev Link Pointer to previous item */
63 /* (virtual memory address) */
64 /* prev_next Physical link pointer data */
65 /* including address, Typ and T. */
66 /* If it's NULL the item between */
67 /* previous and next is unlinked */
68 /* next_prev Link Pointer to item to link */
69 /* (virtual memory address) */
70 /* next Link pointer to next item */
71 /* (physical address, Typ & T) */
72 /* */
73 /* OUTPUT */
74 /* */
75 /* */
76 /* CALLS */
77 /* */
78 /* */
79 /* CALLED BY */
80 /* */
81 /* EHCI Controller Driver */
82 /* */
83 /* RELEASE HISTORY */
84 /* */
85 /* DATE NAME DESCRIPTION */
86 /* */
87 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
88 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
89 /* resulting in version 6.1 */
90 /* */
91 /**************************************************************************/
_ux_hcd_ehci_periodic_descriptor_link(VOID * prev,VOID * prev_next,VOID * next_prev,VOID * next_desc)92 void _ux_hcd_ehci_periodic_descriptor_link(
93 VOID* prev,
94 VOID* prev_next, /* for prev -> next_lp. */
95 VOID* next_prev, /* for next -> prev_lp (virtual). */
96 VOID* next_desc)
97 {
98
99 UX_EHCI_PERIODIC_LINK_POINTER virtual_lp;
100 UX_EHCI_PERIODIC_LINK_POINTER prev_virtual_lp;
101 UX_EHCI_PERIODIC_LINK_POINTER link_virtual_lp;
102 UX_EHCI_PERIODIC_LINK_POINTER link_physical_lp;
103 UX_EHCI_PERIODIC_LINK_POINTER next_physical_lp;
104
105
106 /* Pointers. */
107 prev_virtual_lp.void_ptr = prev;
108 link_physical_lp.void_ptr = prev_next;
109 link_virtual_lp.void_ptr = next_prev;
110 next_physical_lp.void_ptr = next_desc;
111
112 /* Check link/unlink. */
113 if (prev_next && next_prev)
114 {
115
116 /* Link, fill next LP for linked item first. */
117 link_virtual_lp.itd_ptr -> ux_ehci_hsiso_td_next_lp = next_physical_lp;
118 }
119 else
120 {
121
122 /* Unlink, use info from previous and next item. */
123 link_virtual_lp = prev_virtual_lp;
124 link_physical_lp = next_physical_lp;
125 }
126
127 /* Update LP of previous item for HC to access. */
128 prev_virtual_lp.itd_ptr -> ux_ehci_hsiso_td_next_lp = link_physical_lp;
129
130 /* If next item is valid, update its previous LP. */
131 if ((next_physical_lp.value & (UX_EHCI_LINK_ADDRESS_MASK | UX_EHCI_T)) != UX_EHCI_T)
132 {
133
134 /* Get virtual address of next item. */
135 virtual_lp.value = next_physical_lp.value & UX_EHCI_LINK_ADDRESS_MASK;
136 virtual_lp.void_ptr = _ux_utility_virtual_address(virtual_lp.void_ptr);
137
138 /* Update previous LP, except static anchor. */
139 switch(next_physical_lp.value & UX_EHCI_TYP_MASK)
140 {
141 case UX_EHCI_TYP_ITD:
142 virtual_lp.itd_ptr -> ux_ehci_hsiso_td_previous_lp = link_virtual_lp;
143 break;
144 #if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE)
145 case UX_EHCI_TYP_SITD:
146 virtual_lp.sitd_ptr -> ux_ehci_fsiso_td_previous_lp = link_virtual_lp;
147 break;
148 #endif
149 default: /* QH. */
150 if ((virtual_lp.ed_ptr -> ux_ehci_ed_status & UX_EHCI_QH_STATIC) == 0)
151 virtual_lp.ed_ptr -> ux_ehci_ed_previous_ed = link_virtual_lp.ed_ptr;
152 break;
153 }
154 }
155 }
156
157 /*
158 anchor, next + head, tail ==> anchor, head ... tail, next
159 head -> prev = anchor (Vir)
160 anchor -> next = head (Phy)
161 tail -> next = next (Phy)
162 next -> prev = tail (Vir)
163
164 anchor, head ... tail, next ==> anchor, next
165 anchor -> next = next (Phy)
166 next -> prev = anchor (Vir)
167
168 */
169