summaryrefslogtreecommitdiff
path: root/common/usbx_host_controllers/src/ux_hcd_ehci_periodic_descriptor_link.c
blob: 53a42f852ebca673817dc558c8caf3e50be3587b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/***************************************************************************
 * Copyright (c) 2024 Microsoft Corporation
 * Copyright (c) 2026-present Eclipse ThreadX contributors
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * SPDX-License-Identifier: MIT
 **************************************************************************/


/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** USBX Component                                                        */
/**                                                                       */
/**   EHCI Controller Driver                                              */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/


/* Include necessary system files.  */

#define UX_SOURCE_CODE

#include "ux_api.h"
#include "ux_hcd_ehci.h"
#include "ux_host_stack.h"

/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _ux_hcd_ehci_periodic_descriptor_link               PORTABLE C      */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Chaoqiong Xiao, Microsoft Corporation                               */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function link/unlink the iTD/siTD/QH descriptor in periodic    */
/*    lists for Host Controller (HC) to scan for transfers in the         */
/*    (micro-)frames.                                                     */
/*                                                                        */
/*    If link_desc is not NULL:                                           */
/*      prev_desc -> physical_next = link_lp                              */
/*      link_desc -> physical_next = next_desc                            */
/*      next_desc -> virtual_previous = link_desc                         */
/*    Resulting sequence prev - link_lp ... link_desc - next_desc.        */
/*                                                                        */
/*    If link_desc is not NULL:                                           */
/*      prev_desc -> physical_next = link_lp                              */
/*      next_desc -> virtual_previous = link_desc                         */
/*    Resulting unlink of things between prev_desc and next_desc.         */
/*                                                                        */
/*    Note previous LP for linking item is not updated by this function.  */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    prev                                  Link Pointer to previous item */
/*                                          (virtual memory address)      */
/*    prev_next                             Physical link pointer data    */
/*                                          including address, Typ and T. */
/*                                          If it's NULL the item between */
/*                                          previous and next is unlinked */
/*    next_prev                             Link Pointer to item to link  */
/*                                          (virtual memory address)      */
/*    next                                  Link pointer to next item     */
/*                                          (physical address, Typ & T)   */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    EHCI Controller Driver                                              */
/*                                                                        */
/**************************************************************************/
void _ux_hcd_ehci_periodic_descriptor_link(
    VOID* prev,
    VOID* prev_next,      /* for prev -> next_lp.  */
    VOID* next_prev,      /* for next -> prev_lp (virtual).   */
    VOID* next_desc)
{

UX_EHCI_PERIODIC_LINK_POINTER     virtual_lp;
UX_EHCI_PERIODIC_LINK_POINTER     prev_virtual_lp;
UX_EHCI_PERIODIC_LINK_POINTER     link_virtual_lp;
UX_EHCI_PERIODIC_LINK_POINTER     link_physical_lp;
UX_EHCI_PERIODIC_LINK_POINTER     next_physical_lp;


    /* Pointers.  */
    prev_virtual_lp.void_ptr = prev;
    link_physical_lp.void_ptr = prev_next;
    link_virtual_lp.void_ptr = next_prev;
    next_physical_lp.void_ptr = next_desc;

    /* Check link/unlink.  */
    if (prev_next && next_prev)
    {

        /* Link, fill next LP for linked item first.  */
        link_virtual_lp.itd_ptr -> ux_ehci_hsiso_td_next_lp = next_physical_lp;
    }
    else
    {

        /* Unlink, use info from previous and next item.  */
        link_virtual_lp = prev_virtual_lp;
        link_physical_lp = next_physical_lp;
    }

    /* Update LP of previous item for HC to access.  */
    prev_virtual_lp.itd_ptr -> ux_ehci_hsiso_td_next_lp = link_physical_lp;

    /* If next item is valid, update its previous LP.  */
    if ((next_physical_lp.value & (UX_EHCI_LINK_ADDRESS_MASK | UX_EHCI_T)) != UX_EHCI_T)
    {

        /* Get virtual address of next item.  */
        virtual_lp.value = next_physical_lp.value & UX_EHCI_LINK_ADDRESS_MASK;
        virtual_lp.void_ptr = _ux_utility_virtual_address(virtual_lp.void_ptr);

        /* Update previous LP, except static anchor.  */
        switch(next_physical_lp.value & UX_EHCI_TYP_MASK)
        {
        case UX_EHCI_TYP_ITD:
            virtual_lp.itd_ptr -> ux_ehci_hsiso_td_previous_lp = link_virtual_lp;
            break;
#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE)
        case UX_EHCI_TYP_SITD:
            virtual_lp.sitd_ptr -> ux_ehci_fsiso_td_previous_lp = link_virtual_lp;
            break;
#endif
        default: /* QH.  */
            if ((virtual_lp.ed_ptr -> ux_ehci_ed_status & UX_EHCI_QH_STATIC) == 0)
                virtual_lp.ed_ptr -> ux_ehci_ed_previous_ed = link_virtual_lp.ed_ptr;
            break;
        }
    }
}

/*
anchor, next + head, tail ==> anchor, head ... tail, next
    head -> prev = anchor  (Vir)
    anchor -> next = head  (Phy)
    tail -> next = next    (Phy)
    next -> prev = tail    (Vir)

anchor, head ... tail, next ==> anchor, next
    anchor -> next = next   (Phy)
    next -> prev = anchor   (Vir)

*/