summaryrefslogtreecommitdiff
path: root/common/usbx_host_controllers/src/ux_hcd_ehci_request_transfer_add.c
blob: 978f84f4588b274e2b167b7d9e7e5c59a2856983 (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
/***************************************************************************
 * 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_request_transfer_add                   PORTABLE C      */
/*                                                           6.1          */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Chaoqiong Xiao, Microsoft Corporation                               */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*     This function adds a component of a transfer to an existing ED.    */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    hcd_ehci                              Pointer to EHCI controller    */
/*    ed                                    Pointer to the ED             */
/*    phase                                 Phase (for control transfers) */
/*    pid                                   PID to be used with this      */
/*                                            request (SETUP,IN,OUT)      */
/*    toggle                                Toggle value 0 or 1           */
/*    buffer_address                        Buffer address for transfer   */
/*    buffer_length                         Buffer length                 */
/*    transfer_request                      Pointer to transfer request   */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    Completion Status                                                   */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _ux_hcd_ehci_regular_td_obtain        Obtain regular TD             */
/*    _ux_utility_physical_address          Get physical address          */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    EHCI Controller Driver                                              */
/*                                                                        */
/**************************************************************************/
UINT  _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)
{

UX_EHCI_TD              *last_td;
UX_EHCI_TD              *td;
UX_EHCI_LINK_POINTER    lp;
UX_EHCI_POINTER         bp;


    /* Obtain a TD for this transaction.  */
    td =  _ux_hcd_ehci_regular_td_obtain(hcd_ehci);
    if (td == UX_NULL)
        return(UX_NO_TD_AVAILABLE);

    /* Store the transfer request associated with this TD.  */
    td -> ux_ehci_td_transfer_request =  transfer_request;

    /* Store the ED associated with this TD.  */
    td -> ux_ehci_td_ed =  ed;

    /* Mark the TD with the phase.  */
    td -> ux_ehci_td_phase |=  phase;

    /* Set the PID in the control DWORD of the TD.  */
    td -> ux_ehci_td_control =  pid;

    /* Set the buffer address if there is a data payload.  */
    bp.void_ptr = _ux_utility_physical_address(buffer_address);
    td -> ux_ehci_td_bp0 = bp.void_ptr; /* with offset.  */

    /* Fill in the next pages addresses if required.  */
    bp.value &=  UX_EHCI_PAGE_ALIGN;
    td -> ux_ehci_td_bp1 =  bp.u8_ptr + UX_EHCI_PAGE_SIZE;
    td -> ux_ehci_td_bp2 =  bp.u8_ptr + UX_EHCI_PAGE_SIZE * 2;
    td -> ux_ehci_td_bp3 =  bp.u8_ptr + UX_EHCI_PAGE_SIZE * 3;
    td -> ux_ehci_td_bp4 =  bp.u8_ptr + UX_EHCI_PAGE_SIZE * 4;

    /* Set the length of the data transfer. We keep its original value.  */
    td -> ux_ehci_td_control |=  buffer_length << UX_EHCI_TD_LG_LOC;
    td -> ux_ehci_td_length =    buffer_length;

    /* Add the completion trigger, the default error count, the active bit.  */
    td -> ux_ehci_td_control |=  UX_EHCI_TD_CERR | UX_EHCI_TD_ACTIVE;

    /* Add the toggle value. This value is only used for control transfers.  */
    td -> ux_ehci_td_control |=  toggle;

    /* Recall the last TD hooked to the ED. If the value is NULL, this will be the
       first TD and should be hooked to the ED itself..  */
    last_td =  ed -> ux_ehci_ed_last_td;

    /* Do we hook this TD to the ED?  */
    if (last_td == UX_NULL)
    {

        /* The TD is hooked to the ED. We set the T bit so that the controller will
           not transfer this TD on hook up but when all the TDs have been hooked.
           We memorize this TD as the first TD as well.  */
        ed -> ux_ehci_ed_first_td =  td;
        lp.void_ptr = _ux_utility_physical_address(td);
        lp.value |= UX_EHCI_TD_T;
        ed -> ux_ehci_ed_queue_element = lp.td_ptr;
    }
    else
    {

        /* The TD is hooked to the end of the linked TDs.  */
        last_td -> ux_ehci_td_link_pointer =  _ux_utility_physical_address(td);
    }

    /* Memorize the last TD hooked.  */
    ed -> ux_ehci_ed_last_td =  td;

    /* Return successful completion.  */
    return(UX_SUCCESS);
}