rumpdev_bus_space.c revision 1.4 1 /* $NetBSD: rumpdev_bus_space.c,v 1.4 2015/05/17 13:45:37 pooka Exp $ */
2
3 /*-
4 * Copyright (c) 2013 Antti Kantee. 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 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 #include <sys/atomic.h>
30
31 #include <sys/param.h>
32
33 #include <dev/pci/pcivar.h>
34
35 #include "pci_user.h"
36
37 #if defined(RUMP_PCI_IOSPACE) && (defined(__i386__) || defined(__x86_64__))
38 #define IOSPACE_SUPPORTED
39 #endif
40
41 int
42 bus_space_map(bus_space_tag_t bst, bus_addr_t address, bus_size_t size,
43 int flags, bus_space_handle_t *handlep)
44 {
45 int rv;
46
47 /*
48 * I/O space we just "let it bli" in case someone wants to
49 * map it (e.g. on Xen)
50 *
51 * Memory space needs to be mapped into our guest, so we
52 * make a hypercall to request it.
53 */
54 if (bst == 0) {
55 #ifdef IOSPACE_SUPPORTED
56 *handlep = address;
57 rv = 0;
58 #else
59 rv = ENOTSUP;
60 #endif
61 } else {
62 *handlep = (bus_space_handle_t)rumpcomp_pci_map(address, size);
63 rv = *handlep ? 0 : EINVAL;
64 }
65
66 return rv;
67 }
68
69 uint8_t
70 bus_space_read_1(bus_space_tag_t bst, bus_space_handle_t bsh,
71 bus_size_t offset)
72 {
73 uint8_t rv;
74
75 if (bst == 0) {
76 #ifdef IOSPACE_SUPPORTED
77 unsigned short addr = bsh + offset;
78 __asm__ __volatile__("inb %1, %0" : "=a"(rv) : "d"(addr));
79 #else
80 panic("IO space not supported");
81 #endif
82 } else {
83 rv = *(volatile uint8_t *)(bsh + offset);
84 }
85
86 return rv;
87 }
88
89 uint16_t
90 bus_space_read_2(bus_space_tag_t bst, bus_space_handle_t bsh,
91 bus_size_t offset)
92 {
93 uint16_t rv;
94
95 if (bst == 0) {
96 #ifdef IOSPACE_SUPPORTED
97 unsigned short addr = bsh + offset;
98 __asm__ __volatile__("in %1, %0" : "=a"(rv) : "d"(addr));
99 #else
100 panic("IO space not supported");
101 #endif
102 } else {
103 rv = *(volatile uint16_t *)(bsh + offset);
104 }
105
106 return rv;
107 }
108
109 uint32_t
110 bus_space_read_4(bus_space_tag_t bst, bus_space_handle_t bsh,
111 bus_size_t offset)
112 {
113 uint32_t rv;
114
115 if (bst == 0) {
116 #ifdef IOSPACE_SUPPORTED
117 unsigned short addr = bsh + offset;
118 __asm__ __volatile__("inl %1, %0" : "=a"(rv) : "d"(addr));
119 #else
120 panic("IO space not supported");
121 #endif
122 } else {
123 rv = *(volatile uint32_t *)(bsh + offset);
124 }
125
126 return rv;
127 }
128
129 void
130 bus_space_read_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
131 bus_size_t offset, uint8_t *datap, bus_size_t count)
132 {
133
134 while (count--) {
135 *datap++ = bus_space_read_1(bst, bsh, offset);
136 bus_space_barrier(bst, bst, offset, 1, BUS_SPACE_BARRIER_READ);
137 }
138 }
139
140 void
141 bus_space_read_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
142 bus_size_t offset, uint16_t *datap, bus_size_t count)
143 {
144
145 while (count--) {
146 *datap++ = bus_space_read_2(bst, bsh, offset);
147 bus_space_barrier(bst, bst, offset, 2, BUS_SPACE_BARRIER_READ);
148 }
149 }
150
151 void
152 bus_space_read_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
153 bus_size_t offset, uint32_t *datap, bus_size_t count)
154 {
155
156 while (count--) {
157 *datap++ = bus_space_read_4(bst, bsh, offset);
158 bus_space_barrier(bst, bst, offset, 4, BUS_SPACE_BARRIER_READ);
159 }
160 }
161
162 void
163 bus_space_write_1(bus_space_tag_t bst, bus_space_handle_t bsh,
164 bus_size_t offset, uint8_t v)
165 {
166
167 if (bst == 0) {
168 #ifdef IOSPACE_SUPPORTED
169 unsigned short addr = bsh + offset;
170 __asm__ __volatile__("outb %0, %1" :: "a"(v), "d"(addr));
171 #else
172 panic("IO space not supported");
173 #endif
174 } else {
175 *(volatile uint8_t *)(bsh + offset) = v;
176 }
177 }
178
179 void
180 bus_space_write_2(bus_space_tag_t bst, bus_space_handle_t bsh,
181 bus_size_t offset, uint16_t v)
182 {
183
184 if (bst == 0) {
185 #ifdef IOSPACE_SUPPORTED
186 unsigned short addr = bsh + offset;
187 __asm__ __volatile__("out %0, %1" :: "a"(v), "d"(addr));
188 #else
189 panic("IO space not supported");
190 #endif
191 } else {
192 *(volatile uint16_t *)(bsh + offset) = v;
193 }
194 }
195
196 void
197 bus_space_write_4(bus_space_tag_t bst, bus_space_handle_t bsh,
198 bus_size_t offset, uint32_t v)
199 {
200
201 if (bst == 0) {
202 #ifdef IOSPACE_SUPPORTED
203 unsigned short addr = bsh + offset;
204 __asm__ __volatile__("outl %0, %1" :: "a"(v), "d"(addr));
205 #else
206 panic("IO space not supported");
207 #endif
208 } else {
209 *(volatile uint32_t *)(bsh + offset) = v;
210 }
211 }
212
213 void
214 bus_space_write_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
215 bus_size_t offset, const uint8_t *datap, bus_size_t count)
216 {
217
218 while (count--) {
219 const uint8_t value = *datap++;
220
221 bus_space_write_1(bst, bsh, offset, value);
222 bus_space_barrier(bst, bst, offset, 1, BUS_SPACE_BARRIER_WRITE);
223 }
224 }
225
226 void
227 bus_space_write_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
228 bus_size_t offset, const uint16_t *datap, bus_size_t count)
229 {
230
231 while (count--) {
232 const uint16_t value = *datap++;
233
234 bus_space_write_2(bst, bsh, offset, value);
235 bus_space_barrier(bst, bst, offset, 2, BUS_SPACE_BARRIER_WRITE);
236 }
237 }
238
239 void
240 bus_space_write_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
241 bus_size_t offset, const uint32_t *datap, bus_size_t count)
242 {
243
244 while (count--) {
245 const uint32_t value = *datap++;
246
247 bus_space_write_4(bst, bsh, offset, value);
248 bus_space_barrier(bst, bst, offset, 4, BUS_SPACE_BARRIER_WRITE);
249 }
250 }
251
252 paddr_t
253 bus_space_mmap(bus_space_tag_t bst, bus_addr_t addr, off_t off,
254 int prot, int flags)
255 {
256
257 panic("%s: unimplemented", __func__);
258 }
259
260 int
261 bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh,
262 bus_size_t offset, bus_size_t size, bus_space_handle_t *nhandlep)
263 {
264
265 *nhandlep = bsh + offset;
266 return 0;
267 }
268
269 void
270 bus_space_unmap(bus_space_tag_t bst, bus_space_handle_t bsh,
271 bus_size_t size)
272 {
273
274 panic("%s: unimplemented", __func__);
275 }
276
277 void
278 bus_space_barrier(bus_space_tag_t bst, bus_space_handle_t bsh,
279 bus_size_t offset, bus_size_t len, int flags)
280 {
281
282 /* weelll ... */
283 membar_sync();
284 }
285