summaryrefslogtreecommitdiff
path: root/common/usbx_host_controllers/src/ux_hcd_ehci_done_queue_process.c
blob: 8f9cdc60076aece05b447a03fd88baa299467a39 (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_done_queue_process                     PORTABLE C      */
/*                                                           6.1.11       */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Chaoqiong Xiao, Microsoft Corporation                               */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function process the isochronous, periodic and asynchronous    */
/*    lists in search for transfers that occurred in the past             */
/*    (micro-)frame.                                                      */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    hcd_ehci                              Pointer to EHCI controller    */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    None                                                                */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _ux_hcd_ehci_asynch_td_process        Process asynch TD             */
/*    _ux_hcd_ehci_hsisochronous_tds_process                              */
/*                                          Process high speed            */
/*                                          isochronous TDs               */
/*    _ux_hcd_ehci_fsisochronous_tds_process                              */
/*                                          Process full speed (split)    */
/*                                          isochronous TDs               */
/*    _ux_utility_virtual_address           Get virtual address           */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    EHCI Controller Driver                                              */
/*                                                                        */
/**************************************************************************/
VOID  _ux_hcd_ehci_done_queue_process(UX_HCD_EHCI *hcd_ehci)
{

UX_EHCI_TD                      *td;
UX_EHCI_PERIODIC_LINK_POINTER   ed;
UX_EHCI_ED                      *start_ed;


#if UX_MAX_ISO_TD
UX_EHCI_PERIODIC_LINK_POINTER   lp;

    /* We scan the active isochronous list first.  */
    _ux_host_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
    lp.itd_ptr = hcd_ehci -> ux_hcd_ehci_hsiso_scan_list;
    while(lp.itd_ptr != UX_NULL)
    {

        /* Process the iTD, return next active TD.  */
        lp.itd_ptr = _ux_hcd_ehci_hsisochronous_tds_process(hcd_ehci, lp.itd_ptr);
    }
    _ux_host_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);

#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE)

    /* We scan the split isochronous list then.  */
    _ux_host_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
    lp.sitd_ptr = hcd_ehci -> ux_hcd_ehci_fsiso_scan_list;
    while(lp.sitd_ptr != UX_NULL)
    {

        /* Process the iTD, return next active TD.  */
        lp.sitd_ptr = _ux_hcd_ehci_fsisochronous_tds_process(hcd_ehci, lp.sitd_ptr);
    }
    _ux_host_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);

#endif
#endif

    /* We scan the linked interrupt list then.  */
    _ux_host_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);
    ed.ed_ptr = hcd_ehci -> ux_hcd_ehci_interrupt_ed_list;
    while(ed.ed_ptr != UX_NULL)
    {

        /* Retrieve the fist TD attached to this ED.  */
        td =  ed.ed_ptr -> ux_ehci_ed_first_td;

        /* Process TD until there is no next available.  */
        while (td != UX_NULL)
            td =  _ux_hcd_ehci_asynch_td_process(ed.ed_ptr, td);

        /* Next ED.  */
        ed.ed_ptr = ed.ed_ptr -> ux_ehci_ed_next_ed;
    }
    _ux_host_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex);

    /* Now we can parse the asynchronous list. The head ED is always empty and
       used as an anchor only.  */
    start_ed =  hcd_ehci -> ux_hcd_ehci_asynch_head_list;

    /* Point to the next ED in the asynchronous tree.  */
    ed.ed_ptr = start_ed -> ux_ehci_ed_queue_head;
    ed.value &= UX_EHCI_LINK_ADDRESS_MASK;

    /* Obtain the virtual address from the element.  */
    ed.void_ptr = _ux_utility_virtual_address(ed.void_ptr);

    /* Now traverse this list until we have found a non anchor endpoint that
       has transfers done.  */
    while (ed.ed_ptr != start_ed)
    {

        /* Retrieve the fist TD attached to this ED.  */
        td =  ed.ed_ptr -> ux_ehci_ed_first_td;
        while (td != UX_NULL)
        {

            td =  _ux_hcd_ehci_asynch_td_process(ed.ed_ptr, td);
        }

        /* Point to the next ED in the asynchronous tree.  */
        ed.ed_ptr = ed.ed_ptr -> ux_ehci_ed_queue_head;
        ed.value &= UX_EHCI_LINK_ADDRESS_MASK;

        /* Obtain the virtual address from the element.  */
        ed.void_ptr = _ux_utility_virtual_address(ed.void_ptr);
    }
}