xref: /openbsd/sys/arch/i386/include/bus.h (revision 404b540a)
1 /*	$OpenBSD: bus.h,v 1.51 2009/07/30 21:39:15 miod Exp $	*/
2 /*	$NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $	*/
3 
4 /*-
5  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
10  * NASA Ames Research Center.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
36  * Copyright (c) 1996 Jason R. Thorpe.  All rights reserved.
37  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions
41  * are met:
42  * 1. Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  * 2. Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in the
46  *    documentation and/or other materials provided with the distribution.
47  * 3. All advertising materials mentioning features or use of this software
48  *    must display the following acknowledgement:
49  *	This product includes software developed by Christopher G. Demetriou
50  *	for the NetBSD Project.
51  * 4. The name of the author may not be used to endorse or promote products
52  *    derived from this software without specific prior written permission
53  *
54  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
55  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
56  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
58  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
59  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
60  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
61  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
63  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */
65 
66 #ifndef _I386_BUS_H_
67 #define _I386_BUS_H_
68 
69 #include <sys/mutex.h>
70 
71 #include <machine/pio.h>
72 
73 /*
74  * Values for the i386 bus space tag, not to be used directly by MI code.
75  */
76 #define	I386_BUS_SPACE_IO	0	/* space is i/o space */
77 #define I386_BUS_SPACE_MEM	1	/* space is mem space */
78 
79 /*
80  * Bus address and size types
81  */
82 typedef u_long bus_addr_t;
83 typedef u_long bus_size_t;
84 
85 /*
86  * Access methods for bus resources and address space.
87  */
88 typedef	int bus_space_tag_t;
89 typedef	u_long bus_space_handle_t;
90 
91 int	bus_space_map(bus_space_tag_t t, bus_addr_t addr,
92 	    bus_size_t size, int flags, bus_space_handle_t *bshp);
93 /* like bus_space_map(), but without extent map checking/allocation */
94 int	_bus_space_map(bus_space_tag_t t, bus_addr_t addr,
95 	    bus_size_t size, int flags, bus_space_handle_t *bshp);
96 void	bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
97 	    bus_size_t size);
98 /* like bus_space_unmap(), but without extent map deallocation */
99 void	_bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
100 	    bus_size_t, bus_addr_t *);
101 int	bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
102 	    bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
103 
104 int	bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
105 	    bus_addr_t rend, bus_size_t size, bus_size_t align,
106 	    bus_size_t boundary, int flags, bus_addr_t *addrp,
107 	    bus_space_handle_t *bshp);
108 void	bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
109 	    bus_size_t size);
110 
111 /*
112  *	u_intN_t bus_space_read_N(bus_space_tag_t tag,
113  *	    bus_space_handle_t bsh, bus_size_t offset);
114  *
115  * Read a 1, 2, 4, or 8 byte quantity from bus space
116  * described by tag/handle/offset.
117  */
118 u_int8_t	bus_space_read_1(bus_space_tag_t, bus_space_handle_t,
119 		    bus_size_t);
120 
121 u_int16_t	bus_space_read_2(bus_space_tag_t, bus_space_handle_t,
122 		    bus_size_t);
123 
124 u_int32_t	bus_space_read_4(bus_space_tag_t, bus_space_handle_t,
125 		    bus_size_t);
126 
127 #if 0	/* Cause a link error for bus_space_read_8 */
128 #define	bus_space_read_8(t, h, o)	!!! bus_space_read_8 unimplemented !!!
129 #endif
130 
131 #if 0	/* Cause a link error for bus_space_read_8 */
132 #define	bus_space_read_8(t, h, o)	!!! bus_space_read_8 unimplemented !!!
133 #endif
134 
135 /*
136  *	void bus_space_read_multi_N(bus_space_tag_t tag,
137  *	    bus_space_handle_t bsh, bus_size_t offset,
138  *	    u_intN_t *addr, size_t count);
139  *
140  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
141  * described by tag/handle/offset and copy into buffer provided.
142  */
143 
144 #define	bus_space_read_raw_multi_2(t, h, o, a, c) \
145     bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
146 #define	bus_space_read_raw_multi_4(t, h, o, a, c) \
147     bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
148 
149 void	bus_space_read_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
150 	    u_int8_t *, bus_size_t);
151 void	bus_space_read_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
152 	    u_int16_t *, bus_size_t);
153 void	bus_space_read_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
154 	    u_int32_t *, bus_size_t);
155 
156 #if 0	/* Cause a link error for bus_space_read_multi_8 */
157 #define	bus_space_read_multi_8	!!! bus_space_read_multi_8 unimplemented !!!
158 #endif
159 
160 /*
161  *	void bus_space_read_raw_multi_N(bus_space_tag_t tag,
162  *	    bus_space_handle_t bsh, bus_size_t offset,
163  *	    u_int8_t *addr, size_t count);
164  *
165  * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
166  * described by tag/handle/offset and copy into buffer provided.  The buffer
167  * must have proper alignment for the N byte wide entities.  Furthermore
168  * possible byte-swapping should be done by these functions.
169  */
170 
171 #define	bus_space_read_raw_multi_2(t, h, o, a, c) \
172     bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
173 #define	bus_space_read_raw_multi_4(t, h, o, a, c) \
174     bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
175 
176 #if 0	/* Cause a link error for bus_space_read_raw_multi_8 */
177 #define	bus_space_read_raw_multi_8 \
178     !!! bus_space_read_raw_multi_8 unimplemented !!!
179 #endif
180 
181 /*
182  *	void bus_space_read_region_N(bus_space_tag_t tag,
183  *	    bus_space_handle_t bsh, bus_size_t offset,
184  *	    u_intN_t *addr, size_t count);
185  *
186  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
187  * described by tag/handle and starting at `offset' and copy into
188  * buffer provided.
189  */
190 
191 void	bus_space_read_region_1(bus_space_tag_t, bus_space_handle_t,
192 	    bus_size_t, u_int8_t *, bus_size_t);
193 void	bus_space_read_region_2(bus_space_tag_t, bus_space_handle_t,
194 	    bus_size_t, u_int16_t *, bus_size_t);
195 void	bus_space_read_region_4(bus_space_tag_t, bus_space_handle_t,
196 	    bus_size_t, u_int32_t *, bus_size_t);
197 
198 #if 0	/* Cause a link error for bus_space_read_region_8 */
199 #define	bus_space_read_region_8	!!! bus_space_read_region_8 unimplemented !!!
200 #endif
201 
202 /*
203  *	void bus_space_read_raw_region_N(bus_space_tag_t tag,
204  *	    bus_space_handle_t bsh, bus_size_t offset,
205  *	    u_int8_t *addr, size_t count);
206  *
207  * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
208  * described by tag/handle and starting at `offset' and copy into
209  * buffer provided.  The buffer must have proper alignment for the N byte
210  * wide entities.  Furthermore possible byte-swapping should be done by
211  * these functions.
212  */
213 
214 #define	bus_space_read_raw_region_2(t, h, o, a, c) \
215     bus_space_read_region_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
216 #define	bus_space_read_raw_region_4(t, h, o, a, c) \
217     bus_space_read_region_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
218 
219 #if 0	/* Cause a link error for bus_space_read_raw_region_8 */
220 #define	bus_space_read_raw_region_8 \
221     !!! bus_space_read_raw_region_8 unimplemented !!!
222 #endif
223 
224 /*
225  *	void bus_space_write_N(bus_space_tag_t tag,
226  *	    bus_space_handle_t bsh, bus_size_t offset,
227  *	    u_intN_t value);
228  *
229  * Write the 1, 2, 4, or 8 byte value `value' to bus space
230  * described by tag/handle/offset.
231  */
232 
233 void	bus_space_write_1(bus_space_tag_t, bus_space_handle_t,
234 	    bus_size_t, u_int8_t);
235 void	bus_space_write_2(bus_space_tag_t, bus_space_handle_t,
236 	    bus_size_t, u_int16_t);
237 void	bus_space_write_4(bus_space_tag_t, bus_space_handle_t,
238 	    bus_size_t, u_int32_t);
239 
240 #if 0	/* Cause a link error for bus_space_write_8 */
241 #define	bus_space_write_8	!!! bus_space_write_8 not implemented !!!
242 #endif
243 
244 /*
245  *	void bus_space_write_multi_N(bus_space_tag_t tag,
246  *	    bus_space_handle_t bsh, bus_size_t offset,
247  *	    const u_intN_t *addr, size_t count);
248  *
249  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
250  * provided to bus space described by tag/handle/offset.
251  */
252 
253 void	bus_space_write_multi_1(bus_space_tag_t, bus_space_handle_t,
254 	    bus_size_t, const u_int8_t *, bus_size_t);
255 void	bus_space_write_multi_2(bus_space_tag_t, bus_space_handle_t,
256 	    bus_size_t, const u_int16_t *, bus_size_t);
257 void	bus_space_write_multi_4(bus_space_tag_t, bus_space_handle_t,
258 	    bus_size_t, const u_int32_t *, bus_size_t);
259 
260 #if 0	/* Cause a link error for bus_space_write_multi_8 */
261 #define	bus_space_write_multi_8(t, h, o, a, c)				\
262 			!!! bus_space_write_multi_8 unimplemented !!!
263 #endif
264 
265 /*
266  *	void bus_space_write_raw_multi_N(bus_space_tag_t tag,
267  *	    bus_space_handle_t bsh, bus_size_t offset,
268  *	    const u_int8_t *addr, size_t count);
269  *
270  * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer
271  * provided to bus space described by tag/handle/offset.  The buffer
272  * must have proper alignment for the N byte wide entities.  Furthermore
273  * possible byte-swapping should be done by these functions.
274  */
275 
276 #define	bus_space_write_raw_multi_2(t, h, o, a, c) \
277     bus_space_write_multi_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
278 #define	bus_space_write_raw_multi_4(t, h, o, a, c) \
279     bus_space_write_multi_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
280 
281 #if 0	/* Cause a link error for bus_space_write_raw_multi_8 */
282 #define	bus_space_write_raw_multi_8 \
283     !!! bus_space_write_raw_multi_8 unimplemented !!!
284 #endif
285 
286 /*
287  *	void bus_space_write_region_N(bus_space_tag_t tag,
288  *	    bus_space_handle_t bsh, bus_size_t offset,
289  *	    const u_intN_t *addr, size_t count);
290  *
291  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
292  * to bus space described by tag/handle starting at `offset'.
293  */
294 
295 void	bus_space_write_region_1(bus_space_tag_t, bus_space_handle_t,
296 	    bus_size_t, const u_int8_t *, bus_size_t);
297 void	bus_space_write_region_2(bus_space_tag_t, bus_space_handle_t,
298 	    bus_size_t, const u_int16_t *, bus_size_t);
299 void	bus_space_write_region_4(bus_space_tag_t, bus_space_handle_t,
300 	    bus_size_t, const u_int32_t *, bus_size_t);
301 
302 #if 0	/* Cause a link error for bus_space_write_region_8 */
303 #define	bus_space_write_region_8					\
304 			!!! bus_space_write_region_8 unimplemented !!!
305 #endif
306 
307 /*
308  *	void bus_space_write_raw_region_N(bus_space_tag_t tag,
309  *	    bus_space_handle_t bsh, bus_size_t offset,
310  *	    const u_int8_t *addr, size_t count);
311  *
312  * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space
313  * described by tag/handle and starting at `offset' from the
314  * buffer provided.  The buffer must have proper alignment for the N byte
315  * wide entities.  Furthermore possible byte-swapping should be done by
316  * these functions.
317  */
318 
319 #define	bus_space_write_raw_region_2(t, h, o, a, c) \
320     bus_space_write_region_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
321 #define	bus_space_write_raw_region_4(t, h, o, a, c) \
322     bus_space_write_region_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
323 
324 #if 0	/* Cause a link error for bus_space_write_raw_region_8 */
325 #define	bus_space_write_raw_region_8 \
326     !!! bus_space_write_raw_region_8 unimplemented !!!
327 #endif
328 
329 /*
330  *	void bus_space_set_multi_N(bus_space_tag_t tag,
331  *	    bus_space_handle_t bsh, bus_size_t offset,
332  *	    u_intN_t val, size_t count);
333  *
334  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
335  * by tag/handle/offset `count' times.
336  */
337 
338 void	bus_space_set_multi_1(bus_space_tag_t, bus_space_handle_t,
339 	    bus_size_t, u_int8_t, size_t);
340 void	bus_space_set_multi_2(bus_space_tag_t, bus_space_handle_t,
341 	    bus_size_t, u_int16_t, size_t);
342 void	bus_space_set_multi_4(bus_space_tag_t, bus_space_handle_t,
343 	    bus_size_t, u_int32_t, size_t);
344 
345 #if 0	/* Cause a link error for bus_space_set_multi_8 */
346 #define	bus_space_set_multi_8					\
347 			!!! bus_space_set_multi_8 unimplemented !!!
348 #endif
349 
350 /*
351  *	void bus_space_set_region_N(bus_space_tag_t tag,
352  *	    bus_space_handle_t bsh, bus_size_t offset,
353  *	    u_intN_t val, size_t count);
354  *
355  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
356  * by tag/handle starting at `offset'.
357  */
358 void	bus_space_set_region_1(bus_space_tag_t, bus_space_handle_t,
359 	    bus_size_t, u_int8_t, size_t);
360 void	bus_space_set_region_2(bus_space_tag_t, bus_space_handle_t,
361 	    bus_size_t, u_int16_t, size_t);
362 void	bus_space_set_region_4(bus_space_tag_t, bus_space_handle_t,
363 	    bus_size_t, u_int32_t, size_t);
364 
365 
366 #if 0	/* Cause a link error for bus_space_set_region_8 */
367 #define	bus_space_set_region_8					\
368 			!!! bus_space_set_region_8 unimplemented !!!
369 #endif
370 
371 /*
372  *	void bus_space_copy_N(bus_space_tag_t tag,
373  *	    bus_space_handle_t bsh1, bus_size_t off1,
374  *	    bus_space_handle_t bsh2, bus_size_t off2,
375  *	    size_t count);
376  *
377  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
378  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
379  */
380 
381 void	bus_space_copy_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
382 	     bus_space_handle_t, bus_size_t, bus_size_t);
383 void	bus_space_copy_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
384 	     bus_space_handle_t, bus_size_t, bus_size_t);
385 void	bus_space_copy_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
386 	     bus_space_handle_t, bus_size_t, bus_size_t);
387 
388 #if 0	/* Cause a link error for bus_space_copy_8 */
389 #define	bus_space_copy_8					\
390 			!!! bus_space_copy_8 unimplemented !!!
391 #endif
392 
393 #define	i386_space_copy1(a1, a2, cnt, movs, df)		\
394 	__asm __volatile(df "\n\trep\n\t" movs :	\
395 	    "+S" (a1), "+D" (a2), "+c" (cnt)	:: "memory", "cc");
396 
397 #define	i386_space_copy(a1, a2, sz, cnt) do {				\
398 	if ((void *)(a1) < (void *)(a2)) {				\
399 		a1 += ((cnt) - 1) * (sz); a2 += ((cnt) - 1) * (sz);	\
400 		switch (sz) {						\
401 		case 1:	i386_space_copy1(a1,a2,cnt,"movsb","std");break;\
402 		case 2:	i386_space_copy1(a1,a2,cnt,"movsw","std");break;\
403 		case 4:	i386_space_copy1(a1,a2,cnt,"movsl","std");break;\
404 		}							\
405 	} else								\
406 		switch (sz) {						\
407 		case 1:	i386_space_copy1(a1,a2,cnt,"movsb","cld");break;\
408 		case 2:	i386_space_copy1(a1,a2,cnt,"movsw","cld");break;\
409 		case 4:	i386_space_copy1(a1,a2,cnt,"movsl","cld");break;\
410 		}							\
411 } while (0)
412 
413 /*
414  * Bus read/write barrier methods.
415  *
416  *	void bus_space_barrier(bus_space_tag_t tag,
417  *	    bus_space_handle_t bsh, bus_size_t offset,
418  *	    bus_size_t len, int flags);
419  *
420  * Note: the i386 does not currently require barriers, but we must
421  * provide the flags to MI code.
422  */
423 #define	bus_space_barrier(t, h, o, l, f)	\
424 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
425 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
426 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
427 
428 #define	BUS_SPACE_MAP_CACHEABLE		0x0001
429 #define	BUS_SPACE_MAP_LINEAR		0x0002
430 #define	BUS_SPACE_MAP_PREFETCHABLE	0x0008
431 
432 /*
433  *	void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
434  *
435  * Get the kernel virtual address for the mapped bus space.
436  * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR.
437  */
438 #define bus_space_vaddr(t, h) \
439 	((t) == I386_BUS_SPACE_IO ? (void *)(NULL) : (void *)(h))
440 
441 /*
442  * Flags used in various bus DMA methods.
443  */
444 #define	BUS_DMA_WAITOK		0x0000	/* safe to sleep (pseudo-flag) */
445 #define	BUS_DMA_NOWAIT		0x0001	/* not safe to sleep */
446 #define	BUS_DMA_ALLOCNOW	0x0002	/* perform resource allocation now */
447 #define	BUS_DMA_COHERENT	0x0004	/* hint: map memory DMA coherent */
448 #define	BUS_DMA_BUS1		0x0010	/* placeholders for bus functions... */
449 #define	BUS_DMA_BUS2		0x0020
450 #define	BUS_DMA_BUS3		0x0040
451 #define	BUS_DMA_24BIT		0x0080	/* isadma map */
452 #define	BUS_DMA_STREAMING	0x0100	/* hint: sequential, unidirectional */
453 #define	BUS_DMA_READ		0x0200	/* mapping is device -> memory only */
454 #define	BUS_DMA_WRITE		0x0400	/* mapping is memory -> device only */
455 #define	BUS_DMA_NOCACHE		0x0800	/* map memory uncached */
456 #define	BUS_DMA_ZERO		0x1000	/* dmamem_alloc return zeroed mem */
457 #define	BUS_DMA_SG		0x2000	/* Internal. memory is for SG map */
458 
459 /* Forwards needed by prototypes below. */
460 struct mbuf;
461 struct proc;
462 struct uio;
463 
464 /*
465  * Operations performed by bus_dmamap_sync().
466  */
467 #define BUS_DMASYNC_PREREAD	0x01
468 #define BUS_DMASYNC_POSTREAD	0x02
469 #define BUS_DMASYNC_PREWRITE	0x04
470 #define BUS_DMASYNC_POSTWRITE	0x08
471 
472 typedef struct bus_dma_tag		*bus_dma_tag_t;
473 typedef struct bus_dmamap		*bus_dmamap_t;
474 
475 /*
476  *	bus_dma_segment_t
477  *
478  *	Describes a single contiguous DMA transaction.  Values
479  *	are suitable for programming into DMA registers.
480  */
481 struct bus_dma_segment {
482 	bus_addr_t	ds_addr;	/* DMA address */
483 	bus_size_t	ds_len;		/* length of transfer */
484 	/*
485 	 * Ugh. need this so can pass alignment down from bus_dmamem_alloc
486 	 * to scatter gather maps. only the first one is used so the rest is
487 	 * wasted space. bus_dma could do with fixing the api for this.
488 	 */
489 	 bus_size_t	_ds_boundary;	/* don't cross */
490 	 bus_size_t	_ds_align;	/* align to me */
491 };
492 typedef struct bus_dma_segment	bus_dma_segment_t;
493 
494 /*
495  *	bus_dma_tag_t
496  *
497  *	A machine-dependent opaque type describing the implementation of
498  *	DMA for a given bus.
499  */
500 
501 struct bus_dma_tag {
502 	void	*_cookie;		/* cookie used in the guts */
503 
504 	/*
505 	 * DMA mapping methods.
506 	 */
507 	int	(*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
508 		    bus_size_t, bus_size_t, int, bus_dmamap_t *);
509 	void	(*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
510 	int	(*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
511 		    bus_size_t, struct proc *, int);
512 	int	(*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
513 		    struct mbuf *, int);
514 	int	(*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
515 		    struct uio *, int);
516 	int	(*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
517 		    bus_dma_segment_t *, int, bus_size_t, int);
518 	void	(*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
519 	void	(*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
520 		    bus_addr_t, bus_size_t, int);
521 
522 	/*
523 	 * DMA memory utility functions.
524 	 */
525 	int	(*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
526 		    bus_size_t, bus_dma_segment_t *, int, int *, int);
527 	void	(*_dmamem_free)(bus_dma_tag_t,
528 		    bus_dma_segment_t *, int);
529 	int	(*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
530 		    int, size_t, caddr_t *, int);
531 	void	(*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
532 	paddr_t	(*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
533 		    int, off_t, int, int);
534 };
535 
536 #define	bus_dmamap_create(t, s, n, m, b, f, p)			\
537 	(*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
538 #define	bus_dmamap_destroy(t, p)				\
539 	(*(t)->_dmamap_destroy)((t), (p))
540 #define	bus_dmamap_load(t, m, b, s, p, f)			\
541 	(*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
542 #define	bus_dmamap_load_mbuf(t, m, b, f)			\
543 	(*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
544 #define	bus_dmamap_load_uio(t, m, u, f)				\
545 	(*(t)->_dmamap_load_uio)((t), (m), (u), (f))
546 #define	bus_dmamap_load_raw(t, m, sg, n, s, f)			\
547 	(*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
548 #define	bus_dmamap_unload(t, p)					\
549 	(*(t)->_dmamap_unload)((t), (p))
550 #define	bus_dmamap_sync(t, p, o, l, ops)			\
551 	(void)((t)->_dmamap_sync ?				\
552 	    (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
553 
554 #define	bus_dmamem_alloc(t, s, a, b, sg, n, r, f)		\
555 	(*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
556 #define	bus_dmamem_free(t, sg, n)				\
557 	(*(t)->_dmamem_free)((t), (sg), (n))
558 #define	bus_dmamem_map(t, sg, n, s, k, f)			\
559 	(*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
560 #define	bus_dmamem_unmap(t, k, s)				\
561 	(*(t)->_dmamem_unmap)((t), (k), (s))
562 #define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
563 	(*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
564 
565 /*
566  *	bus_dmamap_t
567  *
568  *	Describes a DMA mapping.
569  */
570 struct bus_dmamap {
571 	/*
572 	 * PRIVATE MEMBERS: not for use by machine-independent code.
573 	 */
574 	bus_size_t	_dm_size;	/* largest DMA transfer mappable */
575 	int		_dm_segcnt;	/* number of segs this map can map */
576 	bus_size_t	_dm_maxsegsz;	/* largest possible segment */
577 	bus_size_t	_dm_boundary;	/* don't cross this */
578 	int		_dm_flags;	/* misc. flags */
579 
580 	void		*_dm_cookie;	/* cookie for bus-specific functions */
581 
582 	/*
583 	 * PUBLIC MEMBERS: these are used by machine-independent code.
584 	 */
585 	bus_size_t	dm_mapsize;	/* size of the mapping */
586 	int		dm_nsegs;	/* # valid segments in mapping */
587 	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
588 };
589 
590 int	_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
591 	    bus_size_t, int, bus_dmamap_t *);
592 void	_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
593 int	_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
594 	    bus_size_t, struct proc *, int);
595 int	_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
596 	    struct mbuf *, int);
597 int	_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
598 	    struct uio *, int);
599 int	_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
600 	    bus_dma_segment_t *, int, bus_size_t, int);
601 void	_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
602 void	_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
603 	    bus_size_t, int);
604 
605 int	_bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
606 	    bus_size_t alignment, bus_size_t boundary,
607 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
608 void	_bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
609 	    int nsegs);
610 int	_bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
611 	    int nsegs, size_t size, caddr_t *kvap, int flags);
612 void	_bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
613 	    size_t size);
614 paddr_t	_bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
615 	    int nsegs, off_t off, int prot, int flags);
616 
617 int	_bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
618 	    bus_size_t alignment, bus_size_t boundary,
619 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
620 	    paddr_t low, paddr_t high);
621 
622 struct extent;
623 
624 /* Scatter gather bus_dma functions. */
625 struct sg_cookie {
626 	struct mutex	 sg_mtx;
627 	struct extent	*sg_ex;
628 	void		*sg_hdl;
629 	void		(*bind_page)(void *, bus_addr_t, paddr_t, int);
630 	void		(*unbind_page)(void *, bus_addr_t);
631 	void		(*flush_tlb)(void *);
632 };
633 
634 struct sg_cookie	*sg_dmatag_init(char *, void *, bus_addr_t, bus_size_t,
635 			    void (*)(void *, vaddr_t, paddr_t, int),
636 			    void (*)(void *, vaddr_t), void (*)(void *));
637 void	sg_dmatag_destroy(struct sg_cookie *);
638 int	sg_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
639 	    bus_size_t, int, bus_dmamap_t *);
640 void	sg_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
641 void	sg_dmamap_set_alignment(bus_dma_tag_t, bus_dmamap_t, u_long);
642 int	sg_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
643 	    struct proc *, int);
644 int	sg_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
645 	    struct mbuf *, int);
646 int	sg_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int);
647 int	sg_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *,
648 	    int, bus_size_t, int);
649 void	sg_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
650 int	sg_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
651 	    struct proc *, int, int *, int);
652 int	sg_dmamap_load_physarray(bus_dma_tag_t, bus_dmamap_t, paddr_t *,
653 	    int, int, int *, int);
654 int	sg_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t,
655 	    bus_dma_segment_t *, int, int *, int);
656 
657 
658 #endif /* _I386_BUS_H_ */
659