source: mainline/uspace/drv/bus/usb/ehci/endpoint_list.c@ 2b3dd78

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 2b3dd78 was 5a6cc679, checked in by Jenda <jenda.jzqk73@…>, 8 years ago

Merge commit '50f19b7ee8e94570b5c63896736c4eb49cfa18db' into forwardport

Not all ints are converted to errno_t in xhci tree yet, however it compiles and works :)

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2014 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup drvusbehci
30 * @{
31 */
32/** @file
33 * @brief EHCI driver transfer list implementation
34 */
35
36#include <assert.h>
37#include <errno.h>
38#include <libarch/barrier.h>
39
40#include <usb/debug.h>
41
42#include "endpoint_list.h"
43
44/** Initialize transfer list structures.
45 *
46 * @param[in] instance Memory place to use.
47 * @param[in] name Name of the new list.
48 * @return Error code
49 *
50 * Allocates memory for internal ed_t structure.
51 */
52errno_t endpoint_list_init(endpoint_list_t *instance, const char *name)
53{
54 assert(instance);
55 instance->name = name;
56 if (dma_buffer_alloc(&instance->dma_buffer, sizeof(qh_t))) {
57 usb_log_error("EPL(%p-%s): Failed to allocate list head.",
58 instance, name);
59 return ENOMEM;
60 }
61 instance->list_head = instance->dma_buffer.virt;
62 qh_init(instance->list_head, NULL);
63
64 list_initialize(&instance->endpoint_list);
65 fibril_mutex_initialize(&instance->guard);
66
67 usb_log_debug2("EPL(%p-%s): Transfer list setup with ED: %p(%"PRIxn").",
68 instance, name, instance->list_head,
69 addr_to_phys(instance->list_head));
70
71 return EOK;
72}
73
74void endpoint_list_chain(endpoint_list_t *instance, const endpoint_list_t *next)
75{
76 assert(instance);
77 assert(next);
78 assert(instance->list_head);
79 assert(next->list_head);
80
81 usb_log_debug2("EPL(%p-%s): Chained with EPL(%p-%s).",
82 instance, instance->name, next, next->name);
83
84 qh_append_qh(instance->list_head, next->list_head);
85}
86
87/** Add endpoint to the end of the list and queue.
88 *
89 * @param[in] instance List to use.
90 * @param[in] endpoint Endpoint to add.
91 *
92 * The endpoint is added to the end of the list and queue.
93 */
94void endpoint_list_append_ep(endpoint_list_t *instance, ehci_endpoint_t *ep)
95{
96 assert(instance);
97 assert(instance->list_head);
98 assert(ep);
99 assert(ep->qh);
100 usb_log_debug2("EPL(%p-%s): Append endpoint(%p).",
101 instance, instance->name, ep);
102
103 fibril_mutex_lock(&instance->guard);
104
105 qh_t *last_qh = NULL;
106 /* Add to the hardware queue. */
107 if (list_empty(&instance->endpoint_list)) {
108 /* There are no active EDs */
109 last_qh = instance->list_head;
110 } else {
111 /* There are active EDs, get the last one */
112 ehci_endpoint_t *last = ehci_endpoint_list_instance(
113 list_last(&instance->endpoint_list));
114 last_qh = last->qh;
115 }
116 assert(last_qh);
117 /* Keep link, this might point to the queue QH, or next chained queue */
118 ep->qh->horizontal = last_qh->horizontal;
119 /* Make sure QH update is written to the memory */
120 write_barrier();
121
122 /* Add QH to the hw queue */
123 qh_append_qh(last_qh, ep->qh);
124 /* Make sure QH is updated */
125 write_barrier();
126 /* Add to the sw list */
127 list_append(&ep->eplist_link, &instance->endpoint_list);
128
129 ehci_endpoint_t *first = ehci_endpoint_list_instance(
130 list_first(&instance->endpoint_list));
131 usb_log_debug("EPL(%p-%s): EP(%p) added to list, first is %p(%p).",
132 instance, instance->name, ep, first, first->qh);
133 if (last_qh == instance->list_head) {
134 usb_log_debug2("EPL(%p-%s): head EP(%p-%"PRIxn"): %x:%x.",
135 instance, instance->name, last_qh,
136 addr_to_phys(instance->list_head),
137 last_qh->status, last_qh->horizontal);
138 }
139 fibril_mutex_unlock(&instance->guard);
140}
141
142/** Remove endpoint from the list and queue.
143 *
144 * @param[in] instance List to use.
145 * @param[in] endpoint Endpoint to remove.
146 */
147void endpoint_list_remove_ep(endpoint_list_t *instance, ehci_endpoint_t *ep)
148{
149 assert(instance);
150 assert(instance->list_head);
151 assert(ep);
152 assert(ep->qh);
153
154 fibril_mutex_lock(&instance->guard);
155
156 usb_log_debug2("EPL(%p-%s): removing EP(%p).",
157 instance, instance->name, ep);
158
159 const char *qpos = NULL;
160 qh_t *prev_qh;
161 /* Remove from the hardware queue */
162 if (list_first(&instance->endpoint_list) == &ep->eplist_link) {
163 /* I'm the first one here */
164 prev_qh = instance->list_head;
165 qpos = "FIRST";
166 } else {
167 prev_qh = ehci_endpoint_list_instance(ep->eplist_link.prev)->qh;
168 qpos = "NOT FIRST";
169 }
170 assert(qh_next(prev_qh) == addr_to_phys(ep->qh));
171 prev_qh->horizontal = ep->qh->horizontal;
172 /* Make sure ED is updated */
173 write_barrier();
174
175 usb_log_debug("EPL(%p-%s): EP(%p) removed (%s), horizontal %x.",
176 instance, instance->name, ep, qpos, ep->qh->horizontal);
177
178 /* Remove from the endpoint list */
179 list_remove(&ep->eplist_link);
180 fibril_mutex_unlock(&instance->guard);
181}
182/**
183 * @}
184 */
185
Note: See TracBrowser for help on using the repository browser.