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