xref: /openbsd/sys/arch/i386/include/bus.h (revision d415bd75)
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  */
77 typedef u_long bus_addr_t;
78 typedef u_long bus_size_t;
79 
80 /*
81  * Access methods for bus resources and address space.
82  */
83 struct	i386_bus_space_ops;
84 typedef	const struct i386_bus_space_ops *bus_space_tag_t;
85 typedef	u_long bus_space_handle_t;
86 
87 int	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 */
90 int	_bus_space_map(bus_space_tag_t t, bus_addr_t addr,
91 	    bus_size_t size, int flags, bus_space_handle_t *bshp);
92 void	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 */
95 void	_bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
96 	    bus_size_t, bus_addr_t *);
97 int	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);
99 paddr_t	bus_space_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
100 
101 int	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);
105 void	bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
106 	    bus_size_t size);
107 
108 struct 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 */
508 extern 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 */
512 extern 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. */
534 struct mbuf;
535 struct proc;
536 struct 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 
546 typedef struct bus_dma_tag		*bus_dma_tag_t;
547 typedef 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  */
555 struct 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 };
566 typedef 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 
575 struct 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  */
649 struct 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 
669 int	_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
670 	    bus_size_t, int, bus_dmamap_t *);
671 void	_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
672 int	_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
673 	    bus_size_t, struct proc *, int);
674 int	_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
675 	    struct mbuf *, int);
676 int	_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
677 	    struct uio *, int);
678 int	_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
679 	    bus_dma_segment_t *, int, bus_size_t, int);
680 void	_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
681 void	_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
682 	    bus_size_t, int);
683 
684 int	_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);
687 void	_bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
688 	    int nsegs);
689 int	_bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
690 	    int nsegs, size_t size, caddr_t *kvap, int flags);
691 void	_bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
692 	    size_t size);
693 paddr_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 
696 int	_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_ */
702