source: mainline/uspace/drv/bus/usb/uhci/transfer_list.c@ e0a5d4c

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e0a5d4c was e0a5d4c, checked in by Ondřej Hlavatý <aearsis@…>, 7 years ago

usb: update copyrights

The data was generated by a script, guided manually. If you feel your
name is missing somewhere, please add it!

The semi-automated process was roughly:

1) Changes per file and author (limited to our team) were counted
2) Trivial numbers were thrown away
3) Authors were sorted by lines added to file
4) All previous copyrights were replaced by the newly generated one
5) Hunks changing only year were discarded

It seems that a lot of my copyrights were added. It is due to me being
both sticking my nose everywhere and lazy to update the copyright right
away :)

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * Copyright (c) 2018 Ondrej Hlavaty, Petr Manek
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup drvusbuhcihc
31 * @{
32 */
33/** @file
34 * @brief UHCI driver transfer list implementation
35 */
36
37#include <assert.h>
38#include <errno.h>
39#include <libarch/barrier.h>
40#include <stdint.h>
41#include <usb/debug.h>
42#include <usb/host/usb_transfer_batch.h>
43#include <usb/host/utils/malloc32.h>
44#include <usb/host/utility.h>
45
46#include "hw_struct/link_pointer.h"
47#include "transfer_list.h"
48#include "hc.h"
49
50/** Initialize transfer list structures.
51 *
52 * @param[in] instance Memory place to use.
53 * @param[in] name Name of the new list.
54 * @return Error code
55 *
56 * Allocates memory for internal qh_t structure.
57 */
58errno_t transfer_list_init(transfer_list_t *instance, const char *name)
59{
60 assert(instance);
61 instance->name = name;
62 instance->queue_head = malloc32(sizeof(qh_t));
63 if (!instance->queue_head) {
64 usb_log_error("Failed to allocate queue head.");
65 return ENOMEM;
66 }
67 const uint32_t queue_head_pa = addr_to_phys(instance->queue_head);
68 usb_log_debug2("Transfer list %s setup with QH: %p (%#" PRIx32" ).",
69 name, instance->queue_head, queue_head_pa);
70
71 qh_init(instance->queue_head);
72 list_initialize(&instance->batch_list);
73 fibril_mutex_initialize(&instance->guard);
74 return EOK;
75}
76
77/** Dispose transfer list structures.
78 *
79 * @param[in] instance Memory place to use.
80 *
81 * Frees memory of the internal qh_t structure.
82 */
83void transfer_list_fini(transfer_list_t *instance)
84{
85 assert(instance);
86 free32(instance->queue_head);
87}
88/** Set the next list in transfer list chain.
89 *
90 * @param[in] instance List to lead.
91 * @param[in] next List to append.
92 * @return Error code
93 *
94 * Does not check whether this replaces an existing list .
95 */
96void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)
97{
98 assert(instance);
99 assert(instance->queue_head);
100 assert(next);
101 /* Set queue_head.next to point to the follower */
102 qh_set_next_qh(instance->queue_head, next->queue_head);
103}
104
105/**
106 * Add transfer batch to the list and queue.
107 *
108 * The batch is added to the end of the list and queue.
109 *
110 * @param[in] instance List to use.
111 * @param[in] batch Transfer batch to submit. After return, the batch must
112 * not be used further.
113 */
114int transfer_list_add_batch(
115 transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch)
116{
117 assert(instance);
118 assert(uhci_batch);
119
120 endpoint_t *ep = uhci_batch->base.ep;
121
122 fibril_mutex_lock(&instance->guard);
123
124 const int err = endpoint_activate_locked(ep, &uhci_batch->base);
125 if (err) {
126 fibril_mutex_unlock(&instance->guard);
127 return err;
128 }
129
130 usb_log_debug2("Batch %p adding to queue %s.",
131 uhci_batch, instance->name);
132
133 /* Assume there is nothing scheduled */
134 qh_t *last_qh = instance->queue_head;
135 /* There is something scheduled */
136 if (!list_empty(&instance->batch_list)) {
137 last_qh = uhci_transfer_batch_from_link(
138 list_last(&instance->batch_list))->qh;
139 }
140 /* Add to the hardware queue. */
141 const uint32_t pa = addr_to_phys(uhci_batch->qh);
142 assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
143
144 /* Make sure all data in the batch are written */
145 write_barrier();
146
147 /* keep link */
148 uhci_batch->qh->next = last_qh->next;
149 qh_set_next_qh(last_qh, uhci_batch->qh);
150
151 /* Make sure the pointer is updated */
152 write_barrier();
153
154 /* Add to the driver's list */
155 list_append(&uhci_batch->link, &instance->batch_list);
156
157 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
158 " scheduled in queue %s.", uhci_batch,
159 USB_TRANSFER_BATCH_ARGS(uhci_batch->base), instance->name);
160 fibril_mutex_unlock(&instance->guard);
161 return EOK;
162}
163
164/**
165 * Reset toggle on endpoint callback.
166 */
167static void uhci_reset_toggle(endpoint_t *ep)
168{
169 uhci_endpoint_t *uhci_ep = (uhci_endpoint_t *) ep;
170 uhci_ep->toggle = 0;
171}
172
173/** Add completed batches to the provided list.
174 *
175 * @param[in] instance List to use.
176 * @param[in] done list to fill
177 */
178void transfer_list_check_finished(transfer_list_t *instance)
179{
180 assert(instance);
181
182 fibril_mutex_lock(&instance->guard);
183 list_foreach_safe(instance->batch_list, current, next) {
184 uhci_transfer_batch_t *batch = uhci_transfer_batch_from_link(current);
185
186 if (uhci_transfer_batch_check_completed(batch)) {
187 assert(batch->base.ep->active_batch == &batch->base);
188 endpoint_deactivate_locked(batch->base.ep);
189 hc_reset_toggles(&batch->base, &uhci_reset_toggle);
190 transfer_list_remove_batch(instance, batch);
191 usb_transfer_batch_finish(&batch->base);
192 }
193 }
194 fibril_mutex_unlock(&instance->guard);
195}
196
197/** Walk the list and finish all batches with EINTR.
198 *
199 * @param[in] instance List to use.
200 */
201void transfer_list_abort_all(transfer_list_t *instance)
202{
203 fibril_mutex_lock(&instance->guard);
204 while (!list_empty(&instance->batch_list)) {
205 link_t * const current = list_first(&instance->batch_list);
206 uhci_transfer_batch_t *batch = uhci_transfer_batch_from_link(current);
207 transfer_list_remove_batch(instance, batch);
208 }
209 fibril_mutex_unlock(&instance->guard);
210}
211
212/** Remove a transfer batch from the list and queue.
213 *
214 * @param[in] instance List to use.
215 * @param[in] batch Transfer batch to remove.
216 *
217 * Does not lock the transfer list, caller is responsible for that.
218 */
219void transfer_list_remove_batch(
220 transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch)
221{
222 assert(instance);
223 assert(instance->queue_head);
224 assert(uhci_batch);
225 assert(uhci_batch->qh);
226 assert(fibril_mutex_is_locked(&instance->guard));
227 assert(!list_empty(&instance->batch_list));
228
229 usb_log_debug2("Batch %p removing from queue %s.",
230 uhci_batch, instance->name);
231
232 /* Assume I'm the first */
233 const char *qpos = "FIRST";
234 qh_t *prev_qh = instance->queue_head;
235 /* Remove from the hardware queue */
236 if (list_first(&instance->batch_list) != &uhci_batch->link) {
237 /* There is a batch in front of me */
238 prev_qh =
239 uhci_transfer_batch_from_link(uhci_batch->link.prev)->qh;
240 qpos = "NOT FIRST";
241 }
242 assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
243 == addr_to_phys(uhci_batch->qh));
244 prev_qh->next = uhci_batch->qh->next;
245
246 /* Make sure the pointer is updated */
247 write_barrier();
248
249 /* Remove from the batch list */
250 list_remove(&uhci_batch->link);
251 usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " removed (%s) "
252 "from %s, next: %x.", uhci_batch,
253 USB_TRANSFER_BATCH_ARGS(uhci_batch->base),
254 qpos, instance->name, uhci_batch->qh->next);
255}
256/**
257 * @}
258 */
Note: See TracBrowser for help on using the repository browser.