3 * Copyright (C) 2013 secunet Security Networks AG
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <arch/virtual.h>
31 #include "xhci_private.h"
34 xhci_next_command_trb(xhci_t
*const xhci
)
36 xhci_clear_trb(xhci
->cr
.cur
, xhci
->cr
.pcs
);
41 xhci_post_command(xhci_t
*const xhci
)
43 xhci_debug("Command %d (@%p)\n",
44 TRB_GET(TT
, xhci
->cr
.cur
), xhci
->cr
.cur
);
46 TRB_SET(C
, xhci
->cr
.cur
, xhci
->cr
.pcs
);
49 /* pass command trb to hardware */
51 /* Ring the doorbell */
54 while (TRB_GET(TT
, xhci
->cr
.cur
) == TRB_LINK
) {
55 xhci_debug("Handling LINK pointer (@%p)\n", xhci
->cr
.cur
);
56 const int tc
= TRB_GET(TC
, xhci
->cr
.cur
);
57 TRB_SET(C
, xhci
->cr
.cur
, xhci
->cr
.pcs
);
58 xhci
->cr
.cur
= phys_to_virt(xhci
->cr
.cur
->ptr_low
);
65 xhci_wait_for_command(xhci_t
*const xhci
,
66 const trb_t
*const cmd_trb
,
67 const int clear_event
)
71 cc
= xhci_wait_for_command_done(xhci
, cmd_trb
, clear_event
);
75 /* Abort command on timeout */
76 xhci_debug("Aborting command (@%p), CRCR: 0x%"PRIx32
"\n",
77 cmd_trb
, xhci
->opreg
->crcr_lo
);
79 * Ref. xHCI Specification Revision 1.2, May 2019.
80 * Section 5.4.5, Table 5-24.
82 * Abort the command and stop the ring.
84 xhci
->opreg
->crcr_lo
|= CRCR_CA
;
85 xhci
->opreg
->crcr_hi
= 0;
86 cc
= xhci_wait_for_command_aborted(xhci
, cmd_trb
);
88 if (xhci
->opreg
->crcr_lo
& CRCR_CRR
)
89 fatal("xhci_wait_for_command: Command ring still running\n");
95 * xhci_cmd_* return >= 0: xhci completion code (cc)
96 * < 0: driver error code
100 xhci_cmd_enable_slot(xhci_t
*const xhci
, int *const slot_id
)
102 trb_t
*const cmd
= xhci_next_command_trb(xhci
);
103 TRB_SET(TT
, cmd
, TRB_CMD_ENABLE_SLOT
);
104 xhci_post_command(xhci
);
106 int cc
= xhci_wait_for_command(xhci
, cmd
, 0);
108 if (cc
== CC_SUCCESS
) {
109 *slot_id
= TRB_GET(ID
, xhci
->er
.cur
);
110 if (*slot_id
> xhci
->max_slots_en
)
111 cc
= CONTROLLER_ERROR
;
113 xhci_advance_event_ring(xhci
);
114 xhci_handle_events(xhci
);
120 xhci_cmd_disable_slot(xhci_t
*const xhci
, const int slot_id
)
122 trb_t
*const cmd
= xhci_next_command_trb(xhci
);
123 TRB_SET(TT
, cmd
, TRB_CMD_DISABLE_SLOT
);
124 TRB_SET(ID
, cmd
, slot_id
);
125 xhci_post_command(xhci
);
127 return xhci_wait_for_command(xhci
, cmd
, 1);
131 xhci_cmd_address_device(xhci_t
*const xhci
,
133 inputctx_t
*const ic
)
135 trb_t
*const cmd
= xhci_next_command_trb(xhci
);
136 TRB_SET(TT
, cmd
, TRB_CMD_ADDRESS_DEV
);
137 TRB_SET(ID
, cmd
, slot_id
);
138 cmd
->ptr_low
= virt_to_phys(ic
->raw
);
139 xhci_post_command(xhci
);
141 return xhci_wait_for_command(xhci
, cmd
, 1);
145 xhci_cmd_configure_endpoint(xhci_t
*const xhci
,
148 inputctx_t
*const ic
)
150 trb_t
*const cmd
= xhci_next_command_trb(xhci
);
151 TRB_SET(TT
, cmd
, TRB_CMD_CONFIGURE_EP
);
152 TRB_SET(ID
, cmd
, slot_id
);
153 cmd
->ptr_low
= virt_to_phys(ic
->raw
);
156 xhci_post_command(xhci
);
158 return xhci_wait_for_command(xhci
, cmd
, 1);
162 xhci_cmd_evaluate_context(xhci_t
*const xhci
,
164 inputctx_t
*const ic
)
166 trb_t
*const cmd
= xhci_next_command_trb(xhci
);
167 TRB_SET(TT
, cmd
, TRB_CMD_EVAL_CTX
);
168 TRB_SET(ID
, cmd
, slot_id
);
169 cmd
->ptr_low
= virt_to_phys(ic
->raw
);
170 xhci_post_command(xhci
);
172 return xhci_wait_for_command(xhci
, cmd
, 1);
176 xhci_cmd_reset_endpoint(xhci_t
*const xhci
, const int slot_id
, const int ep
)
178 trb_t
*const cmd
= xhci_next_command_trb(xhci
);
179 TRB_SET(TT
, cmd
, TRB_CMD_RESET_EP
);
180 TRB_SET(ID
, cmd
, slot_id
);
181 TRB_SET(EP
, cmd
, ep
);
182 xhci_post_command(xhci
);
184 return xhci_wait_for_command(xhci
, cmd
, 1);
188 xhci_cmd_stop_endpoint(xhci_t
*const xhci
, const int slot_id
, const int ep
)
190 trb_t
*const cmd
= xhci_next_command_trb(xhci
);
191 TRB_SET(TT
, cmd
, TRB_CMD_STOP_EP
);
192 TRB_SET(ID
, cmd
, slot_id
);
193 TRB_SET(EP
, cmd
, ep
);
194 xhci_post_command(xhci
);
196 return xhci_wait_for_command(xhci
, cmd
, 1);
200 xhci_cmd_set_tr_dq(xhci_t
*const xhci
, const int slot_id
, const int ep
,
201 trb_t
*const dq_trb
, const int dcs
)
203 trb_t
*const cmd
= xhci_next_command_trb(xhci
);
204 TRB_SET(TT
, cmd
, TRB_CMD_SET_TR_DQ
);
205 TRB_SET(ID
, cmd
, slot_id
);
206 TRB_SET(EP
, cmd
, ep
);
207 cmd
->ptr_low
= virt_to_phys(dq_trb
) | dcs
;
208 xhci_post_command(xhci
);
210 return xhci_wait_for_command(xhci
, cmd
, 1);