bus.h revision 39755
1279377Simp/*	$NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $	*/
2279377Simp
3279377Simp/*-
4279377Simp * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5279377Simp * All rights reserved.
6279377Simp *
7279377Simp * This code is derived from software contributed to The NetBSD Foundation
8279377Simp * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9279377Simp * NASA Ames Research Center.
10279377Simp *
11279377Simp * Redistribution and use in source and binary forms, with or without
12279377Simp * modification, are permitted provided that the following conditions
13279377Simp * are met:
14279377Simp * 1. Redistributions of source code must retain the above copyright
15279377Simp *    notice, this list of conditions and the following disclaimer.
16279377Simp * 2. Redistributions in binary form must reproduce the above copyright
17279377Simp *    notice, this list of conditions and the following disclaimer in the
18279377Simp *    documentation and/or other materials provided with the distribution.
19279377Simp * 3. All advertising materials mentioning features or use of this software
20279377Simp *    must display the following acknowledgement:
21279377Simp *	This product includes software developed by the NetBSD
22279377Simp *	Foundation, Inc. and its contributors.
23279377Simp * 4. Neither the name of The NetBSD Foundation nor the names of its
24279377Simp *    contributors may be used to endorse or promote products derived
25279377Simp *    from this software without specific prior written permission.
26279377Simp *
27279377Simp * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28279377Simp * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29279377Simp * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30279377Simp * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31279377Simp * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32279377Simp * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33279377Simp * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34279377Simp * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35279377Simp * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36279377Simp * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37279377Simp * POSSIBILITY OF SUCH DAMAGE.
38279377Simp */
39279377Simp
40279377Simp/*
41279377Simp * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
42279377Simp * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
43279377Simp *
44279377Simp * Redistribution and use in source and binary forms, with or without
45279377Simp * modification, are permitted provided that the following conditions
46279377Simp * are met:
47279377Simp * 1. Redistributions of source code must retain the above copyright
48279377Simp *    notice, this list of conditions and the following disclaimer.
49279377Simp * 2. Redistributions in binary form must reproduce the above copyright
50279377Simp *    notice, this list of conditions and the following disclaimer in the
51279377Simp *    documentation and/or other materials provided with the distribution.
52279377Simp * 3. All advertising materials mentioning features or use of this software
53279377Simp *    must display the following acknowledgement:
54279377Simp *      This product includes software developed by Christopher G. Demetriou
55279377Simp *	for the NetBSD Project.
56279377Simp * 4. The name of the author may not be used to endorse or promote products
57279377Simp *    derived from this software without specific prior written permission
58279377Simp *
59279377Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60279377Simp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61279377Simp * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62279377Simp * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63279377Simp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64279377Simp * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65279377Simp * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66279377Simp * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67279377Simp * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68279377Simp * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69279377Simp */
70279377Simp/* $Id: bus.h,v 1.3 1998/05/06 01:45:47 gibbs Exp $ */
71279377Simp
72279377Simp#ifndef _I386_BUS_H_
73279377Simp#define _I386_BUS_H_
74279377Simp
75279377Simp#include <machine/cpufunc.h>
76279377Simp
77279377Simp/*
78279377Simp * Values for the i386 bus space tag, not to be used directly by MI code.
79279377Simp */
80279377Simp#define	I386_BUS_SPACE_IO	0	/* space is i/o space */
81279377Simp#define I386_BUS_SPACE_MEM	1	/* space is mem space */
82279377Simp
83279377Simp/*
84279377Simp * Bus address and size types
85279377Simp */
86279377Simptypedef u_int bus_addr_t;
87279377Simptypedef u_int bus_size_t;
88279377Simp
89279377Simp#define BUS_SPACE_MAXSIZE_24BIT	0xFFFFFF
90279377Simp#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
91279377Simp#define BUS_SPACE_MAXSIZE	(64 * 1024) /* Maximum supported size */
92279377Simp#define BUS_SPACE_MAXADDR_24BIT	0xFFFFFF
93279377Simp#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
94279377Simp#define BUS_SPACE_MAXADDR	0xFFFFFFFF
95279377Simp
96279377Simp#define BUS_SPACE_UNRESTRICTED	(~0)
97279377Simp
98279377Simp/*
99279377Simp * Access methods for bus resources and address space.
100279377Simp */
101279377Simptypedef	int bus_space_tag_t;
102279377Simptypedef	u_int bus_space_handle_t;
103279377Simp
104279377Simp/*
105279377Simp * Map a region of device bus space into CPU virtual address space.
106279377Simp */
107279377Simp
108279377Simp#define	BUS_SPACE_MAP_CACHEABLE		0x01
109279377Simp#define	BUS_SPACE_MAP_LINEAR		0x02
110279377Simp
111279377Simpint	bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
112279377Simp		      int flags, bus_space_handle_t *bshp);
113279377Simp
114279377Simp/*
115279377Simp * Unmap a region of device bus space.
116279377Simp */
117279377Simp
118279377Simpvoid	bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
119279377Simp			bus_size_t size);
120279377Simp
121279377Simp/*
122279377Simp * Get a new handle for a subregion of an already-mapped area of bus space.
123279377Simp */
124279377Simp
125279377Simpint	bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
126279377Simp			    bus_size_t offset, bus_size_t size,
127279377Simp			    bus_space_handle_t *nbshp);
128279377Simp
129279377Simp/*
130279377Simp * Allocate a region of memory that is accessible to devices in bus space.
131279377Simp */
132279377Simp
133279377Simpint	bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
134279377Simp			bus_addr_t rend, bus_size_t size, bus_size_t align,
135279377Simp			bus_size_t boundary, int flags, bus_addr_t *addrp,
136279377Simp			bus_space_handle_t *bshp);
137279377Simp
138279377Simp/*
139279377Simp * Free a region of bus space accessible memory.
140279377Simp */
141279377Simp
142279377Simpvoid	bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
143279377Simp		       bus_size_t size);
144279377Simp
145279377Simp#if defined(_I386_BUS_PIO_H_) || defined(_I386_BUS_MEMIO_H_)
146279377Simp
147279377Simp/*
148279377Simp * Read a 1, 2, 4, or 8 byte quantity from bus space
149279377Simp * described by tag/handle/offset.
150279377Simp */
151279377Simpstatic __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
152279377Simp					  bus_space_handle_t handle,
153279377Simp					  bus_size_t offset);
154279377Simp
155279377Simpstatic __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
156279377Simp					   bus_space_handle_t handle,
157279377Simp					   bus_size_t offset);
158279377Simp
159279377Simpstatic __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
160279377Simp					   bus_space_handle_t handle,
161279377Simp					   bus_size_t offset);
162279377Simp
163279377Simpstatic __inline u_int8_t
164279377Simpbus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
165279377Simp		 bus_size_t offset)
166279377Simp{
167279377Simp#if defined (_I386_BUS_PIO_H_)
168279377Simp#if defined (_I386_BUS_MEMIO_H_)
169279377Simp	if (tag == I386_BUS_SPACE_IO)
170279377Simp#endif
171279377Simp		return (inb(handle + offset));
172279377Simp#endif
173279377Simp#if defined (_I386_BUS_MEMIO_H_)
174279377Simp	return (*(volatile u_int8_t *)(handle + offset));
175279377Simp#endif
176279377Simp}
177279377Simp
178279377Simpstatic __inline u_int16_t
179279377Simpbus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
180279377Simp		 bus_size_t offset)
181279377Simp{
182279377Simp#if defined(_I386_BUS_PIO_H_)
183279377Simp#if defined(_I386_BUS_MEMIO_H_)
184279377Simp	if (tag == I386_BUS_SPACE_IO)
185279377Simp#endif
186279377Simp		return (inw(handle + offset));
187279377Simp#endif
188279377Simp#if defined(_I386_BUS_MEMIO_H_)
189279377Simp	return (*(volatile u_int16_t *)(handle + offset));
190279377Simp#endif
191279377Simp}
192279377Simp
193279377Simpstatic __inline u_int32_t
194279377Simpbus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
195279377Simp		 bus_size_t offset)
196279377Simp{
197279377Simp#if defined(_I386_BUS_PIO_H_)
198279377Simp#if defined(_I386_BUS_MEMIO_H_)
199279377Simp	if (tag == I386_BUS_SPACE_IO)
200279377Simp#endif
201279377Simp		return (inl(handle + offset));
202279377Simp#endif
203279377Simp#if defined(_I386_BUS_MEMIO_H_)
204279377Simp	return (*(volatile u_int32_t *)(handle + offset));
205279377Simp#endif
206279377Simp}
207279377Simp
208279377Simp#if 0	/* Cause a link error for bus_space_read_8 */
209279377Simp#define	bus_space_read_8(t, h, o)	!!! bus_space_read_8 unimplemented !!!
210279377Simp#endif
211279377Simp
212279377Simp/*
213279377Simp * Read `count' 1, 2, 4, or 8 byte quantities from bus space
214279377Simp * described by tag/handle/offset and copy into buffer provided.
215279377Simp */
216279377Simpstatic __inline void bus_space_read_multi_1(bus_space_tag_t tag,
217279377Simp					    bus_space_handle_t bsh,
218279377Simp					    bus_size_t offset, u_int8_t *addr,
219279377Simp					    size_t count);
220279377Simp
221279377Simpstatic __inline void bus_space_read_multi_2(bus_space_tag_t tag,
222279377Simp					    bus_space_handle_t bsh,
223279377Simp					    bus_size_t offset, u_int16_t *addr,
224279377Simp					    size_t count);
225279377Simp
226279377Simpstatic __inline void bus_space_read_multi_4(bus_space_tag_t tag,
227279377Simp					    bus_space_handle_t bsh,
228279377Simp					    bus_size_t offset, u_int32_t *addr,
229279377Simp					    size_t count);
230279377Simp
231279377Simpstatic __inline void
232279377Simpbus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
233279377Simp		       bus_size_t offset, u_int8_t *addr, size_t count)
234279377Simp{
235279377Simp#if defined(_I386_BUS_PIO_H_)
236279377Simp#if defined(_I386_BUS_MEMIO_H_)
237279377Simp	if (tag == I386_BUS_SPACE_IO)
238279377Simp#endif
239279377Simp		insb(bsh + offset, addr, count);
240279377Simp#endif
241279377Simp#if defined(_I386_BUS_MEMIO_H_)
242279377Simp#if defined(_I386_BUS_PIO_H_)
243279377Simp	else
244279377Simp#endif
245279377Simp	{
246279377Simp		int __x __asm__("%eax");
247279377Simp		__asm __volatile("				\n\
248279377Simp			cld					\n\
249279377Simp		1:	movb (%1),%%al				\n\
250279377Simp			stosb					\n\
251279377Simp			loop 1b"				:
252279377Simp		    "=&a" (__x)					:
253279377Simp		    "r" (bsh + offset), "D" (addr), "c" (count)	:
254279377Simp		    "%edi", "%ecx", "memory");
255279377Simp	}
256279377Simp#endif
257279377Simp}
258279377Simp
259279377Simpstatic __inline void
260279377Simpbus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
261279377Simp		       bus_size_t offset, u_int16_t *addr, size_t count)
262279377Simp{
263279377Simp#if defined(_I386_BUS_PIO_H_)
264279377Simp#if defined(_I386_BUS_MEMIO_H_)
265279377Simp	if (tag == I386_BUS_SPACE_IO)
266279377Simp#endif
267279377Simp		insw(bsh + offset, addr, count);
268279377Simp#endif
269279377Simp#if defined(_I386_BUS_MEMIO_H_)
270279377Simp#if defined(_I386_BUS_PIO_H_)
271279377Simp	else
272279377Simp#endif
273279377Simp	{
274279377Simp		int __x __asm__("%eax");
275279377Simp		__asm __volatile("				\n\
276279377Simp			cld					\n\
277279377Simp		1:	movw (%1),%%ax				\n\
278279377Simp			stosw					\n\
279279377Simp			loop 1b"				:
280279377Simp		    "=&a" (__x)					:
281279377Simp		    "r" (bsh + offset), "D" (addr), "c" (count)	:
282279377Simp		    "%edi", "%ecx", "memory");
283279377Simp	}
284279377Simp#endif
285279377Simp}
286279377Simp
287279377Simpstatic __inline void
288279377Simpbus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
289279377Simp		       bus_size_t offset, u_int32_t *addr, size_t count)
290279377Simp{
291279377Simp#if defined(_I386_BUS_PIO_H_)
292279377Simp#if defined(_I386_BUS_MEMIO_H_)
293279377Simp	if (tag == I386_BUS_SPACE_IO)
294279377Simp#endif
295279377Simp		insl(bsh + offset, addr, count);
296279377Simp#endif
297279377Simp#if defined(_I386_BUS_MEMIO_H_)
298279377Simp#if defined(_I386_BUS_PIO_H_)
299279377Simp	else
300279377Simp#endif
301279377Simp	{
302279377Simp		int __x __asm__("%eax");
303279377Simp		__asm __volatile("				\n\
304279377Simp			cld					\n\
305279377Simp		1:	movl (%1),%%eax				\n\
306279377Simp			stosl					\n\
307279377Simp			loop 1b"				:
308279377Simp		    "=&a" (__x)					:
309279377Simp		    "r" (bsh + offset), "D" (addr), "c" (count)	:
310279377Simp		    "%edi", "%ecx", "memory");
311279377Simp	}
312279377Simp#endif
313279377Simp}
314279377Simp
315279377Simp#if 0	/* Cause a link error for bus_space_read_multi_8 */
316279377Simp#define	bus_space_read_multi_8	!!! bus_space_read_multi_8 unimplemented !!!
317279377Simp#endif
318279377Simp
319279377Simp/*
320279377Simp * Read `count' 1, 2, 4, or 8 byte quantities from bus space
321279377Simp * described by tag/handle and starting at `offset' and copy into
322279377Simp * buffer provided.
323279377Simp */
324279377Simpstatic __inline void bus_space_read_region_1(bus_space_tag_t tag,
325279377Simp					     bus_space_handle_t bsh,
326279377Simp					     bus_size_t offset, u_int8_t *addr,
327279377Simp					     size_t count);
328279377Simp
329279377Simpstatic __inline void bus_space_read_region_2(bus_space_tag_t tag,
330279377Simp					     bus_space_handle_t bsh,
331279377Simp					     bus_size_t offset, u_int16_t *addr,
332279377Simp					     size_t count);
333279377Simp
334279377Simpstatic __inline void bus_space_read_region_4(bus_space_tag_t tag,
335279377Simp					     bus_space_handle_t bsh,
336279377Simp					     bus_size_t offset, u_int32_t *addr,
337279377Simp					     size_t count);
338279377Simp
339279377Simp
340279377Simpstatic __inline void
341279377Simpbus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
342279377Simp			bus_size_t offset, u_int8_t *addr, size_t count)
343279377Simp{
344279377Simp#if defined(_I386_BUS_PIO_H_)
345279377Simp#if defined(_I386_BUS_MEMIO_H_)
346279377Simp	if (tag == I386_BUS_SPACE_IO)
347279377Simp#endif
348279377Simp	{
349279377Simp		int __x __asm__("%eax");
350279377Simp		__asm __volatile("				\n\
351279377Simp			cld					\n\
352279377Simp		1:	inb %w1,%%al				\n\
353279377Simp			stosb					\n\
354279377Simp			incl %1					\n\
355279377Simp			loop 1b"				:
356279377Simp		    "=&a" (__x)					:
357279377Simp		    "d" (bsh + offset), "D" (addr), "c" (count)	:
358279377Simp		    "%edx", "%edi", "%ecx", "memory");
359279377Simp	}
360279377Simp#endif
361279377Simp#if defined(_I386_BUS_MEMIO_H_)
362279377Simp#if defined(_I386_BUS_PIO_H_)
363279377Simp	else
364279377Simp#endif
365279377Simp	{
366279377Simp		__asm __volatile("				\n\
367279377Simp			cld					\n\
368279377Simp			repne					\n\
369279377Simp			movsb"					:
370279377Simp								:
371279377Simp		    "S" (bsh + offset), "D" (addr), "c" (count)	:
372279377Simp		    "%esi", "%edi", "%ecx", "memory");
373279377Simp	}
374279377Simp#endif
375279377Simp}
376279377Simp
377279377Simpstatic __inline void
378279377Simpbus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
379279377Simp			bus_size_t offset, u_int16_t *addr, size_t count)
380279377Simp{
381279377Simp#if defined(_I386_BUS_PIO_H_)
382279377Simp#if defined(_I386_BUS_MEMIO_H_)
383279377Simp	if (tag == I386_BUS_SPACE_IO)
384279377Simp#endif
385279377Simp	{
386279377Simp		int __x __asm__("%eax");
387279377Simp		__asm __volatile("				\n\
388279377Simp			cld					\n\
389279377Simp		1:	inw %w1,%%ax				\n\
390279377Simp			stosw					\n\
391279377Simp			addl $2,%1				\n\
392279377Simp			loop 1b"				:
393279377Simp		    "=&a" (__x)					:
394279377Simp		    "d" (bsh + offset), "D" (addr), "c" (count)	:
395279377Simp		    "%edx", "%edi", "%ecx", "memory");
396279377Simp	}
397279377Simp#endif
398279377Simp#if defined(_I386_BUS_MEMIO_H_)
399279377Simp#if defined(_I386_BUS_PIO_H_)
400279377Simp	else
401279377Simp#endif
402279377Simp	{
403279377Simp		__asm __volatile("				\n\
404279377Simp			cld					\n\
405279377Simp			repne					\n\
406279377Simp			movsw"					:
407279377Simp								:
408279377Simp		    "S" (bsh + offset), "D" (addr), "c" (count)	:
409279377Simp		    "%esi", "%edi", "%ecx", "memory");
410279377Simp	}
411279377Simp#endif
412279377Simp}
413279377Simp
414279377Simpstatic __inline void
415279377Simpbus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
416279377Simp			bus_size_t offset, u_int32_t *addr, size_t count)
417279377Simp{
418279377Simp#if defined(_I386_BUS_PIO_H_)
419279377Simp#if defined(_I386_BUS_MEMIO_H_)
420279377Simp	if (tag == I386_BUS_SPACE_IO)
421279377Simp#endif
422279377Simp	{
423279377Simp		int __x __asm__("%eax");
424279377Simp		__asm __volatile("				\n\
425279377Simp			cld					\n\
426279377Simp		1:	inl %w1,%%eax				\n\
427279377Simp			stosl					\n\
428279377Simp			addl $4,%1				\n\
429279377Simp			loop 1b"				:
430279377Simp		    "=&a" (__x)					:
431279377Simp		    "d" (bsh + offset), "D" (addr), "c" (count)	:
432279377Simp		    "%edx", "%edi", "%ecx", "memory");
433279377Simp	}
434279377Simp#endif
435279377Simp#if defined(_I386_BUS_MEMIO_H_)
436279377Simp#if defined(_I386_BUS_PIO_H_)
437279377Simp	else
438279377Simp#endif
439279377Simp	{
440279377Simp		__asm __volatile("				\n\
441279377Simp			cld					\n\
442279377Simp			repne					\n\
443279377Simp			movsl"					:
444279377Simp								:
445279377Simp		    "S" (bsh + offset), "D" (addr), "c" (count)	:
446279377Simp		    "%esi", "%edi", "%ecx", "memory");
447279377Simp	}
448279377Simp#endif
449279377Simp}
450279377Simp
451279377Simp#if 0	/* Cause a link error for bus_space_read_region_8 */
452279377Simp#define	bus_space_read_region_8	!!! bus_space_read_region_8 unimplemented !!!
453279377Simp#endif
454279377Simp
455279377Simp/*
456279377Simp * Write the 1, 2, 4, or 8 byte value `value' to bus space
457279377Simp * described by tag/handle/offset.
458279377Simp */
459279377Simp
460279377Simpstatic __inline void bus_space_write_1(bus_space_tag_t tag,
461279377Simp				       bus_space_handle_t bsh,
462279377Simp				       bus_size_t offset, u_int8_t value);
463279377Simp
464279377Simpstatic __inline void bus_space_write_2(bus_space_tag_t tag,
465279377Simp				       bus_space_handle_t bsh,
466279377Simp				       bus_size_t offset, u_int16_t value);
467279377Simp
468279377Simpstatic __inline void bus_space_write_4(bus_space_tag_t tag,
469279377Simp				       bus_space_handle_t bsh,
470279377Simp				       bus_size_t offset, u_int32_t value);
471279377Simp
472279377Simpstatic __inline void
473279377Simpbus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
474279377Simp		       bus_size_t offset, u_int8_t value)
475279377Simp{
476279377Simp#if defined(_I386_BUS_PIO_H_)
477279377Simp#if defined(_I386_BUS_MEMIO_H_)
478279377Simp	if (tag == I386_BUS_SPACE_IO)
479279377Simp#endif
480279377Simp		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
490static __inline void
491bus_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
508static __inline void
509bus_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
535static __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);
540static __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
546static __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
552static __inline void
553bus_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
580static __inline void
581bus_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
608static __inline void
609bus_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
646static __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);
651static __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);
656static __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
662static __inline void
663bus_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
699static __inline void
700bus_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
736static __inline void
737bus_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
783static __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);
787static __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);
791static __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
796static __inline void
797bus_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
818static __inline void
819bus_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
840static __inline void
841bus_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
871static __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);
875static __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);
879static __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
884static __inline void
885bus_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
906static __inline void
907bus_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
928static __inline void
929bus_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
959static __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
965static __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
971static __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
977static __inline void
978bus_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
1023static __inline void
1024bus_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
1069static __inline void
1070bus_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. */
1148struct mbuf;
1149struct uio;
1150
1151/*
1152 *	bus_dmasync_op_t
1153 *
1154 *	Operations performed by bus_dmamap_sync().
1155 */
1156typedef 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 */
1171typedef struct bus_dma_tag	*bus_dma_tag_t;
1172
1173/*
1174 *	bus_dmamap_t
1175 *
1176 *	DMA mapping instance information.
1177 */
1178typedef 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 */
1186typedef 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 */
1195typedef 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 */
1218int 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
1224int 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 */
1230int 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 */
1236int 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 */
1243int 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 */
1250void 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 */
1256typedef 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 */
1261int 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 */
1268void _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 */
1276void _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