bus_dma.h revision 60672
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: head/sys/sys/bus_dma.h 60672 2000-05-18 00:06:10Z msmith $ */
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 */
95typedef u_int bus_addr_t;
96typedef 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 */
110typedef	int bus_space_tag_t;
111typedef	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
120int	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
127void	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
134int	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
142int	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
151void	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 */
160static __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
164static __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
168static __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
172static __inline u_int8_t
173bus_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
187static __inline u_int16_t
188bus_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
202static __inline u_int32_t
203bus_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 */
225static __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
230static __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
235static __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
240static __inline void
241bus_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
267static __inline void
268bus_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
294static __inline void
295bus_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 */
330static __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
335static __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
340static __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
346static __inline void
347bus_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
384static __inline void
385bus_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
422static __inline void
423bus_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
469static __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
473static __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
477static __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
481static __inline void
482bus_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
499static __inline void
500bus_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
517static __inline void
518bus_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
544static __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);
549static __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
555static __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
561static __inline void
562bus_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
588static __inline void
589bus_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,(%1)				\n\
607			movw %%ax,(%2)				\n\
608			loop 1b"				:
609		    "=S" (addr), "=c" (count)			:
610		    "r" (bsh + offset), "0" (addr), "1" (count)	:
611		    "%eax", "memory", "cc");
612	}
613#endif
614}
615
616static __inline void
617bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
618			bus_size_t offset, const u_int32_t *addr, size_t count)
619{
620#if defined(_I386_BUS_PIO_H_)
621#if defined(_I386_BUS_MEMIO_H_)
622	if (tag == I386_BUS_SPACE_IO)
623#endif
624		outsl(bsh + offset, addr, count);
625#endif
626#if defined(_I386_BUS_MEMIO_H_)
627#if defined(_I386_BUS_PIO_H_)
628	else
629#endif
630	{
631		__asm __volatile("				\n\
632			cld					\n\
633		1:	lodsl					\n\
634			movl %%eax,(%2)				\n\
635			loop 1b"				:
636		    "=S" (addr), "=c" (count)			:
637		    "r" (bsh + offset), "0" (addr), "1" (count)	:
638		    "%eax", "memory", "cc");
639	}
640#endif
641}
642
643#if 0	/* Cause a link error for bus_space_write_multi_8 */
644#define	bus_space_write_multi_8(t, h, o, a, c)				\
645			!!! bus_space_write_multi_8 unimplemented !!!
646#endif
647
648/*
649 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
650 * to bus space described by tag/handle starting at `offset'.
651 */
652
653static __inline void bus_space_write_region_1(bus_space_tag_t tag,
654					      bus_space_handle_t bsh,
655					      bus_size_t offset,
656					      const u_int8_t *addr,
657					      size_t count);
658static __inline void bus_space_write_region_2(bus_space_tag_t tag,
659					      bus_space_handle_t bsh,
660					      bus_size_t offset,
661					      const u_int16_t *addr,
662					      size_t count);
663static __inline void bus_space_write_region_4(bus_space_tag_t tag,
664					      bus_space_handle_t bsh,
665					      bus_size_t offset,
666					      const u_int32_t *addr,
667					      size_t count);
668
669static __inline void
670bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
671			 bus_size_t offset, const u_int8_t *addr, size_t count)
672{
673#if defined(_I386_BUS_PIO_H_)
674#if defined(_I386_BUS_MEMIO_H_)
675	if (tag == I386_BUS_SPACE_IO)
676#endif
677	{
678		int _port_ = bsh + offset;			\
679		__asm __volatile("				\n\
680			cld					\n\
681		1:	lodsb					\n\
682			outb %%al,%w0				\n\
683			incl %0					\n\
684			loop 1b"				:
685		    "=d" (_port_), "=S" (addr), "=c" (count)	:
686		    "0" (_port_), "1" (addr), "2" (count)	:
687		    "%eax", "memory", "cc");
688	}
689#endif
690#if defined(_I386_BUS_MEMIO_H_)
691#if defined(_I386_BUS_PIO_H_)
692	else
693#endif
694	{
695		int _port_ = bsh + offset;			\
696		__asm __volatile("				\n\
697			cld					\n\
698			repne					\n\
699			movsb"					:
700		    "=D" (_port_), "=S" (addr), "=c" (count)	:
701		    "0" (_port_), "1" (addr), "2" (count)	:
702		    "memory", "cc");
703	}
704#endif
705}
706
707static __inline void
708bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
709			 bus_size_t offset, const u_int16_t *addr, size_t count)
710{
711#if defined(_I386_BUS_PIO_H_)
712#if defined(_I386_BUS_MEMIO_H_)
713	if (tag == I386_BUS_SPACE_IO)
714#endif
715	{
716		int _port_ = bsh + offset;			\
717		__asm __volatile("				\n\
718			cld					\n\
719		1:	lodsw					\n\
720			outw %%ax,%w0				\n\
721			addl $2,%0				\n\
722			loop 1b"				:
723		    "=d" (_port_), "=S" (addr), "=c" (count)	:
724		    "0" (_port_), "1" (addr), "2" (count)	:
725		    "%eax", "memory", "cc");
726	}
727#endif
728#if defined(_I386_BUS_MEMIO_H_)
729#if defined(_I386_BUS_PIO_H_)
730	else
731#endif
732	{
733		int _port_ = bsh + offset;			\
734		__asm __volatile("				\n\
735			cld					\n\
736			repne					\n\
737			movsw"					:
738		    "=D" (_port_), "=S" (addr), "=c" (count)	:
739		    "0" (_port_), "1" (addr), "2" (count)	:
740		    "memory", "cc");
741	}
742#endif
743}
744
745static __inline void
746bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
747			 bus_size_t offset, const u_int32_t *addr, size_t count)
748{
749#if defined(_I386_BUS_PIO_H_)
750#if defined(_I386_BUS_MEMIO_H_)
751	if (tag == I386_BUS_SPACE_IO)
752#endif
753	{
754		int _port_ = bsh + offset;			\
755		__asm __volatile("				\n\
756			cld					\n\
757		1:	lodsl					\n\
758			outl %%eax,%w0				\n\
759			addl $4,%0				\n\
760			loop 1b"				:
761		    "=d" (_port_), "=S" (addr), "=c" (count)	:
762		    "0" (_port_), "1" (addr), "2" (count)	:
763		    "%eax", "memory", "cc");
764	}
765#endif
766#if defined(_I386_BUS_MEMIO_H_)
767#if defined(_I386_BUS_PIO_H_)
768	else
769#endif
770	{
771		int _port_ = bsh + offset;			\
772		__asm __volatile("				\n\
773			cld					\n\
774			repne					\n\
775			movsl"					:
776		    "=D" (_port_), "=S" (addr), "=c" (count)	:
777		    "0" (_port_), "1" (addr), "2" (count)	:
778		    "memory", "cc");
779	}
780#endif
781}
782
783#if 0	/* Cause a link error for bus_space_write_region_8 */
784#define	bus_space_write_region_8					\
785			!!! bus_space_write_region_8 unimplemented !!!
786#endif
787
788/*
789 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
790 * by tag/handle/offset `count' times.
791 */
792
793static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
794					   bus_space_handle_t bsh,
795					   bus_size_t offset,
796					   u_int8_t value, size_t count);
797static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
798					   bus_space_handle_t bsh,
799					   bus_size_t offset,
800					   u_int16_t value, size_t count);
801static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
802					   bus_space_handle_t bsh,
803					   bus_size_t offset,
804					   u_int32_t value, size_t count);
805
806static __inline void
807bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
808		      bus_size_t offset, u_int8_t value, size_t count)
809{
810	bus_addr_t addr = bsh + offset;
811
812#if defined(_I386_BUS_PIO_H_)
813#if defined(_I386_BUS_MEMIO_H_)
814	if (tag == I386_BUS_SPACE_IO)
815#endif
816		while (count--)
817			outb(addr, value);
818#endif
819#if defined(_I386_BUS_MEMIO_H_)
820#if defined(_I386_BUS_PIO_H_)
821	else
822#endif
823		while (count--)
824			*(volatile u_int8_t *)(addr) = value;
825#endif
826}
827
828static __inline void
829bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
830		     bus_size_t offset, u_int16_t value, size_t count)
831{
832	bus_addr_t addr = bsh + offset;
833
834#if defined(_I386_BUS_PIO_H_)
835#if defined(_I386_BUS_MEMIO_H_)
836	if (tag == I386_BUS_SPACE_IO)
837#endif
838		while (count--)
839			outw(addr, value);
840#endif
841#if defined(_I386_BUS_MEMIO_H_)
842#if defined(_I386_BUS_PIO_H_)
843	else
844#endif
845		while (count--)
846			*(volatile u_int16_t *)(addr) = value;
847#endif
848}
849
850static __inline void
851bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
852		      bus_size_t offset, u_int32_t value, size_t count)
853{
854	bus_addr_t addr = bsh + offset;
855
856#if defined(_I386_BUS_PIO_H_)
857#if defined(_I386_BUS_MEMIO_H_)
858	if (tag == I386_BUS_SPACE_IO)
859#endif
860		while (count--)
861			outl(addr, value);
862#endif
863#if defined(_I386_BUS_MEMIO_H_)
864#if defined(_I386_BUS_PIO_H_)
865	else
866#endif
867		while (count--)
868			*(volatile u_int32_t *)(addr) = value;
869#endif
870}
871
872#if 0	/* Cause a link error for bus_space_set_multi_8 */
873#define	bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
874#endif
875
876/*
877 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
878 * by tag/handle starting at `offset'.
879 */
880
881static __inline void bus_space_set_region_1(bus_space_tag_t tag,
882					    bus_space_handle_t bsh,
883					    bus_size_t offset, u_int8_t value,
884					    size_t count);
885static __inline void bus_space_set_region_2(bus_space_tag_t tag,
886					    bus_space_handle_t bsh,
887					    bus_size_t offset, u_int16_t value,
888					    size_t count);
889static __inline void bus_space_set_region_4(bus_space_tag_t tag,
890					    bus_space_handle_t bsh,
891					    bus_size_t offset, u_int32_t value,
892					    size_t count);
893
894static __inline void
895bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
896		       bus_size_t offset, u_int8_t value, size_t count)
897{
898	bus_addr_t addr = bsh + offset;
899
900#if defined(_I386_BUS_PIO_H_)
901#if defined(_I386_BUS_MEMIO_H_)
902	if (tag == I386_BUS_SPACE_IO)
903#endif
904		for (; count != 0; count--, addr++)
905			outb(addr, value);
906#endif
907#if defined(_I386_BUS_MEMIO_H_)
908#if defined(_I386_BUS_PIO_H_)
909	else
910#endif
911		for (; count != 0; count--, addr++)
912			*(volatile u_int8_t *)(addr) = value;
913#endif
914}
915
916static __inline void
917bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
918		       bus_size_t offset, u_int16_t value, size_t count)
919{
920	bus_addr_t addr = bsh + offset;
921
922#if defined(_I386_BUS_PIO_H_)
923#if defined(_I386_BUS_MEMIO_H_)
924	if (tag == I386_BUS_SPACE_IO)
925#endif
926		for (; count != 0; count--, addr += 2)
927			outw(addr, value);
928#endif
929#if defined(_I386_BUS_MEMIO_H_)
930#if defined(_I386_BUS_PIO_H_)
931	else
932#endif
933		for (; count != 0; count--, addr += 2)
934			*(volatile u_int16_t *)(addr) = value;
935#endif
936}
937
938static __inline void
939bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
940		       bus_size_t offset, u_int32_t value, size_t count)
941{
942	bus_addr_t addr = bsh + offset;
943
944#if defined(_I386_BUS_PIO_H_)
945#if defined(_I386_BUS_MEMIO_H_)
946	if (tag == I386_BUS_SPACE_IO)
947#endif
948		for (; count != 0; count--, addr += 4)
949			outl(addr, value);
950#endif
951#if defined(_I386_BUS_MEMIO_H_)
952#if defined(_I386_BUS_PIO_H_)
953	else
954#endif
955		for (; count != 0; count--, addr += 4)
956			*(volatile u_int32_t *)(addr) = value;
957#endif
958}
959
960#if 0	/* Cause a link error for bus_space_set_region_8 */
961#define	bus_space_set_region_8	!!! bus_space_set_region_8 unimplemented !!!
962#endif
963
964/*
965 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
966 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
967 */
968
969static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
970					     bus_space_handle_t bsh1,
971					     bus_size_t off1,
972					     bus_space_handle_t bsh2,
973					     bus_size_t off2, size_t count);
974
975static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
976					     bus_space_handle_t bsh1,
977					     bus_size_t off1,
978					     bus_space_handle_t bsh2,
979					     bus_size_t off2, size_t count);
980
981static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
982					     bus_space_handle_t bsh1,
983					     bus_size_t off1,
984					     bus_space_handle_t bsh2,
985					     bus_size_t off2, size_t count);
986
987static __inline void
988bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
989			bus_size_t off1, bus_space_handle_t bsh2,
990			bus_size_t off2, size_t count)
991{
992	bus_addr_t addr1 = bsh1 + off1;
993	bus_addr_t addr2 = bsh2 + off2;
994
995#if defined(_I386_BUS_PIO_H_)
996#if defined(_I386_BUS_MEMIO_H_)
997	if (tag == I386_BUS_SPACE_IO)
998#endif
999	{
1000		if (addr1 >= addr2) {
1001			/* src after dest: copy forward */
1002			for (; count != 0; count--, addr1++, addr2++)
1003				outb(addr2, inb(addr1));
1004		} else {
1005			/* dest after src: copy backwards */
1006			for (addr1 += (count - 1), addr2 += (count - 1);
1007			    count != 0; count--, addr1--, addr2--)
1008				outb(addr2, inb(addr1));
1009		}
1010	}
1011#endif
1012#if defined(_I386_BUS_MEMIO_H_)
1013#if defined(_I386_BUS_PIO_H_)
1014	else
1015#endif
1016	{
1017		if (addr1 >= addr2) {
1018			/* src after dest: copy forward */
1019			for (; count != 0; count--, addr1++, addr2++)
1020				*(volatile u_int8_t *)(addr2) =
1021				    *(volatile u_int8_t *)(addr1);
1022		} else {
1023			/* dest after src: copy backwards */
1024			for (addr1 += (count - 1), addr2 += (count - 1);
1025			    count != 0; count--, addr1--, addr2--)
1026				*(volatile u_int8_t *)(addr2) =
1027				    *(volatile u_int8_t *)(addr1);
1028		}
1029	}
1030#endif
1031}
1032
1033static __inline void
1034bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
1035			bus_size_t off1, bus_space_handle_t bsh2,
1036			bus_size_t off2, size_t count)
1037{
1038	bus_addr_t addr1 = bsh1 + off1;
1039	bus_addr_t addr2 = bsh2 + off2;
1040
1041#if defined(_I386_BUS_PIO_H_)
1042#if defined(_I386_BUS_MEMIO_H_)
1043	if (tag == I386_BUS_SPACE_IO)
1044#endif
1045	{
1046		if (addr1 >= addr2) {
1047			/* src after dest: copy forward */
1048			for (; count != 0; count--, addr1 += 2, addr2 += 2)
1049				outw(addr2, inw(addr1));
1050		} else {
1051			/* dest after src: copy backwards */
1052			for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
1053			    count != 0; count--, addr1 -= 2, addr2 -= 2)
1054				outw(addr2, inw(addr1));
1055		}
1056	}
1057#endif
1058#if defined(_I386_BUS_MEMIO_H_)
1059#if defined(_I386_BUS_PIO_H_)
1060	else
1061#endif
1062	{
1063		if (addr1 >= addr2) {
1064			/* src after dest: copy forward */
1065			for (; count != 0; count--, addr1 += 2, addr2 += 2)
1066				*(volatile u_int16_t *)(addr2) =
1067				    *(volatile u_int16_t *)(addr1);
1068		} else {
1069			/* dest after src: copy backwards */
1070			for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
1071			    count != 0; count--, addr1 -= 2, addr2 -= 2)
1072				*(volatile u_int16_t *)(addr2) =
1073				    *(volatile u_int16_t *)(addr1);
1074		}
1075	}
1076#endif
1077}
1078
1079static __inline void
1080bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
1081			bus_size_t off1, bus_space_handle_t bsh2,
1082			bus_size_t off2, size_t count)
1083{
1084	bus_addr_t addr1 = bsh1 + off1;
1085	bus_addr_t addr2 = bsh2 + off2;
1086
1087#if defined(_I386_BUS_PIO_H_)
1088#if defined(_I386_BUS_MEMIO_H_)
1089	if (tag == I386_BUS_SPACE_IO)
1090#endif
1091	{
1092		if (addr1 >= addr2) {
1093			/* src after dest: copy forward */
1094			for (; count != 0; count--, addr1 += 4, addr2 += 4)
1095				outl(addr2, inl(addr1));
1096		} else {
1097			/* dest after src: copy backwards */
1098			for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
1099			    count != 0; count--, addr1 -= 4, addr2 -= 4)
1100				outl(addr2, inl(addr1));
1101		}
1102	}
1103#endif
1104#if defined(_I386_BUS_MEMIO_H_)
1105#if defined(_I386_BUS_PIO_H_)
1106	else
1107#endif
1108	{
1109		if (addr1 >= addr2) {
1110			/* src after dest: copy forward */
1111			for (; count != 0; count--, addr1 += 4, addr2 += 4)
1112				*(volatile u_int32_t *)(addr2) =
1113				    *(volatile u_int32_t *)(addr1);
1114		} else {
1115			/* dest after src: copy backwards */
1116			for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
1117			    count != 0; count--, addr1 -= 4, addr2 -= 4)
1118				*(volatile u_int32_t *)(addr2) =
1119				    *(volatile u_int32_t *)(addr1);
1120		}
1121	}
1122#endif
1123}
1124
1125#endif /* defined(_I386_BUS_PIO_H_) || defined(_I386_MEM_IO_H_) */
1126
1127#if 0	/* Cause a link error for bus_space_copy_8 */
1128#define	bus_space_copy_region_8	!!! bus_space_copy_region_8 unimplemented !!!
1129#endif
1130
1131/*
1132 * Bus read/write barrier methods.
1133 *
1134 *	void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
1135 *			       bus_size_t offset, bus_size_t len, int flags);
1136 *
1137 *
1138 * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
1139 * prevent reordering by the compiler; all Intel x86 processors currently
1140 * retire operations outside the CPU in program order.
1141 */
1142#define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
1143#define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
1144
1145static __inline void
1146bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
1147		  bus_size_t offset, bus_size_t len, int flags)
1148{
1149	if (flags & BUS_SPACE_BARRIER_READ)
1150		__asm __volatile ("lock; addl $0,0(%esp)" : : : "memory");
1151	else
1152		__asm __volatile ("" : : : "memory");
1153}
1154
1155
1156/*
1157 * Flags used in various bus DMA methods.
1158 */
1159#define	BUS_DMA_WAITOK		0x00	/* safe to sleep (pseudo-flag) */
1160#define	BUS_DMA_NOWAIT		0x01	/* not safe to sleep */
1161#define	BUS_DMA_ALLOCNOW	0x02	/* perform resource allocation now */
1162#define	BUS_DMAMEM_NOSYNC	0x04	/* map memory to not require sync */
1163#define	BUS_DMA_BUS1		0x10	/* placeholders for bus functions... */
1164#define	BUS_DMA_BUS2		0x20
1165#define	BUS_DMA_BUS3		0x40
1166#define	BUS_DMA_BUS4		0x80
1167
1168/* Forwards needed by prototypes below. */
1169struct mbuf;
1170struct uio;
1171
1172/*
1173 *	bus_dmasync_op_t
1174 *
1175 *	Operations performed by bus_dmamap_sync().
1176 */
1177typedef enum {
1178	BUS_DMASYNC_PREREAD,
1179	BUS_DMASYNC_POSTREAD,
1180	BUS_DMASYNC_PREWRITE,
1181	BUS_DMASYNC_POSTWRITE
1182} bus_dmasync_op_t;
1183
1184/*
1185 *	bus_dma_tag_t
1186 *
1187 *	A machine-dependent opaque type describing the characteristics
1188 *	of how to perform DMA mappings.  This structure encapsultes
1189 *	information concerning address and alignment restrictions, number
1190 *	of S/G	segments, amount of data per S/G segment, etc.
1191 */
1192typedef struct bus_dma_tag	*bus_dma_tag_t;
1193
1194/*
1195 *	bus_dmamap_t
1196 *
1197 *	DMA mapping instance information.
1198 */
1199typedef struct bus_dmamap	*bus_dmamap_t;
1200
1201/*
1202 *	bus_dma_segment_t
1203 *
1204 *	Describes a single contiguous DMA transaction.  Values
1205 *	are suitable for programming into DMA registers.
1206 */
1207typedef struct bus_dma_segment {
1208	bus_addr_t	ds_addr;	/* DMA address */
1209	bus_size_t	ds_len;		/* length of transfer */
1210} bus_dma_segment_t;
1211
1212/*
1213 * A function that returns 1 if the address cannot be accessed by
1214 * a device and 0 if it can be.
1215 */
1216typedef int bus_dma_filter_t(void *, bus_addr_t);
1217
1218/*
1219 * Allocate a device specific dma_tag encapsulating the constraints of
1220 * the parent tag in addition to other restrictions specified:
1221 *
1222 *	alignment:	alignment for segments.
1223 *	boundary:	Boundary that segments cannot cross.
1224 *	lowaddr:	Low restricted address that cannot appear in a mapping.
1225 *	highaddr:	High restricted address that cannot appear in a mapping.
1226 *	filtfunc:	An optional function to further test if an address
1227 *			within the range of lowaddr and highaddr cannot appear
1228 *			in a mapping.
1229 *	filtfuncarg:	An argument that will be passed to filtfunc in addition
1230 *			to the address to test.
1231 *	maxsize:	Maximum mapping size supported by this tag.
1232 *	nsegments:	Number of discontinuities allowed in maps.
1233 *	maxsegsz:	Maximum size of a segment in the map.
1234 *	flags:		Bus DMA flags.
1235 *	dmat:		A pointer to set to a valid dma tag should the return
1236 *			value of this function indicate success.
1237 */
1238/* XXX Should probably allow specification of alignment */
1239int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignemnt,
1240		       bus_size_t boundary, bus_addr_t lowaddr,
1241		       bus_addr_t highaddr, bus_dma_filter_t *filtfunc,
1242		       void *filtfuncarg, bus_size_t maxsize, int nsegments,
1243		       bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat);
1244
1245int bus_dma_tag_destroy(bus_dma_tag_t dmat);
1246
1247/*
1248 * Allocate a handle for mapping from kva/uva/physical
1249 * address space into bus device space.
1250 */
1251int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp);
1252
1253/*
1254 * Destroy  a handle for mapping from kva/uva/physical
1255 * address space into bus device space.
1256 */
1257int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map);
1258
1259/*
1260 * Allocate a piece of memory that can be efficiently mapped into
1261 * bus device space based on the constraints lited in the dma tag.
1262 * A dmamap to for use with dmamap_load is also allocated.
1263 */
1264int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
1265		     bus_dmamap_t *mapp);
1266
1267/*
1268 * Free a piece of memory and it's allociated dmamap, that was allocated
1269 * via bus_dmamem_alloc.
1270 */
1271void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map);
1272
1273/*
1274 * A function that processes a successfully loaded dma map or an error
1275 * from a delayed load map.
1276 */
1277typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
1278
1279/*
1280 * Map the buffer buf into bus space using the dmamap map.
1281 */
1282int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
1283		    bus_size_t buflen, bus_dmamap_callback_t *callback,
1284		    void *callback_arg, int flags);
1285
1286/*
1287 * Perform a syncronization operation on the given map.
1288 */
1289void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_dmasync_op_t);
1290#define bus_dmamap_sync(dmat, dmamap, op) 		\
1291	if ((dmamap) != NULL)				\
1292		_bus_dmamap_sync(dmat, dmamap, op)
1293
1294/*
1295 * Release the mapping held by map.
1296 */
1297void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map);
1298#define bus_dmamap_unload(dmat, dmamap) 		\
1299	if ((dmamap) != NULL)				\
1300		_bus_dmamap_unload(dmat, dmamap)
1301
1302#endif /* _I386_BUS_AT386_H_ */
1303