xref: /freebsd/sys/amd64/include/bus.h (revision 0640d357f29fb1c0daaaffadd0416c5981413afd)
1 /*	$NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $	*/
2 
3 /*-
4  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
42  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
43  *
44  * Redistribution and use in source and binary forms, with or without
45  * modification, are permitted provided that the following conditions
46  * are met:
47  * 1. Redistributions of source code must retain the above copyright
48  *    notice, this list of conditions and the following disclaimer.
49  * 2. Redistributions in binary form must reproduce the above copyright
50  *    notice, this list of conditions and the following disclaimer in the
51  *    documentation and/or other materials provided with the distribution.
52  * 3. All advertising materials mentioning features or use of this software
53  *    must display the following acknowledgement:
54  *      This product includes software developed by Christopher G. Demetriou
55  *	for the NetBSD Project.
56  * 4. The name of the author may not be used to endorse or promote products
57  *    derived from this software without specific prior written permission
58  *
59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69  */
70 /* $Id: bus.h,v 1.3 1998/05/06 01:45:47 gibbs Exp $ */
71 
72 #ifndef _I386_BUS_H_
73 #define _I386_BUS_H_
74 
75 #include <machine/cpufunc.h>
76 
77 /*
78  * Values for the i386 bus space tag, not to be used directly by MI code.
79  */
80 #define	I386_BUS_SPACE_IO	0	/* space is i/o space */
81 #define I386_BUS_SPACE_MEM	1	/* space is mem space */
82 
83 /*
84  * Bus address and size types
85  */
86 typedef u_int bus_addr_t;
87 typedef u_int bus_size_t;
88 
89 #define BUS_SPACE_MAXSIZE_24BIT	0xFFFFFF
90 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
91 #define BUS_SPACE_MAXSIZE	(64 * 1024) /* Maximum supported size */
92 #define BUS_SPACE_MAXADDR_24BIT	0xFFFFFF
93 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
94 #define BUS_SPACE_MAXADDR	0xFFFFFFFF
95 
96 #define BUS_SPACE_UNRESTRICTED	(~0)
97 
98 /*
99  * Access methods for bus resources and address space.
100  */
101 typedef	int bus_space_tag_t;
102 typedef	u_int bus_space_handle_t;
103 
104 /*
105  * Map a region of device bus space into CPU virtual address space.
106  */
107 
108 #define	BUS_SPACE_MAP_CACHEABLE		0x01
109 #define	BUS_SPACE_MAP_LINEAR		0x02
110 
111 int	bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
112 		      int flags, bus_space_handle_t *bshp);
113 
114 /*
115  * Unmap a region of device bus space.
116  */
117 
118 void	bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
119 			bus_size_t size);
120 
121 /*
122  * Get a new handle for a subregion of an already-mapped area of bus space.
123  */
124 
125 int	bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
126 			    bus_size_t offset, bus_size_t size,
127 			    bus_space_handle_t *nbshp);
128 
129 /*
130  * Allocate a region of memory that is accessible to devices in bus space.
131  */
132 
133 int	bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
134 			bus_addr_t rend, bus_size_t size, bus_size_t align,
135 			bus_size_t boundary, int flags, bus_addr_t *addrp,
136 			bus_space_handle_t *bshp);
137 
138 /*
139  * Free a region of bus space accessible memory.
140  */
141 
142 void	bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
143 		       bus_size_t size);
144 
145 #if defined(_I386_BUS_PIO_H_) || defined(_I386_BUS_MEMIO_H_)
146 
147 /*
148  * Read a 1, 2, 4, or 8 byte quantity from bus space
149  * described by tag/handle/offset.
150  */
151 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
152 					  bus_space_handle_t handle,
153 					  bus_size_t offset);
154 
155 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
156 					   bus_space_handle_t handle,
157 					   bus_size_t offset);
158 
159 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
160 					   bus_space_handle_t handle,
161 					   bus_size_t offset);
162 
163 static __inline u_int8_t
164 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
165 		 bus_size_t offset)
166 {
167 #if defined (_I386_BUS_PIO_H_)
168 #if defined (_I386_BUS_MEMIO_H_)
169 	if (tag == I386_BUS_SPACE_IO)
170 #endif
171 		return (inb(handle + offset));
172 #endif
173 #if defined (_I386_BUS_MEMIO_H_)
174 	return (*(volatile u_int8_t *)(handle + offset));
175 #endif
176 }
177 
178 static __inline u_int16_t
179 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
180 		 bus_size_t offset)
181 {
182 #if defined(_I386_BUS_PIO_H_)
183 #if defined(_I386_BUS_MEMIO_H_)
184 	if (tag == I386_BUS_SPACE_IO)
185 #endif
186 		return (inw(handle + offset));
187 #endif
188 #if defined(_I386_BUS_MEMIO_H_)
189 	return (*(volatile u_int16_t *)(handle + offset));
190 #endif
191 }
192 
193 static __inline u_int32_t
194 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
195 		 bus_size_t offset)
196 {
197 #if defined(_I386_BUS_PIO_H_)
198 #if defined(_I386_BUS_MEMIO_H_)
199 	if (tag == I386_BUS_SPACE_IO)
200 #endif
201 		return (inl(handle + offset));
202 #endif
203 #if defined(_I386_BUS_MEMIO_H_)
204 	return (*(volatile u_int32_t *)(handle + offset));
205 #endif
206 }
207 
208 #if 0	/* Cause a link error for bus_space_read_8 */
209 #define	bus_space_read_8(t, h, o)	!!! bus_space_read_8 unimplemented !!!
210 #endif
211 
212 /*
213  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
214  * described by tag/handle/offset and copy into buffer provided.
215  */
216 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
217 					    bus_space_handle_t bsh,
218 					    bus_size_t offset, u_int8_t *addr,
219 					    size_t count);
220 
221 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
222 					    bus_space_handle_t bsh,
223 					    bus_size_t offset, u_int16_t *addr,
224 					    size_t count);
225 
226 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
227 					    bus_space_handle_t bsh,
228 					    bus_size_t offset, u_int32_t *addr,
229 					    size_t count);
230 
231 static __inline void
232 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
233 		       bus_size_t offset, u_int8_t *addr, size_t count)
234 {
235 #if defined(_I386_BUS_PIO_H_)
236 #if defined(_I386_BUS_MEMIO_H_)
237 	if (tag == I386_BUS_SPACE_IO)
238 #endif
239 		insb(bsh + offset, addr, count);
240 #endif
241 #if defined(_I386_BUS_MEMIO_H_)
242 #if defined(_I386_BUS_PIO_H_)
243 	else
244 #endif
245 	{
246 		int __x __asm__("%eax");
247 		__asm __volatile("				\n\
248 			cld					\n\
249 		1:	movb (%1),%%al				\n\
250 			stosb					\n\
251 			loop 1b"				:
252 		    "=&a" (__x)					:
253 		    "r" (bsh + offset), "D" (addr), "c" (count)	:
254 		    "%edi", "%ecx", "memory");
255 	}
256 #endif
257 }
258 
259 static __inline void
260 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
261 		       bus_size_t offset, u_int16_t *addr, size_t count)
262 {
263 #if defined(_I386_BUS_PIO_H_)
264 #if defined(_I386_BUS_MEMIO_H_)
265 	if (tag == I386_BUS_SPACE_IO)
266 #endif
267 		insw(bsh + offset, addr, count);
268 #endif
269 #if defined(_I386_BUS_MEMIO_H_)
270 #if defined(_I386_BUS_PIO_H_)
271 	else
272 #endif
273 	{
274 		int __x __asm__("%eax");
275 		__asm __volatile("				\n\
276 			cld					\n\
277 		1:	movw (%1),%%ax				\n\
278 			stosw					\n\
279 			loop 1b"				:
280 		    "=&a" (__x)					:
281 		    "r" (bsh + offset), "D" (addr), "c" (count)	:
282 		    "%edi", "%ecx", "memory");
283 	}
284 #endif
285 }
286 
287 static __inline void
288 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
289 		       bus_size_t offset, u_int32_t *addr, size_t count)
290 {
291 #if defined(_I386_BUS_PIO_H_)
292 #if defined(_I386_BUS_MEMIO_H_)
293 	if (tag == I386_BUS_SPACE_IO)
294 #endif
295 		insl(bsh + offset, addr, count);
296 #endif
297 #if defined(_I386_BUS_MEMIO_H_)
298 #if defined(_I386_BUS_PIO_H_)
299 	else
300 #endif
301 	{
302 		int __x __asm__("%eax");
303 		__asm __volatile("				\n\
304 			cld					\n\
305 		1:	movl (%1),%%eax				\n\
306 			stosl					\n\
307 			loop 1b"				:
308 		    "=&a" (__x)					:
309 		    "r" (bsh + offset), "D" (addr), "c" (count)	:
310 		    "%edi", "%ecx", "memory");
311 	}
312 #endif
313 }
314 
315 #if 0	/* Cause a link error for bus_space_read_multi_8 */
316 #define	bus_space_read_multi_8	!!! bus_space_read_multi_8 unimplemented !!!
317 #endif
318 
319 /*
320  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
321  * described by tag/handle and starting at `offset' and copy into
322  * buffer provided.
323  */
324 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
325 					     bus_space_handle_t bsh,
326 					     bus_size_t offset, u_int8_t *addr,
327 					     size_t count);
328 
329 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
330 					     bus_space_handle_t bsh,
331 					     bus_size_t offset, u_int16_t *addr,
332 					     size_t count);
333 
334 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
335 					     bus_space_handle_t bsh,
336 					     bus_size_t offset, u_int32_t *addr,
337 					     size_t count);
338 
339 
340 static __inline void
341 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
342 			bus_size_t offset, u_int8_t *addr, size_t count)
343 {
344 #if defined(_I386_BUS_PIO_H_)
345 #if defined(_I386_BUS_MEMIO_H_)
346 	if (tag == I386_BUS_SPACE_IO)
347 #endif
348 	{
349 		int __x __asm__("%eax");
350 		__asm __volatile("				\n\
351 			cld					\n\
352 		1:	inb %w1,%%al				\n\
353 			stosb					\n\
354 			incl %1					\n\
355 			loop 1b"				:
356 		    "=&a" (__x)					:
357 		    "d" (bsh + offset), "D" (addr), "c" (count)	:
358 		    "%edx", "%edi", "%ecx", "memory");
359 	}
360 #endif
361 #if defined(_I386_BUS_MEMIO_H_)
362 #if defined(_I386_BUS_PIO_H_)
363 	else
364 #endif
365 	{
366 		__asm __volatile("				\n\
367 			cld					\n\
368 			repne					\n\
369 			movsb"					:
370 								:
371 		    "S" (bsh + offset), "D" (addr), "c" (count)	:
372 		    "%esi", "%edi", "%ecx", "memory");
373 	}
374 #endif
375 }
376 
377 static __inline void
378 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
379 			bus_size_t offset, u_int16_t *addr, size_t count)
380 {
381 #if defined(_I386_BUS_PIO_H_)
382 #if defined(_I386_BUS_MEMIO_H_)
383 	if (tag == I386_BUS_SPACE_IO)
384 #endif
385 	{
386 		int __x __asm__("%eax");
387 		__asm __volatile("				\n\
388 			cld					\n\
389 		1:	inw %w1,%%ax				\n\
390 			stosw					\n\
391 			addl $2,%1				\n\
392 			loop 1b"				:
393 		    "=&a" (__x)					:
394 		    "d" (bsh + offset), "D" (addr), "c" (count)	:
395 		    "%edx", "%edi", "%ecx", "memory");
396 	}
397 #endif
398 #if defined(_I386_BUS_MEMIO_H_)
399 #if defined(_I386_BUS_PIO_H_)
400 	else
401 #endif
402 	{
403 		__asm __volatile("				\n\
404 			cld					\n\
405 			repne					\n\
406 			movsw"					:
407 								:
408 		    "S" (bsh + offset), "D" (addr), "c" (count)	:
409 		    "%esi", "%edi", "%ecx", "memory");
410 	}
411 #endif
412 }
413 
414 static __inline void
415 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
416 			bus_size_t offset, u_int32_t *addr, size_t count)
417 {
418 #if defined(_I386_BUS_PIO_H_)
419 #if defined(_I386_BUS_MEMIO_H_)
420 	if (tag == I386_BUS_SPACE_IO)
421 #endif
422 	{
423 		int __x __asm__("%eax");
424 		__asm __volatile("				\n\
425 			cld					\n\
426 		1:	inl %w1,%%eax				\n\
427 			stosl					\n\
428 			addl $4,%1				\n\
429 			loop 1b"				:
430 		    "=&a" (__x)					:
431 		    "d" (bsh + offset), "D" (addr), "c" (count)	:
432 		    "%edx", "%edi", "%ecx", "memory");
433 	}
434 #endif
435 #if defined(_I386_BUS_MEMIO_H_)
436 #if defined(_I386_BUS_PIO_H_)
437 	else
438 #endif
439 	{
440 		__asm __volatile("				\n\
441 			cld					\n\
442 			repne					\n\
443 			movsl"					:
444 								:
445 		    "S" (bsh + offset), "D" (addr), "c" (count)	:
446 		    "%esi", "%edi", "%ecx", "memory");
447 	}
448 #endif
449 }
450 
451 #if 0	/* Cause a link error for bus_space_read_region_8 */
452 #define	bus_space_read_region_8	!!! bus_space_read_region_8 unimplemented !!!
453 #endif
454 
455 /*
456  * Write the 1, 2, 4, or 8 byte value `value' to bus space
457  * described by tag/handle/offset.
458  */
459 
460 static __inline void bus_space_write_1(bus_space_tag_t tag,
461 				       bus_space_handle_t bsh,
462 				       bus_size_t offset, u_int8_t value);
463 
464 static __inline void bus_space_write_2(bus_space_tag_t tag,
465 				       bus_space_handle_t bsh,
466 				       bus_size_t offset, u_int16_t value);
467 
468 static __inline void bus_space_write_4(bus_space_tag_t tag,
469 				       bus_space_handle_t bsh,
470 				       bus_size_t offset, u_int32_t value);
471 
472 static __inline void
473 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
474 		       bus_size_t offset, u_int8_t value)
475 {
476 #if defined(_I386_BUS_PIO_H_)
477 #if defined(_I386_BUS_MEMIO_H_)
478 	if (tag == I386_BUS_SPACE_IO)
479 #endif
480 		outb(bsh + offset, value);
481 #endif
482 #if defined(_I386_BUS_MEMIO_H_)
483 #if defined(_I386_BUS_PIO_H_)
484 	else
485 #endif
486 		*(volatile u_int8_t *)(bsh + offset) = value;
487 #endif
488 }
489 
490 static __inline void
491 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
492 		       bus_size_t offset, u_int16_t value)
493 {
494 #if defined(_I386_BUS_PIO_H_)
495 #if defined(_I386_BUS_MEMIO_H_)
496 	if (tag == I386_BUS_SPACE_IO)
497 #endif
498 		outw(bsh + offset, value);
499 #endif
500 #if defined(_I386_BUS_MEMIO_H_)
501 #if defined(_I386_BUS_PIO_H_)
502 	else
503 #endif
504 		*(volatile u_int16_t *)(bsh + offset) = value;
505 #endif
506 }
507 
508 static __inline void
509 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
510 		       bus_size_t offset, u_int32_t value)
511 {
512 #if defined(_I386_BUS_PIO_H_)
513 #if defined(_I386_BUS_MEMIO_H_)
514 	if (tag == I386_BUS_SPACE_IO)
515 #endif
516 		outl(bsh + offset, value);
517 #endif
518 #if defined(_I386_BUS_MEMIO_H_)
519 #if defined(_I386_BUS_PIO_H_)
520 	else
521 #endif
522 		*(volatile u_int32_t *)(bsh + offset) = value;
523 #endif
524 }
525 
526 #if 0	/* Cause a link error for bus_space_write_8 */
527 #define	bus_space_write_8	!!! bus_space_write_8 not implemented !!!
528 #endif
529 
530 /*
531  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
532  * provided to bus space described by tag/handle/offset.
533  */
534 
535 static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
536 					     bus_space_handle_t bsh,
537 					     bus_size_t offset,
538 					     const u_int8_t *addr,
539 					     size_t count);
540 static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
541 					     bus_space_handle_t bsh,
542 					     bus_size_t offset,
543 					     const u_int16_t *addr,
544 					     size_t count);
545 
546 static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
547 					     bus_space_handle_t bsh,
548 					     bus_size_t offset,
549 					     const u_int32_t *addr,
550 					     size_t count);
551 
552 static __inline void
553 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
554 			bus_size_t offset, const u_int8_t *addr, size_t count)
555 {
556 #if defined(_I386_BUS_PIO_H_)
557 #if defined(_I386_BUS_MEMIO_H_)
558 	if (tag == I386_BUS_SPACE_IO)
559 #endif
560 		outsb(bsh + offset, addr, count);
561 #endif
562 #if defined(_I386_BUS_MEMIO_H_)
563 #if defined(_I386_BUS_PIO_H_)
564 	else
565 #endif
566 	{
567 		int __x __asm__("%eax");
568 		__asm __volatile("				\n\
569 			cld					\n\
570 		1:	lodsb					\n\
571 			movb %%al,(%1)				\n\
572 			loop 1b"				:
573 		    "=&a" (__x)					:
574 		    "r" (bsh + offset), "S" (addr), "c" (count)	:
575 		    "%esi", "%ecx");
576 	}
577 #endif
578 }
579 
580 static __inline void
581 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
582 			bus_size_t offset, const u_int16_t *addr, size_t count)
583 {
584 #if defined(_I386_BUS_PIO_H_)
585 #if defined(_I386_BUS_MEMIO_H_)
586 	if (tag == I386_BUS_SPACE_IO)
587 #endif
588 		outsw(bsh + offset, addr, count);
589 #endif
590 #if defined(_I386_BUS_MEMIO_H_)
591 #if defined(_I386_BUS_PIO_H_)
592 	else
593 #endif
594 	{
595 		int __x __asm__("%eax");
596 		__asm __volatile("				\n\
597 			cld					\n\
598 		1:	lodsw					\n\
599 			movw %%ax,(%1)				\n\
600 			loop 1b"				:
601 		    "=&a" (__x)					:
602 		    "r" (bsh + offset), "S" (addr), "c" (count)	:
603 		    "%esi", "%ecx");
604 	}
605 #endif
606 }
607 
608 static __inline void
609 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
610 			bus_size_t offset, const u_int32_t *addr, size_t count)
611 {
612 #if defined(_I386_BUS_PIO_H_)
613 #if defined(_I386_BUS_MEMIO_H_)
614 	if (tag == I386_BUS_SPACE_IO)
615 #endif
616 		outsl(bsh + offset, addr, count);
617 #endif
618 #if defined(_I386_BUS_MEMIO_H_)
619 #if defined(_I386_BUS_PIO_H_)
620 	else
621 #endif
622 	{
623 		int __x __asm__("%eax");
624 		__asm __volatile("				\n\
625 			cld					\n\
626 		1:	lodsl					\n\
627 			movl %%eax,(%1)				\n\
628 			loop 1b"				:
629 		    "=&a" (__x)					:
630 		    "r" (bsh + offset), "S" (addr), "c" (count)	:
631 		    "%esi", "%ecx");
632 	}
633 #endif
634 }
635 
636 #if 0	/* Cause a link error for bus_space_write_multi_8 */
637 #define	bus_space_write_multi_8(t, h, o, a, c)				\
638 			!!! bus_space_write_multi_8 unimplemented !!!
639 #endif
640 
641 /*
642  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
643  * to bus space described by tag/handle starting at `offset'.
644  */
645 
646 static __inline void bus_space_write_region_1(bus_space_tag_t tag,
647 					      bus_space_handle_t bsh,
648 					      bus_size_t offset,
649 					      const u_int8_t *addr,
650 					      size_t count);
651 static __inline void bus_space_write_region_2(bus_space_tag_t tag,
652 					      bus_space_handle_t bsh,
653 					      bus_size_t offset,
654 					      const u_int16_t *addr,
655 					      size_t count);
656 static __inline void bus_space_write_region_4(bus_space_tag_t tag,
657 					      bus_space_handle_t bsh,
658 					      bus_size_t offset,
659 					      const u_int32_t *addr,
660 					      size_t count);
661 
662 static __inline void
663 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
664 			 bus_size_t offset, const u_int8_t *addr, size_t count)
665 {
666 #if defined(_I386_BUS_PIO_H_)
667 #if defined(_I386_BUS_MEMIO_H_)
668 	if (tag == I386_BUS_SPACE_IO)
669 #endif
670 	{
671 		int __x __asm__("%eax");
672 		__asm __volatile("				\n\
673 			cld					\n\
674 		1:	lodsb					\n\
675 			outb %%al,%w1				\n\
676 			incl %1					\n\
677 			loop 1b"				:
678 		    "=&a" (__x)					:
679 		    "d" (bsh + offset), "S" (addr), "c" (count)	:
680 		    "%edx", "%esi", "%ecx", "memory");
681 	}
682 #endif
683 #if defined(_I386_BUS_MEMIO_H_)
684 #if defined(_I386_BUS_PIO_H_)
685 	else
686 #endif
687 	{
688 		__asm __volatile("				\n\
689 			cld					\n\
690 			repne					\n\
691 			movsb"					:
692 								:
693 		    "D" (bsh + offset), "S" (addr), "c" (count)	:
694 		    "%edi", "%esi", "%ecx", "memory");
695 	}
696 #endif
697 }
698 
699 static __inline void
700 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
701 			 bus_size_t offset, const u_int16_t *addr, size_t count)
702 {
703 #if defined(_I386_BUS_PIO_H_)
704 #if defined(_I386_BUS_MEMIO_H_)
705 	if (tag == I386_BUS_SPACE_IO)
706 #endif
707 	{
708 		int __x __asm__("%eax");
709 		__asm __volatile("				\n\
710 			cld					\n\
711 		1:	lodsw					\n\
712 			outw %%ax,%w1				\n\
713 			addl $2,%1				\n\
714 			loop 1b"				:
715 		    "=&a" (__x)					:
716 		    "d" (bsh + offset), "S" (addr), "c" (count)	:
717 		    "%edx", "%esi", "%ecx", "memory");
718 	}
719 #endif
720 #if defined(_I386_BUS_MEMIO_H_)
721 #if defined(_I386_BUS_PIO_H_)
722 	else
723 #endif
724 	{
725 		__asm __volatile("				\n\
726 			cld					\n\
727 			repne					\n\
728 			movsw"					:
729 								:
730 		    "D" (bsh + offset), "S" (addr), "c" (count)	:
731 		    "%edi", "%esi", "%ecx", "memory");
732 	}
733 #endif
734 }
735 
736 static __inline void
737 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
738 			 bus_size_t offset, const u_int32_t *addr, size_t count)
739 {
740 #if defined(_I386_BUS_PIO_H_)
741 #if defined(_I386_BUS_MEMIO_H_)
742 	if (tag == I386_BUS_SPACE_IO)
743 #endif
744 	{
745 		int __x __asm__("%eax");
746 		__asm __volatile("				\n\
747 			cld					\n\
748 		1:	lodsl					\n\
749 			outl %%eax,%w1				\n\
750 			addl $4,%1				\n\
751 			loop 1b"				:
752 		    "=&a" (__x)					:
753 		    "d" (bsh + offset), "S" (addr), "c" (count)	:
754 		    "%edx", "%esi", "%ecx", "memory");
755 	}
756 #endif
757 #if defined(_I386_BUS_MEMIO_H_)
758 #if defined(_I386_BUS_PIO_H_)
759 	else
760 #endif
761 	{
762 		__asm __volatile("				\n\
763 			cld					\n\
764 			repne					\n\
765 			movsl"					:
766 								:
767 		    "D" (bsh + offset), "S" (addr), "c" (count)	:
768 		    "%edi", "%esi", "%ecx", "memory");
769 	}
770 #endif
771 }
772 
773 #if 0	/* Cause a link error for bus_space_write_region_8 */
774 #define	bus_space_write_region_8					\
775 			!!! bus_space_write_region_8 unimplemented !!!
776 #endif
777 
778 /*
779  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
780  * by tag/handle/offset `count' times.
781  */
782 
783 static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
784 					   bus_space_handle_t bsh,
785 					   bus_size_t offset,
786 					   u_int8_t value, size_t count);
787 static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
788 					   bus_space_handle_t bsh,
789 					   bus_size_t offset,
790 					   u_int16_t value, size_t count);
791 static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
792 					   bus_space_handle_t bsh,
793 					   bus_size_t offset,
794 					   u_int32_t value, size_t count);
795 
796 static __inline void
797 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
798 		      bus_size_t offset, u_int8_t value, size_t count)
799 {
800 	bus_addr_t addr = bsh + offset;
801 
802 #if defined(_I386_BUS_PIO_H_)
803 #if defined(_I386_BUS_MEMIO_H_)
804 	if (tag == I386_BUS_SPACE_IO)
805 #endif
806 		while (count--)
807 			outb(addr, value);
808 #endif
809 #if defined(_I386_BUS_MEMIO_H_)
810 #if defined(_I386_BUS_PIO_H_)
811 	else
812 #endif
813 		while (count--)
814 			*(volatile u_int8_t *)(addr) = value;
815 #endif
816 }
817 
818 static __inline void
819 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
820 		     bus_size_t offset, u_int16_t value, size_t count)
821 {
822 	bus_addr_t addr = bsh + offset;
823 
824 #if defined(_I386_BUS_PIO_H_)
825 #if defined(_I386_BUS_MEMIO_H_)
826 	if (tag == I386_BUS_SPACE_IO)
827 #endif
828 		while (count--)
829 			outw(addr, value);
830 #endif
831 #if defined(_I386_BUS_MEMIO_H_)
832 #if defined(_I386_BUS_PIO_H_)
833 	else
834 #endif
835 		while (count--)
836 			*(volatile u_int16_t *)(addr) = value;
837 #endif
838 }
839 
840 static __inline void
841 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
842 		      bus_size_t offset, u_int32_t value, size_t count)
843 {
844 	bus_addr_t addr = bsh + offset;
845 
846 #if defined(_I386_BUS_PIO_H_)
847 #if defined(_I386_BUS_MEMIO_H_)
848 	if (tag == I386_BUS_SPACE_IO)
849 #endif
850 		while (count--)
851 			outl(addr, value);
852 #endif
853 #if defined(_I386_BUS_MEMIO_H_)
854 #if defined(_I386_BUS_PIO_H_)
855 	else
856 #endif
857 		while (count--)
858 			*(volatile u_int32_t *)(addr) = value;
859 #endif
860 }
861 
862 #if 0	/* Cause a link error for bus_space_set_multi_8 */
863 #define	bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
864 #endif
865 
866 /*
867  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
868  * by tag/handle starting at `offset'.
869  */
870 
871 static __inline void bus_space_set_region_1(bus_space_tag_t tag,
872 					    bus_space_handle_t bsh,
873 					    bus_size_t offset, u_int8_t value,
874 					    size_t count);
875 static __inline void bus_space_set_region_2(bus_space_tag_t tag,
876 					    bus_space_handle_t bsh,
877 					    bus_size_t offset, u_int16_t value,
878 					    size_t count);
879 static __inline void bus_space_set_region_4(bus_space_tag_t tag,
880 					    bus_space_handle_t bsh,
881 					    bus_size_t offset, u_int32_t value,
882 					    size_t count);
883 
884 static __inline void
885 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
886 		       bus_size_t offset, u_int8_t value, size_t count)
887 {
888 	bus_addr_t addr = bsh + offset;
889 
890 #if defined(_I386_BUS_PIO_H_)
891 #if defined(_I386_BUS_MEMIO_H_)
892 	if (tag == I386_BUS_SPACE_IO)
893 #endif
894 		for (; count != 0; count--, addr++)
895 			outb(addr, value);
896 #endif
897 #if defined(_I386_BUS_MEMIO_H_)
898 #if defined(_I386_BUS_PIO_H_)
899 	else
900 #endif
901 		for (; count != 0; count--, addr++)
902 			*(volatile u_int8_t *)(addr) = value;
903 #endif
904 }
905 
906 static __inline void
907 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
908 		       bus_size_t offset, u_int16_t value, size_t count)
909 {
910 	bus_addr_t addr = bsh + offset;
911 
912 #if defined(_I386_BUS_PIO_H_)
913 #if defined(_I386_BUS_MEMIO_H_)
914 	if (tag == I386_BUS_SPACE_IO)
915 #endif
916 		for (; count != 0; count--, addr += 2)
917 			outw(addr, value);
918 #endif
919 #if defined(_I386_BUS_MEMIO_H_)
920 #if defined(_I386_BUS_PIO_H_)
921 	else
922 #endif
923 		for (; count != 0; count--, addr += 2)
924 			*(volatile u_int16_t *)(addr) = value;
925 #endif
926 }
927 
928 static __inline void
929 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
930 		       bus_size_t offset, u_int32_t value, size_t count)
931 {
932 	bus_addr_t addr = bsh + offset;
933 
934 #if defined(_I386_BUS_PIO_H_)
935 #if defined(_I386_BUS_MEMIO_H_)
936 	if (tag == I386_BUS_SPACE_IO)
937 #endif
938 		for (; count != 0; count--, addr += 4)
939 			outl(addr, value);
940 #endif
941 #if defined(_I386_BUS_MEMIO_H_)
942 #if defined(_I386_BUS_PIO_H_)
943 	else
944 #endif
945 		for (; count != 0; count--, addr += 4)
946 			*(volatile u_int32_t *)(addr) = value;
947 #endif
948 }
949 
950 #if 0	/* Cause a link error for bus_space_set_region_8 */
951 #define	bus_space_set_region_8	!!! bus_space_set_region_8 unimplemented !!!
952 #endif
953 
954 /*
955  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
956  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
957  */
958 
959 static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
960 					     bus_space_handle_t bsh1,
961 					     bus_size_t off1,
962 					     bus_space_handle_t bsh2,
963 					     bus_size_t off2, size_t count);
964 
965 static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
966 					     bus_space_handle_t bsh1,
967 					     bus_size_t off1,
968 					     bus_space_handle_t bsh2,
969 					     bus_size_t off2, size_t count);
970 
971 static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
972 					     bus_space_handle_t bsh1,
973 					     bus_size_t off1,
974 					     bus_space_handle_t bsh2,
975 					     bus_size_t off2, size_t count);
976 
977 static __inline void
978 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
979 			bus_size_t off1, bus_space_handle_t bsh2,
980 			bus_size_t off2, size_t count)
981 {
982 	bus_addr_t addr1 = bsh1 + off1;
983 	bus_addr_t addr2 = bsh2 + off2;
984 
985 #if defined(_I386_BUS_PIO_H_)
986 #if defined(_I386_BUS_MEMIO_H_)
987 	if (tag == I386_BUS_SPACE_IO)
988 #endif
989 	{
990 		if (addr1 >= addr2) {
991 			/* src after dest: copy forward */
992 			for (; count != 0; count--, addr1++, addr2++)
993 				outb(addr2, inb(addr1));
994 		} else {
995 			/* dest after src: copy backwards */
996 			for (addr1 += (count - 1), addr2 += (count - 1);
997 			    count != 0; count--, addr1--, addr2--)
998 				outb(addr2, inb(addr1));
999 		}
1000 	}
1001 #endif
1002 #if defined(_I386_BUS_MEMIO_H_)
1003 #if defined(_I386_BUS_PIO_H_)
1004 	else
1005 #endif
1006 	{
1007 		if (addr1 >= addr2) {
1008 			/* src after dest: copy forward */
1009 			for (; count != 0; count--, addr1++, addr2++)
1010 				*(volatile u_int8_t *)(addr2) =
1011 				    *(volatile u_int8_t *)(addr1);
1012 		} else {
1013 			/* dest after src: copy backwards */
1014 			for (addr1 += (count - 1), addr2 += (count - 1);
1015 			    count != 0; count--, addr1--, addr2--)
1016 				*(volatile u_int8_t *)(addr2) =
1017 				    *(volatile u_int8_t *)(addr1);
1018 		}
1019 	}
1020 #endif
1021 }
1022 
1023 static __inline void
1024 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
1025 			bus_size_t off1, bus_space_handle_t bsh2,
1026 			bus_size_t off2, size_t count)
1027 {
1028 	bus_addr_t addr1 = bsh1 + off1;
1029 	bus_addr_t addr2 = bsh2 + off2;
1030 
1031 #if defined(_I386_BUS_PIO_H_)
1032 #if defined(_I386_BUS_MEMIO_H_)
1033 	if (tag == I386_BUS_SPACE_IO)
1034 #endif
1035 	{
1036 		if (addr1 >= addr2) {
1037 			/* src after dest: copy forward */
1038 			for (; count != 0; count--, addr1 += 2, addr2 += 2)
1039 				outw(addr2, inw(addr1));
1040 		} else {
1041 			/* dest after src: copy backwards */
1042 			for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
1043 			    count != 0; count--, addr1 -= 2, addr2 -= 2)
1044 				outw(addr2, inw(addr1));
1045 		}
1046 	}
1047 #endif
1048 #if defined(_I386_BUS_MEMIO_H_)
1049 #if defined(_I386_BUS_PIO_H_)
1050 	else
1051 #endif
1052 	{
1053 		if (addr1 >= addr2) {
1054 			/* src after dest: copy forward */
1055 			for (; count != 0; count--, addr1 += 2, addr2 += 2)
1056 				*(volatile u_int16_t *)(addr2) =
1057 				    *(volatile u_int16_t *)(addr1);
1058 		} else {
1059 			/* dest after src: copy backwards */
1060 			for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
1061 			    count != 0; count--, addr1 -= 2, addr2 -= 2)
1062 				*(volatile u_int16_t *)(addr2) =
1063 				    *(volatile u_int16_t *)(addr1);
1064 		}
1065 	}
1066 #endif
1067 }
1068 
1069 static __inline void
1070 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
1071 			bus_size_t off1, bus_space_handle_t bsh2,
1072 			bus_size_t off2, size_t count)
1073 {
1074 	bus_addr_t addr1 = bsh1 + off1;
1075 	bus_addr_t addr2 = bsh2 + off2;
1076 
1077 #if defined(_I386_BUS_PIO_H_)
1078 #if defined(_I386_BUS_MEMIO_H_)
1079 	if (tag == I386_BUS_SPACE_IO)
1080 #endif
1081 	{
1082 		if (addr1 >= addr2) {
1083 			/* src after dest: copy forward */
1084 			for (; count != 0; count--, addr1 += 4, addr2 += 4)
1085 				outl(addr2, inl(addr1));
1086 		} else {
1087 			/* dest after src: copy backwards */
1088 			for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
1089 			    count != 0; count--, addr1 -= 4, addr2 -= 4)
1090 				outl(addr2, inl(addr1));
1091 		}
1092 	}
1093 #endif
1094 #if defined(_I386_BUS_MEMIO_H_)
1095 #if defined(_I386_BUS_PIO_H_)
1096 	else
1097 #endif
1098 	{
1099 		if (addr1 >= addr2) {
1100 			/* src after dest: copy forward */
1101 			for (; count != 0; count--, addr1 += 4, addr2 += 4)
1102 				*(volatile u_int32_t *)(addr2) =
1103 				    *(volatile u_int32_t *)(addr1);
1104 		} else {
1105 			/* dest after src: copy backwards */
1106 			for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
1107 			    count != 0; count--, addr1 -= 4, addr2 -= 4)
1108 				*(volatile u_int32_t *)(addr2) =
1109 				    *(volatile u_int32_t *)(addr1);
1110 		}
1111 	}
1112 #endif
1113 }
1114 
1115 #endif /* defined(_I386_BUS_PIO_H_) || defined(_I386_MEM_IO_H_) */
1116 
1117 #if 0	/* Cause a link error for bus_space_copy_8 */
1118 #define	bus_space_copy_region_8	!!! bus_space_copy_region_8 unimplemented !!!
1119 #endif
1120 
1121 /*
1122  * Bus read/write barrier methods.
1123  *
1124  *	void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
1125  *			       bus_size_t offset, bus_size_t len, int flags);
1126  *
1127  * Note: the i386 does not currently require barriers, but we must
1128  * provide the flags to MI code.
1129  */
1130 #define	bus_space_barrier(t, h, o, l, f)	\
1131 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
1132 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
1133 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
1134 
1135 /*
1136  * Flags used in various bus DMA methods.
1137  */
1138 #define	BUS_DMA_WAITOK		0x00	/* safe to sleep (pseudo-flag) */
1139 #define	BUS_DMA_NOWAIT		0x01	/* not safe to sleep */
1140 #define	BUS_DMA_ALLOCNOW	0x02	/* perform resource allocation now */
1141 #define	BUS_DMAMEM_NOSYNC	0x04	/* map memory to not require sync */
1142 #define	BUS_DMA_BUS1		0x10	/* placeholders for bus functions... */
1143 #define	BUS_DMA_BUS2		0x20
1144 #define	BUS_DMA_BUS3		0x40
1145 #define	BUS_DMA_BUS4		0x80
1146 
1147 /* Forwards needed by prototypes below. */
1148 struct mbuf;
1149 struct uio;
1150 
1151 /*
1152  *	bus_dmasync_op_t
1153  *
1154  *	Operations performed by bus_dmamap_sync().
1155  */
1156 typedef enum {
1157 	BUS_DMASYNC_PREREAD,
1158 	BUS_DMASYNC_POSTREAD,
1159 	BUS_DMASYNC_PREWRITE,
1160 	BUS_DMASYNC_POSTWRITE
1161 } bus_dmasync_op_t;
1162 
1163 /*
1164  *	bus_dma_tag_t
1165  *
1166  *	A machine-dependent opaque type describing the characteristics
1167  *	of how to perform DMA mappings.  This structure encapsultes
1168  *	information concerning address and alignment restrictions, number
1169  *	of S/G	segments, amount of data per S/G segment, etc.
1170  */
1171 typedef struct bus_dma_tag	*bus_dma_tag_t;
1172 
1173 /*
1174  *	bus_dmamap_t
1175  *
1176  *	DMA mapping instance information.
1177  */
1178 typedef struct bus_dmamap	*bus_dmamap_t;
1179 
1180 /*
1181  *	bus_dma_segment_t
1182  *
1183  *	Describes a single contiguous DMA transaction.  Values
1184  *	are suitable for programming into DMA registers.
1185  */
1186 typedef struct bus_dma_segment {
1187 	bus_addr_t	ds_addr;	/* DMA address */
1188 	bus_size_t	ds_len;		/* length of transfer */
1189 } bus_dma_segment_t;
1190 
1191 /*
1192  * A function that returns 1 if the address cannot be accessed by
1193  * a device and 0 if it can be.
1194  */
1195 typedef int bus_dma_filter_t(void *, bus_addr_t);
1196 
1197 /*
1198  * Allocate a device specific dma_tag encapsulating the constraints of
1199  * the parent tag in addition to other restrictions specified:
1200  *
1201  *	alignment:	alignment for segments.
1202  *	boundary:	Boundary that segments cannot cross.
1203  *	lowaddr:	Low restricted address that cannot appear in a mapping.
1204  *	highaddr:	High restricted address that cannot appear in a mapping.
1205  *	filtfunc:	An optional function to further test if an address
1206  *			within the range of lowaddr and highaddr cannot appear
1207  *			in a mapping.
1208  *	filtfuncarg:	An argument that will be passed to filtfunc in addition
1209  *			to the address to test.
1210  *	maxsize:	Maximum mapping size supported by this tag.
1211  *	nsegments:	Number of discontinuities allowed in maps.
1212  *	maxsegsz:	Maximum size of a segment in the map.
1213  *	flags:		Bus DMA flags.
1214  *	dmat:		A pointer to set to a valid dma tag should the return
1215  *			value of this function indicate success.
1216  */
1217 /* XXX Should probably allow specification of alignment */
1218 int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignemnt,
1219 		       bus_size_t boundary, bus_addr_t lowaddr,
1220 		       bus_addr_t highaddr, bus_dma_filter_t *filtfunc,
1221 		       void *filtfuncarg, bus_size_t maxsize, int nsegments,
1222 		       bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat);
1223 
1224 int bus_dma_tag_destroy(bus_dma_tag_t dmat);
1225 
1226 /*
1227  * Allocate a handle for mapping from kva/uva/physical
1228  * address space into bus device space.
1229  */
1230 int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp);
1231 
1232 /*
1233  * Destroy  a handle for mapping from kva/uva/physical
1234  * address space into bus device space.
1235  */
1236 int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map);
1237 
1238 /*
1239  * Allocate a piece of memory that can be efficiently mapped into
1240  * bus device space based on the constraints lited in the dma tag.
1241  * A dmamap to for use with dmamap_load is also allocated.
1242  */
1243 int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
1244 		     bus_dmamap_t *mapp);
1245 
1246 /*
1247  * Free a piece of memory and it's allociated dmamap, that was allocated
1248  * via bus_dmamem_alloc.
1249  */
1250 void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map);
1251 
1252 /*
1253  * A function that processes a successfully loaded dma map or an error
1254  * from a delayed load map.
1255  */
1256 typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
1257 
1258 /*
1259  * Map the buffer buf into bus space using the dmamap map.
1260  */
1261 int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
1262 		    bus_size_t buflen, bus_dmamap_callback_t *callback,
1263 		    void *callback_arg, int flags);
1264 
1265 /*
1266  * Perform a syncronization operation on the given map.
1267  */
1268 void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t);
1269 #define bus_dmamap_sync(dmat, dmamap, op) 		\
1270 	if ((dmamap) != NULL)				\
1271 		_bus_dmamap_sync(dmat, dmamap, op)
1272 
1273 /*
1274  * Release the mapping held by map.
1275  */
1276 void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map);
1277 #define bus_dmamap_unload(dmat, dmamap) 		\
1278 	if ((dmamap) != NULL)				\
1279 		_bus_dmamap_unload(dmat, dmamap)
1280 
1281 #endif /* _I386_BUS_H_ */
1282