1/* $OpenBSD: bus.h,v 1.67 2017/05/08 00:27:45 dlg Exp $ */
2/* $NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $ */
3
4/*-
5 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10 * NASA Ames Research Center.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/*
35 * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
36 * Copyright (c) 1996 Jason R. Thorpe. All rights reserved.
37 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. All advertising materials mentioning features or use of this software
48 * must display the following acknowledgement:
49 * This product includes software developed by Christopher G. Demetriou
50 * for the NetBSD Project.
51 * 4. The name of the author may not be used to endorse or promote products
52 * derived from this software without specific prior written permission
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
55 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
56 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
58 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
63 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 */
65
66#ifndef _MACHINE_BUS_H_
67#define _MACHINE_BUS_H_
68
69#include <sys/mutex.h>
70#include <sys/tree.h>
71
72#include <machine/pio.h>
73
74/*
75 * Bus address and size types
76 */
77typedef u_long bus_addr_t;
78typedef u_long bus_size_t;
79
80/*
81 * Access methods for bus resources and address space.
82 */
83struct i386_bus_space_ops;
84typedef const struct i386_bus_space_ops *bus_space_tag_t;
85typedef u_long bus_space_handle_t;
86
87int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
88 bus_size_t size, int flags, bus_space_handle_t *bshp);
89/* like bus_space_map(), but without extent map checking/allocation */
90int _bus_space_map(bus_space_tag_t t, bus_addr_t addr,
91 bus_size_t size, int flags, bus_space_handle_t *bshp);
92void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
93 bus_size_t size);
94/* like bus_space_unmap(), but without extent map deallocation */
95void _bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
96 bus_size_t, bus_addr_t *);
97int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
98 bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
99paddr_t bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
100
101int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
102 bus_addr_t rend, bus_size_t size, bus_size_t align,
103 bus_size_t boundary, int flags, bus_addr_t *addrp,
104 bus_space_handle_t *bshp);
105void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
106 bus_size_t size);
107
108struct i386_bus_space_ops {
109
110/*
111 * u_intN_t bus_space_read_N(bus_space_tag_t tag,
112 * bus_space_handle_t bsh, bus_size_t offset);
113 *
114 * Read a 1, 2, 4, or 8 byte quantity from bus space
115 * described by tag/handle/offset.
116 */
117 u_int8_t (*read_1)(bus_space_handle_t, bus_size_t);
118 u_int16_t (*read_2)(bus_space_handle_t, bus_size_t);
119 u_int32_t (*read_4)(bus_space_handle_t, bus_size_t);
120
121#define bus_space_read_1(_t, _h, _o) ((_t)->read_1((_h), (_o)))
122#define bus_space_read_2(_t, _h, _o) ((_t)->read_2((_h), (_o)))
123#define bus_space_read_4(_t, _h, _o) ((_t)->read_4((_h), (_o)))
124
125#define bus_space_read_raw_2(t, h, o) \
126 bus_space_read_2((t), (h), (o))
127#define bus_space_read_raw_4(t, h, o) \
128 bus_space_read_4((t), (h), (o))
129
130#if 0
131/* Cause a link error for bus_space_read_8 and bus_space_read_raw_8 */
132#define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!!
133#define bus_space_read_raw_8(t, h, o) !!! bus_space_read_raw_8 unimplemented !!!
134#endif
135
136/*
137 * void bus_space_read_multi_N(bus_space_tag_t tag,
138 * bus_space_handle_t bsh, bus_size_t offset,
139 * u_intN_t *addr, size_t count);
140 *
141 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
142 * described by tag/handle/offset and copy into buffer provided.
143 */
144
145 void (*read_multi_1)(bus_space_handle_t, bus_size_t,
146 u_int8_t *, bus_size_t);
147 void (*read_multi_2)(bus_space_handle_t, bus_size_t,
148 u_int16_t *, bus_size_t);
149 void (*read_multi_4)(bus_space_handle_t, bus_size_t,
150 u_int32_t *, bus_size_t);
151
152#define bus_space_read_multi_1(_t, _h, _o, _a, _c) \
153 ((_t)->read_multi_1((_h), (_o), (_a), (_c)))
154#define bus_space_read_multi_2(_t, _h, _o, _a, _c) \
155 ((_t)->read_multi_2((_h), (_o), (_a), (_c)))
156#define bus_space_read_multi_4(_t, _h, _o, _a, _c) \
157 ((_t)->read_multi_4((_h), (_o), (_a), (_c)))
158
159#if 0 /* Cause a link error for bus_space_read_multi_8 */
160#define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!!
161#endif
162
163/*
164 * void bus_space_read_raw_multi_N(bus_space_tag_t tag,
165 * bus_space_handle_t bsh, bus_size_t offset,
166 * u_int8_t *addr, size_t count);
167 *
168 * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
169 * described by tag/handle/offset and copy into buffer provided. The buffer
170 * must have proper alignment for the N byte wide entities. Furthermore
171 * possible byte-swapping should be done by these functions.
172 */
173
174#define bus_space_read_raw_multi_2(t, h, o, a, c) \
175 bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
176#define bus_space_read_raw_multi_4(t, h, o, a, c) \
177 bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
178
179#if 0 /* Cause a link error for bus_space_read_raw_multi_8 */
180#define bus_space_read_raw_multi_8 \
181 !!! bus_space_read_raw_multi_8 unimplemented !!!
182#endif
183
184/*
185 * void bus_space_read_region_N(bus_space_tag_t tag,
186 * bus_space_handle_t bsh, bus_size_t offset,
187 * u_intN_t *addr, size_t count);
188 *
189 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
190 * described by tag/handle and starting at `offset' and copy into
191 * buffer provided.
192 */
193
194 void (*read_region_1)(bus_space_handle_t,
195 bus_size_t, u_int8_t *, bus_size_t);
196 void (*read_region_2)(bus_space_handle_t,
197 bus_size_t, u_int16_t *, bus_size_t);
198 void (*read_region_4)(bus_space_handle_t,
199 bus_size_t, u_int32_t *, bus_size_t);
200
201#define bus_space_read_region_1(_t, _h, _o, _a, _c) \
202 ((_t)->read_region_1((_h), (_o), (_a), (_c)))
203#define bus_space_read_region_2(_t, _h, _o, _a, _c) \
204 ((_t)->read_region_2((_h), (_o), (_a), (_c)))
205#define bus_space_read_region_4(_t, _h, _o, _a, _c) \
206 ((_t)->read_region_4((_h), (_o), (_a), (_c)))
207
208#if 0 /* Cause a link error for bus_space_read_region_8 */
209#define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
210#endif
211
212/*
213 * void bus_space_read_raw_region_N(bus_space_tag_t tag,
214 * bus_space_handle_t bsh, bus_size_t offset,
215 * u_int8_t *addr, size_t count);
216 *
217 * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
218 * described by tag/handle and starting at `offset' and copy into
219 * buffer provided. The buffer must have proper alignment for the N byte
220 * wide entities. Furthermore possible byte-swapping should be done by
221 * these functions.
222 */
223
224#define bus_space_read_raw_region_2(_t, _h, _o, _a, _c) \
225 ((_t)->read_region_2((_h), (_o), (u_int16_t *)(_a), (_c) >> 1))
226#define bus_space_read_raw_region_4(_t, _h, _o, _a, _c) \
227 ((_t)->read_region_4((_h), (_o), (u_int32_t *)(_a), (_c) >> 2))
228
229#if 0 /* Cause a link error for bus_space_read_raw_region_8 */
230#define bus_space_read_raw_region_8 \
231 !!! bus_space_read_raw_region_8 unimplemented !!!
232#endif
233
234/*
235 * void bus_space_write_N(bus_space_tag_t tag,
236 * bus_space_handle_t bsh, bus_size_t offset,
237 * u_intN_t value);
238 *
239 * Write the 1, 2, 4, or 8 byte value `value' to bus space
240 * described by tag/handle/offset.
241 */
242
243 void (*write_1)(bus_space_handle_t, bus_size_t, u_int8_t);
244 void (*write_2)(bus_space_handle_t, bus_size_t, u_int16_t);
245 void (*write_4)(bus_space_handle_t, bus_size_t, u_int32_t);
246
247#define bus_space_write_1(_t, _h, _o, _v) \
248 ((_t)->write_1((_h), (_o), (_v)))
249#define bus_space_write_2(_t, _h, _o, _v) \
250 ((_t)->write_2((_h), (_o), (_v)))
251#define bus_space_write_4(_t, _h, _o, _v) \
252 ((_t)->write_4((_h), (_o), (_v)))
253
254#define bus_space_write_raw_2(t, h, o, v) \
255 bus_space_write_2((t), (h), (o), (v))
256#define bus_space_write_raw_4(t, h, o, v) \
257 bus_space_write_4((t), (h), (o), (v))
258
259#if 0
260/* Cause a link error for bus_space_write_8 and bus_space_write_raw_8 */
261#define bus_space_write_8 !!! bus_space_write_8 not implemented !!!
262#define bus_space_write_raw_8 !!! bus_space_write_raw_8 not implemented !!!
263#endif
264
265/*
266 * void bus_space_write_multi_N(bus_space_tag_t tag,
267 * bus_space_handle_t bsh, bus_size_t offset,
268 * const u_intN_t *addr, size_t count);
269 *
270 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
271 * provided to bus space described by tag/handle/offset.
272 */
273
274 void (*write_multi_1)(bus_space_handle_t,
275 bus_size_t, const u_int8_t *, bus_size_t);
276 void (*write_multi_2)(bus_space_handle_t,
277 bus_size_t, const u_int16_t *, bus_size_t);
278 void (*write_multi_4)(bus_space_handle_t,
279 bus_size_t, const u_int32_t *, bus_size_t);
280
281#define bus_space_write_multi_1(_t, _h, _o, _a, _c) \
282 ((_t)->write_multi_1((_h), (_o), (_a), (_c)))
283#define bus_space_write_multi_2(_t, _h, _o, _a, _c) \
284 ((_t)->write_multi_2((_h), (_o), (_a), (_c)))
285#define bus_space_write_multi_4(_t, _h, _o, _a, _c) \
286 ((_t)->write_multi_4((_h), (_o), (_a), (_c)))
287
288#if 0 /* Cause a link error for bus_space_write_multi_8 */
289#define bus_space_write_multi_8(t, h, o, a, c) \
290 !!! bus_space_write_multi_8 unimplemented !!!
291#endif
292
293/*
294 * void bus_space_write_raw_multi_N(bus_space_tag_t tag,
295 * bus_space_handle_t bsh, bus_size_t offset,
296 * const u_int8_t *addr, size_t count);
297 *
298 * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer
299 * provided to bus space described by tag/handle/offset. The buffer
300 * must have proper alignment for the N byte wide entities. Furthermore
301 * possible byte-swapping should be done by these functions.
302 */
303
304#define bus_space_write_raw_multi_2(_t, _h, _o, _a, _c) \
305 ((_t)->write_multi_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1))
306#define bus_space_write_raw_multi_4(_t, _h, _o, _a, _c) \
307 ((_t)->write_multi_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2))
308
309#if 0 /* Cause a link error for bus_space_write_raw_multi_8 */
310#define bus_space_write_raw_multi_8 \
311 !!! bus_space_write_raw_multi_8 unimplemented !!!
312#endif
313
314/*
315 * void bus_space_write_region_N(bus_space_tag_t tag,
316 * bus_space_handle_t bsh, bus_size_t offset,
317 * const u_intN_t *addr, size_t count);
318 *
319 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
320 * to bus space described by tag/handle starting at `offset'.
321 */
322
323 void (*write_region_1)(bus_space_handle_t,
324 bus_size_t, const u_int8_t *, bus_size_t);
325 void (*write_region_2)(bus_space_handle_t,
326 bus_size_t, const u_int16_t *, bus_size_t);
327 void (*write_region_4)(bus_space_handle_t,
328 bus_size_t, const u_int32_t *, bus_size_t);
329
330#define bus_space_write_region_1(_t, _h, _o, _a, _c) \
331 ((_t)->write_region_1((_h), (_o), (_a), (_c)))
332#define bus_space_write_region_2(_t, _h, _o, _a, _c) \
333 ((_t)->write_region_2((_h), (_o), (_a), (_c)))
334#define bus_space_write_region_4(_t, _h, _o, _a, _c) \
335 ((_t)->write_region_4((_h), (_o), (_a), (_c)))
336
337#if 0 /* Cause a link error for bus_space_write_region_8 */
338#define bus_space_write_region_8 \
339 !!! bus_space_write_region_8 unimplemented !!!
340#endif
341
342/*
343 * void bus_space_write_raw_region_N(bus_space_tag_t tag,
344 * bus_space_handle_t bsh, bus_size_t offset,
345 * const u_int8_t *addr, size_t count);
346 *
347 * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space
348 * described by tag/handle and starting at `offset' from the
349 * buffer provided. The buffer must have proper alignment for the N byte
350 * wide entities. Furthermore possible byte-swapping should be done by
351 * these functions.
352 */
353
354#define bus_space_write_raw_region_2(_t, _h, _o, _a, _c) \
355 ((_t)->write_region_2((_h), (_o), (const u_int16_t *)(_a), (_c) >> 1))
356#define bus_space_write_raw_region_4(_t, _h, _o, _a, _c) \
357 ((_t)->write_region_4((_h), (_o), (const u_int32_t *)(_a), (_c) >> 2))
358
359#if 0 /* Cause a link error for bus_space_write_raw_region_8 */
360#define bus_space_write_raw_region_8 \
361 !!! bus_space_write_raw_region_8 unimplemented !!!
362#endif
363
364/*
365 * void bus_space_set_multi_N(bus_space_tag_t tag,
366 * bus_space_handle_t bsh, bus_size_t offset,
367 * u_intN_t val, size_t count);
368 *
369 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
370 * by tag/handle/offset `count' times.
371 */
372
373 void (*set_multi_1)(bus_space_handle_t,
374 bus_size_t, u_int8_t, size_t);
375 void (*set_multi_2)(bus_space_handle_t,
376 bus_size_t, u_int16_t, size_t);
377 void (*set_multi_4)(bus_space_handle_t,
378 bus_size_t, u_int32_t, size_t);
379
380#define bus_space_set_multi_1(_t, _h, _o, _a, _c) \
381 ((_t)->set_multi_1((_h), (_o), (_a), (_c)))
382#define bus_space_set_multi_2(_t, _h, _o, _a, _c) \
383 ((_t)->set_multi_2((_h), (_o), (_a), (_c)))
384#define bus_space_set_multi_4(_t, _h, _o, _a, _c) \
385 ((_t)->set_multi_4((_h), (_o), (_a), (_c)))
386
387#if 0 /* Cause a link error for bus_space_set_multi_8 */
388#define bus_space_set_multi_8 \
389 !!! bus_space_set_multi_8 unimplemented !!!
390#endif
391
392/*
393 * void bus_space_set_region_N(bus_space_tag_t tag,
394 * bus_space_handle_t bsh, bus_size_t offset,
395 * u_intN_t val, size_t count);
396 *
397 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
398 * by tag/handle starting at `offset'.
399 */
400
401 void (*set_region_1)(bus_space_handle_t,
402 bus_size_t, u_int8_t, size_t);
403 void (*set_region_2)(bus_space_handle_t,
404 bus_size_t, u_int16_t, size_t);
405 void (*set_region_4)(bus_space_handle_t,
406 bus_size_t, u_int32_t, size_t);
407
408#define bus_space_set_region_1(_t, _h, _o, _a, _c) \
409 ((_t)->set_region_1((_h), (_o), (_a), (_c)))
410#define bus_space_set_region_2(_t, _h, _o, _a, _c) \
411 ((_t)->set_region_2((_h), (_o), (_a), (_c)))
412#define bus_space_set_region_4(_t, _h, _o, _a, _c) \
413 ((_t)->set_region_4((_h), (_o), (_a), (_c)))
414
415#if 0 /* Cause a link error for bus_space_set_region_8 */
416#define bus_space_set_region_8 \
417 !!! bus_space_set_region_8 unimplemented !!!
418#endif
419
420/*
421 * void bus_space_copy_N(bus_space_tag_t tag,
422 * bus_space_handle_t bsh1, bus_size_t off1,
423 * bus_space_handle_t bsh2, bus_size_t off2,
424 * size_t count);
425 *
426 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
427 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
428 */
429
430 void (*copy_1)(bus_space_handle_t,
431 bus_size_t, bus_space_handle_t, bus_size_t, size_t);
432 void (*copy_2)(bus_space_handle_t,
433 bus_size_t, bus_space_handle_t, bus_size_t, size_t);
434 void (*copy_4)(bus_space_handle_t,
435 bus_size_t, bus_space_handle_t, bus_size_t, size_t);
436
437#define bus_space_copy_1(_t, _h1, _o1, _h2, _o2, _c) \
438 ((_t)->copy_1((_h1), (_o1), (_h2), (_o2), (_c)))
439#define bus_space_copy_2(_t, _h1, _o1, _h2, _o2, _c) \
440 ((_t)->copy_2((_h1), (_o1), (_h2), (_o2), (_c)))
441#define bus_space_copy_4(_t, _h1, _o1, _h2, _o2, _c) \
442 ((_t)->copy_4((_h1), (_o1), (_h2), (_o2), (_c)))
443
444#if 0 /* Cause a link error for bus_space_copy_8 */
445#define bus_space_copy_8 \
446 !!! bus_space_copy_8 unimplemented !!!
447#endif
448
449#define i386_space_copy1(a1, a2, cnt, movs, df) \
450 __asm volatile(df "\n\trep\n\t" movs : \
451 "+S" (a1), "+D" (a2), "+c" (cnt) :: "memory", "cc");
452
453#define i386_space_copy(a1, a2, sz, cnt) do { \
454 if ((void *)(a1) < (void *)(a2)) { \
455 a1 += ((cnt) - 1) * (sz); a2 += ((cnt) - 1) * (sz); \
456 switch (sz) { \
457 case 1: i386_space_copy1(a1,a2,cnt,"movsb","std");break;\
458 case 2: i386_space_copy1(a1,a2,cnt,"movsw","std");break;\
459 case 4: i386_space_copy1(a1,a2,cnt,"movsl","std");break;\
460 } \
461 __asm volatile("cld"); /* must restore before func ret */ \
462 } else \
463 switch (sz) { \
464 case 1: i386_space_copy1(a1,a2,cnt,"movsb","cld");break;\
465 case 2: i386_space_copy1(a1,a2,cnt,"movsw","cld");break;\
466 case 4: i386_space_copy1(a1,a2,cnt,"movsl","cld");break;\
467 } \
468} while (0)
469
470/*
471 * void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
472 *
473 * Get the kernel virtual address for the mapped bus space.
474 * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR.
475 */
476 void * (*vaddr)(bus_space_handle_t);
477
478#define bus_space_vaddr(_t, _h) \
479 ((_t)->vaddr((_h)))
480};
481
482/*
483 * Bus read/write barrier methods.
484 *
485 * void bus_space_barrier(bus_space_tag_t tag,
486 * bus_space_handle_t bsh, bus_size_t offset,
487 * bus_size_t len, int flags);
488 *
489 * Note: the i386 does not currently require barriers, but we must
490 * provide the flags to MI code.
491 */
492#define bus_space_barrier(t, h, o, l, f) do { \
493 ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)));\
494 __asm volatile("" : : : "memory"); \
495} while (0)
496#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
497#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
498
499#define BUS_SPACE_MAP_CACHEABLE 0x0001
500#define BUS_SPACE_MAP_LINEAR 0x0002
501#define BUS_SPACE_MAP_PREFETCHABLE 0x0008
502
503/*
504 * Values for the i386 bus space tag, not to be used directly by MI code.
505 */
506
507/* space is i/o space */
508extern const struct i386_bus_space_ops i386_bus_space_io_ops;
509#define I386_BUS_SPACE_IO (&i386_bus_space_io_ops)
510
511/* space is mem space */
512extern const struct i386_bus_space_ops i386_bus_space_mem_ops;
513#define I386_BUS_SPACE_MEM (&i386_bus_space_mem_ops)
514
515/*
516 * Flags used in various bus DMA methods.
517 */
518#define BUS_DMA_WAITOK 0x0000 /* safe to sleep (pseudo-flag) */
519#define BUS_DMA_NOWAIT 0x0001 /* not safe to sleep */
520#define BUS_DMA_ALLOCNOW 0x0002 /* perform resource allocation now */
521#define BUS_DMA_COHERENT 0x0004 /* hint: map memory DMA coherent */
522#define BUS_DMA_BUS1 0x0010 /* placeholders for bus functions... */
523#define BUS_DMA_BUS2 0x0020
524#define BUS_DMA_BUS3 0x0040
525#define BUS_DMA_24BIT 0x0080 /* isadma map */
526#define BUS_DMA_STREAMING 0x0100 /* hint: sequential, unidirectional */
527#define BUS_DMA_READ 0x0200 /* mapping is device -> memory only */
528#define BUS_DMA_WRITE 0x0400 /* mapping is memory -> device only */
529#define BUS_DMA_NOCACHE 0x0800 /* map memory uncached */
530#define BUS_DMA_ZERO 0x1000 /* dmamem_alloc return zeroed mem */
531#define BUS_DMA_64BIT 0x2000 /* device handles 64bit dva */
532
533/* Forwards needed by prototypes below. */
534struct mbuf;
535struct proc;
536struct uio;
537
538/*
539 * Operations performed by bus_dmamap_sync().
540 */
541#define BUS_DMASYNC_PREREAD 0x01
542#define BUS_DMASYNC_POSTREAD 0x02
543#define BUS_DMASYNC_PREWRITE 0x04
544#define BUS_DMASYNC_POSTWRITE 0x08
545
546typedef struct bus_dma_tag *bus_dma_tag_t;
547typedef struct bus_dmamap *bus_dmamap_t;
548
549/*
550 * bus_dma_segment_t
551 *
552 * Describes a single contiguous DMA transaction. Values
553 * are suitable for programming into DMA registers.
554 */
555struct bus_dma_segment {
556 bus_addr_t ds_addr; /* DMA address */
557 bus_size_t ds_len; /* length of transfer */
558 /*
559 * Ugh. need this so can pass alignment down from bus_dmamem_alloc
560 * to scatter gather maps. only the first one is used so the rest is
561 * wasted space. bus_dma could do with fixing the api for this.
562 */
563 bus_size_t _ds_boundary; /* don't cross */
564 bus_size_t _ds_align; /* align to me */
565};
566typedef struct bus_dma_segment bus_dma_segment_t;
567
568/*
569 * bus_dma_tag_t
570 *
571 * A machine-dependent opaque type describing the implementation of
572 * DMA for a given bus.
573 */
574
575struct bus_dma_tag {
576 void *_cookie; /* cookie used in the guts */
577
578 /*
579 * DMA mapping methods.
580 */
581 int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
582 bus_size_t, bus_size_t, int, bus_dmamap_t *);
583 void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
584 int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
585 bus_size_t, struct proc *, int);
586 int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
587 struct mbuf *, int);
588 int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
589 struct uio *, int);
590 int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
591 bus_dma_segment_t *, int, bus_size_t, int);
592 void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
593 void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
594 bus_addr_t, bus_size_t, int);
595
596 /*
597 * DMA memory utility functions.
598 */
599 int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
600 bus_size_t, bus_dma_segment_t *, int, int *, int);
601 int (*_dmamem_alloc_range)(bus_dma_tag_t, bus_size_t, bus_size_t,
602 bus_size_t, bus_dma_segment_t *, int, int *, int,
603 bus_addr_t, bus_addr_t);
604 void (*_dmamem_free)(bus_dma_tag_t,
605 bus_dma_segment_t *, int);
606 int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
607 int, size_t, caddr_t *, int);
608 void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
609 paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
610 int, off_t, int, int);
611};
612
613#define bus_dmamap_create(t, s, n, m, b, f, p) \
614 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
615#define bus_dmamap_destroy(t, p) \
616 (*(t)->_dmamap_destroy)((t), (p))
617#define bus_dmamap_load(t, m, b, s, p, f) \
618 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
619#define bus_dmamap_load_mbuf(t, m, b, f) \
620 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
621#define bus_dmamap_load_uio(t, m, u, f) \
622 (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
623#define bus_dmamap_load_raw(t, m, sg, n, s, f) \
624 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
625#define bus_dmamap_unload(t, p) \
626 (*(t)->_dmamap_unload)((t), (p))
627#define bus_dmamap_sync(t, p, o, l, ops) \
628 (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops))
629
630#define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
631 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
632#define bus_dmamem_alloc_range(t, s, a, b, sg, n, r, f, l, h) \
633 (*(t)->_dmamem_alloc_range)((t), (s), (a), (b), (sg), \
634 (n), (r), (f), (l), (h))
635#define bus_dmamem_free(t, sg, n) \
636 (*(t)->_dmamem_free)((t), (sg), (n))
637#define bus_dmamem_map(t, sg, n, s, k, f) \
638 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
639#define bus_dmamem_unmap(t, k, s) \
640 (*(t)->_dmamem_unmap)((t), (k), (s))
641#define bus_dmamem_mmap(t, sg, n, o, p, f) \
642 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
643
644/*
645 * bus_dmamap_t
646 *
647 * Describes a DMA mapping.
648 */
649struct bus_dmamap {
650 /*
651 * PRIVATE MEMBERS: not for use by machine-independent code.
652 */
653 bus_size_t _dm_size; /* largest DMA transfer mappable */
654 int _dm_segcnt; /* number of segs this map can map */
655 bus_size_t _dm_maxsegsz; /* largest possible segment */
656 bus_size_t _dm_boundary; /* don't cross this */
657 int _dm_flags; /* misc. flags */
658
659 void *_dm_cookie; /* cookie for bus-specific functions */
660
661 /*
662 * PUBLIC MEMBERS: these are used by machine-independent code.
663 */
664 bus_size_t dm_mapsize; /* size of the mapping */
665 int dm_nsegs; /* # valid segments in mapping */
666 bus_dma_segment_t dm_segs[1]; /* segments; variable length */
667};
668
669int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
670 bus_size_t, int, bus_dmamap_t *);
671void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
672int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
673 bus_size_t, struct proc *, int);
674int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
675 struct mbuf *, int);
676int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
677 struct uio *, int);
678int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
679 bus_dma_segment_t *, int, bus_size_t, int);
680void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
681void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
682 bus_size_t, int);
683
684int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
685 bus_size_t alignment, bus_size_t boundary,
686 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
687void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
688 int nsegs);
689int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
690 int nsegs, size_t size, caddr_t *kvap, int flags);
691void _bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
692 size_t size);
693paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
694 int nsegs, off_t off, int prot, int flags);
695
696int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
697 bus_size_t alignment, bus_size_t boundary,
698 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
699 paddr_t low, paddr_t high);
700
701#endif /* _MACHINE_BUS_H_ */