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