xref: /openbsd/sys/arch/i386/include/bus.h (revision 17df1aa7)
1 /*	$OpenBSD: bus.h,v 1.52 2010/04/08 00:55:25 oga 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 #include <sys/tree.h>
71 
72 #include <machine/pio.h>
73 
74 /*
75  * Values for the i386 bus space tag, not to be used directly by MI code.
76  */
77 #define	I386_BUS_SPACE_IO	0	/* space is i/o space */
78 #define I386_BUS_SPACE_MEM	1	/* space is mem space */
79 
80 /*
81  * Bus address and size types
82  */
83 typedef u_long bus_addr_t;
84 typedef u_long bus_size_t;
85 
86 /*
87  * Access methods for bus resources and address space.
88  */
89 typedef	int bus_space_tag_t;
90 typedef	u_long bus_space_handle_t;
91 
92 int	bus_space_map(bus_space_tag_t t, bus_addr_t addr,
93 	    bus_size_t size, int flags, bus_space_handle_t *bshp);
94 /* like bus_space_map(), but without extent map checking/allocation */
95 int	_bus_space_map(bus_space_tag_t t, bus_addr_t addr,
96 	    bus_size_t size, int flags, bus_space_handle_t *bshp);
97 void	bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
98 	    bus_size_t size);
99 /* like bus_space_unmap(), but without extent map deallocation */
100 void	_bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
101 	    bus_size_t, bus_addr_t *);
102 int	bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
103 	    bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
104 
105 int	bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
106 	    bus_addr_t rend, bus_size_t size, bus_size_t align,
107 	    bus_size_t boundary, int flags, bus_addr_t *addrp,
108 	    bus_space_handle_t *bshp);
109 void	bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
110 	    bus_size_t size);
111 
112 /*
113  *	u_intN_t bus_space_read_N(bus_space_tag_t tag,
114  *	    bus_space_handle_t bsh, bus_size_t offset);
115  *
116  * Read a 1, 2, 4, or 8 byte quantity from bus space
117  * described by tag/handle/offset.
118  */
119 u_int8_t	bus_space_read_1(bus_space_tag_t, bus_space_handle_t,
120 		    bus_size_t);
121 
122 u_int16_t	bus_space_read_2(bus_space_tag_t, bus_space_handle_t,
123 		    bus_size_t);
124 
125 u_int32_t	bus_space_read_4(bus_space_tag_t, bus_space_handle_t,
126 		    bus_size_t);
127 
128 #if 0	/* Cause a link error for bus_space_read_8 */
129 #define	bus_space_read_8(t, h, o)	!!! bus_space_read_8 unimplemented !!!
130 #endif
131 
132 #if 0	/* Cause a link error for bus_space_read_8 */
133 #define	bus_space_read_8(t, h, o)	!!! bus_space_read_8 unimplemented !!!
134 #endif
135 
136 /*
137  *	void bus_space_read_multi_N(bus_space_tag_t tag,
138  *	    bus_space_handle_t bsh, bus_size_t offset,
139  *	    u_intN_t *addr, size_t count);
140  *
141  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
142  * described by tag/handle/offset and copy into buffer provided.
143  */
144 
145 #define	bus_space_read_raw_multi_2(t, h, o, a, c) \
146     bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
147 #define	bus_space_read_raw_multi_4(t, h, o, a, c) \
148     bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
149 
150 void	bus_space_read_multi_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
151 	    u_int8_t *, bus_size_t);
152 void	bus_space_read_multi_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
153 	    u_int16_t *, bus_size_t);
154 void	bus_space_read_multi_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
155 	    u_int32_t *, bus_size_t);
156 
157 #if 0	/* Cause a link error for bus_space_read_multi_8 */
158 #define	bus_space_read_multi_8	!!! bus_space_read_multi_8 unimplemented !!!
159 #endif
160 
161 /*
162  *	void bus_space_read_raw_multi_N(bus_space_tag_t tag,
163  *	    bus_space_handle_t bsh, bus_size_t offset,
164  *	    u_int8_t *addr, size_t count);
165  *
166  * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
167  * described by tag/handle/offset and copy into buffer provided.  The buffer
168  * must have proper alignment for the N byte wide entities.  Furthermore
169  * possible byte-swapping should be done by these functions.
170  */
171 
172 #define	bus_space_read_raw_multi_2(t, h, o, a, c) \
173     bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
174 #define	bus_space_read_raw_multi_4(t, h, o, a, c) \
175     bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
176 
177 #if 0	/* Cause a link error for bus_space_read_raw_multi_8 */
178 #define	bus_space_read_raw_multi_8 \
179     !!! bus_space_read_raw_multi_8 unimplemented !!!
180 #endif
181 
182 /*
183  *	void bus_space_read_region_N(bus_space_tag_t tag,
184  *	    bus_space_handle_t bsh, bus_size_t offset,
185  *	    u_intN_t *addr, size_t count);
186  *
187  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
188  * described by tag/handle and starting at `offset' and copy into
189  * buffer provided.
190  */
191 
192 void	bus_space_read_region_1(bus_space_tag_t, bus_space_handle_t,
193 	    bus_size_t, u_int8_t *, bus_size_t);
194 void	bus_space_read_region_2(bus_space_tag_t, bus_space_handle_t,
195 	    bus_size_t, u_int16_t *, bus_size_t);
196 void	bus_space_read_region_4(bus_space_tag_t, bus_space_handle_t,
197 	    bus_size_t, u_int32_t *, bus_size_t);
198 
199 #if 0	/* Cause a link error for bus_space_read_region_8 */
200 #define	bus_space_read_region_8	!!! bus_space_read_region_8 unimplemented !!!
201 #endif
202 
203 /*
204  *	void bus_space_read_raw_region_N(bus_space_tag_t tag,
205  *	    bus_space_handle_t bsh, bus_size_t offset,
206  *	    u_int8_t *addr, size_t count);
207  *
208  * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
209  * described by tag/handle and starting at `offset' and copy into
210  * buffer provided.  The buffer must have proper alignment for the N byte
211  * wide entities.  Furthermore possible byte-swapping should be done by
212  * these functions.
213  */
214 
215 #define	bus_space_read_raw_region_2(t, h, o, a, c) \
216     bus_space_read_region_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
217 #define	bus_space_read_raw_region_4(t, h, o, a, c) \
218     bus_space_read_region_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
219 
220 #if 0	/* Cause a link error for bus_space_read_raw_region_8 */
221 #define	bus_space_read_raw_region_8 \
222     !!! bus_space_read_raw_region_8 unimplemented !!!
223 #endif
224 
225 /*
226  *	void bus_space_write_N(bus_space_tag_t tag,
227  *	    bus_space_handle_t bsh, bus_size_t offset,
228  *	    u_intN_t value);
229  *
230  * Write the 1, 2, 4, or 8 byte value `value' to bus space
231  * described by tag/handle/offset.
232  */
233 
234 void	bus_space_write_1(bus_space_tag_t, bus_space_handle_t,
235 	    bus_size_t, u_int8_t);
236 void	bus_space_write_2(bus_space_tag_t, bus_space_handle_t,
237 	    bus_size_t, u_int16_t);
238 void	bus_space_write_4(bus_space_tag_t, bus_space_handle_t,
239 	    bus_size_t, u_int32_t);
240 
241 #if 0	/* Cause a link error for bus_space_write_8 */
242 #define	bus_space_write_8	!!! bus_space_write_8 not implemented !!!
243 #endif
244 
245 /*
246  *	void bus_space_write_multi_N(bus_space_tag_t tag,
247  *	    bus_space_handle_t bsh, bus_size_t offset,
248  *	    const u_intN_t *addr, size_t count);
249  *
250  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
251  * provided to bus space described by tag/handle/offset.
252  */
253 
254 void	bus_space_write_multi_1(bus_space_tag_t, bus_space_handle_t,
255 	    bus_size_t, const u_int8_t *, bus_size_t);
256 void	bus_space_write_multi_2(bus_space_tag_t, bus_space_handle_t,
257 	    bus_size_t, const u_int16_t *, bus_size_t);
258 void	bus_space_write_multi_4(bus_space_tag_t, bus_space_handle_t,
259 	    bus_size_t, const u_int32_t *, bus_size_t);
260 
261 #if 0	/* Cause a link error for bus_space_write_multi_8 */
262 #define	bus_space_write_multi_8(t, h, o, a, c)				\
263 			!!! bus_space_write_multi_8 unimplemented !!!
264 #endif
265 
266 /*
267  *	void bus_space_write_raw_multi_N(bus_space_tag_t tag,
268  *	    bus_space_handle_t bsh, bus_size_t offset,
269  *	    const u_int8_t *addr, size_t count);
270  *
271  * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer
272  * provided to bus space described by tag/handle/offset.  The buffer
273  * must have proper alignment for the N byte wide entities.  Furthermore
274  * possible byte-swapping should be done by these functions.
275  */
276 
277 #define	bus_space_write_raw_multi_2(t, h, o, a, c) \
278     bus_space_write_multi_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
279 #define	bus_space_write_raw_multi_4(t, h, o, a, c) \
280     bus_space_write_multi_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
281 
282 #if 0	/* Cause a link error for bus_space_write_raw_multi_8 */
283 #define	bus_space_write_raw_multi_8 \
284     !!! bus_space_write_raw_multi_8 unimplemented !!!
285 #endif
286 
287 /*
288  *	void bus_space_write_region_N(bus_space_tag_t tag,
289  *	    bus_space_handle_t bsh, bus_size_t offset,
290  *	    const u_intN_t *addr, size_t count);
291  *
292  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
293  * to bus space described by tag/handle starting at `offset'.
294  */
295 
296 void	bus_space_write_region_1(bus_space_tag_t, bus_space_handle_t,
297 	    bus_size_t, const u_int8_t *, bus_size_t);
298 void	bus_space_write_region_2(bus_space_tag_t, bus_space_handle_t,
299 	    bus_size_t, const u_int16_t *, bus_size_t);
300 void	bus_space_write_region_4(bus_space_tag_t, bus_space_handle_t,
301 	    bus_size_t, const u_int32_t *, bus_size_t);
302 
303 #if 0	/* Cause a link error for bus_space_write_region_8 */
304 #define	bus_space_write_region_8					\
305 			!!! bus_space_write_region_8 unimplemented !!!
306 #endif
307 
308 /*
309  *	void bus_space_write_raw_region_N(bus_space_tag_t tag,
310  *	    bus_space_handle_t bsh, bus_size_t offset,
311  *	    const u_int8_t *addr, size_t count);
312  *
313  * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space
314  * described by tag/handle and starting at `offset' from the
315  * buffer provided.  The buffer must have proper alignment for the N byte
316  * wide entities.  Furthermore possible byte-swapping should be done by
317  * these functions.
318  */
319 
320 #define	bus_space_write_raw_region_2(t, h, o, a, c) \
321     bus_space_write_region_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
322 #define	bus_space_write_raw_region_4(t, h, o, a, c) \
323     bus_space_write_region_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
324 
325 #if 0	/* Cause a link error for bus_space_write_raw_region_8 */
326 #define	bus_space_write_raw_region_8 \
327     !!! bus_space_write_raw_region_8 unimplemented !!!
328 #endif
329 
330 /*
331  *	void bus_space_set_multi_N(bus_space_tag_t tag,
332  *	    bus_space_handle_t bsh, bus_size_t offset,
333  *	    u_intN_t val, size_t count);
334  *
335  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
336  * by tag/handle/offset `count' times.
337  */
338 
339 void	bus_space_set_multi_1(bus_space_tag_t, bus_space_handle_t,
340 	    bus_size_t, u_int8_t, size_t);
341 void	bus_space_set_multi_2(bus_space_tag_t, bus_space_handle_t,
342 	    bus_size_t, u_int16_t, size_t);
343 void	bus_space_set_multi_4(bus_space_tag_t, bus_space_handle_t,
344 	    bus_size_t, u_int32_t, size_t);
345 
346 #if 0	/* Cause a link error for bus_space_set_multi_8 */
347 #define	bus_space_set_multi_8					\
348 			!!! bus_space_set_multi_8 unimplemented !!!
349 #endif
350 
351 /*
352  *	void bus_space_set_region_N(bus_space_tag_t tag,
353  *	    bus_space_handle_t bsh, bus_size_t offset,
354  *	    u_intN_t val, size_t count);
355  *
356  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
357  * by tag/handle starting at `offset'.
358  */
359 void	bus_space_set_region_1(bus_space_tag_t, bus_space_handle_t,
360 	    bus_size_t, u_int8_t, size_t);
361 void	bus_space_set_region_2(bus_space_tag_t, bus_space_handle_t,
362 	    bus_size_t, u_int16_t, size_t);
363 void	bus_space_set_region_4(bus_space_tag_t, bus_space_handle_t,
364 	    bus_size_t, u_int32_t, size_t);
365 
366 
367 #if 0	/* Cause a link error for bus_space_set_region_8 */
368 #define	bus_space_set_region_8					\
369 			!!! bus_space_set_region_8 unimplemented !!!
370 #endif
371 
372 /*
373  *	void bus_space_copy_N(bus_space_tag_t tag,
374  *	    bus_space_handle_t bsh1, bus_size_t off1,
375  *	    bus_space_handle_t bsh2, bus_size_t off2,
376  *	    size_t count);
377  *
378  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
379  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
380  */
381 
382 void	bus_space_copy_1(bus_space_tag_t, bus_space_handle_t, bus_size_t,
383 	     bus_space_handle_t, bus_size_t, bus_size_t);
384 void	bus_space_copy_2(bus_space_tag_t, bus_space_handle_t, bus_size_t,
385 	     bus_space_handle_t, bus_size_t, bus_size_t);
386 void	bus_space_copy_4(bus_space_tag_t, bus_space_handle_t, bus_size_t,
387 	     bus_space_handle_t, bus_size_t, bus_size_t);
388 
389 #if 0	/* Cause a link error for bus_space_copy_8 */
390 #define	bus_space_copy_8					\
391 			!!! bus_space_copy_8 unimplemented !!!
392 #endif
393 
394 #define	i386_space_copy1(a1, a2, cnt, movs, df)		\
395 	__asm __volatile(df "\n\trep\n\t" movs :	\
396 	    "+S" (a1), "+D" (a2), "+c" (cnt)	:: "memory", "cc");
397 
398 #define	i386_space_copy(a1, a2, sz, cnt) do {				\
399 	if ((void *)(a1) < (void *)(a2)) {				\
400 		a1 += ((cnt) - 1) * (sz); a2 += ((cnt) - 1) * (sz);	\
401 		switch (sz) {						\
402 		case 1:	i386_space_copy1(a1,a2,cnt,"movsb","std");break;\
403 		case 2:	i386_space_copy1(a1,a2,cnt,"movsw","std");break;\
404 		case 4:	i386_space_copy1(a1,a2,cnt,"movsl","std");break;\
405 		}							\
406 	} else								\
407 		switch (sz) {						\
408 		case 1:	i386_space_copy1(a1,a2,cnt,"movsb","cld");break;\
409 		case 2:	i386_space_copy1(a1,a2,cnt,"movsw","cld");break;\
410 		case 4:	i386_space_copy1(a1,a2,cnt,"movsl","cld");break;\
411 		}							\
412 } while (0)
413 
414 /*
415  * Bus read/write barrier methods.
416  *
417  *	void bus_space_barrier(bus_space_tag_t tag,
418  *	    bus_space_handle_t bsh, bus_size_t offset,
419  *	    bus_size_t len, int flags);
420  *
421  * Note: the i386 does not currently require barriers, but we must
422  * provide the flags to MI code.
423  */
424 #define	bus_space_barrier(t, h, o, l, f)	\
425 	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
426 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
427 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
428 
429 #define	BUS_SPACE_MAP_CACHEABLE		0x0001
430 #define	BUS_SPACE_MAP_LINEAR		0x0002
431 #define	BUS_SPACE_MAP_PREFETCHABLE	0x0008
432 
433 /*
434  *	void *bus_space_vaddr(bus_space_tag_t, bus_space_handle_t);
435  *
436  * Get the kernel virtual address for the mapped bus space.
437  * Only allowed for regions mapped with BUS_SPACE_MAP_LINEAR.
438  */
439 #define bus_space_vaddr(t, h) \
440 	((t) == I386_BUS_SPACE_IO ? (void *)(NULL) : (void *)(h))
441 
442 /*
443  * Flags used in various bus DMA methods.
444  */
445 #define	BUS_DMA_WAITOK		0x0000	/* safe to sleep (pseudo-flag) */
446 #define	BUS_DMA_NOWAIT		0x0001	/* not safe to sleep */
447 #define	BUS_DMA_ALLOCNOW	0x0002	/* perform resource allocation now */
448 #define	BUS_DMA_COHERENT	0x0004	/* hint: map memory DMA coherent */
449 #define	BUS_DMA_BUS1		0x0010	/* placeholders for bus functions... */
450 #define	BUS_DMA_BUS2		0x0020
451 #define	BUS_DMA_BUS3		0x0040
452 #define	BUS_DMA_24BIT		0x0080	/* isadma map */
453 #define	BUS_DMA_STREAMING	0x0100	/* hint: sequential, unidirectional */
454 #define	BUS_DMA_READ		0x0200	/* mapping is device -> memory only */
455 #define	BUS_DMA_WRITE		0x0400	/* mapping is memory -> device only */
456 #define	BUS_DMA_NOCACHE		0x0800	/* map memory uncached */
457 #define	BUS_DMA_ZERO		0x1000	/* dmamem_alloc return zeroed mem */
458 #define	BUS_DMA_SG		0x2000	/* Internal. memory is for SG map */
459 
460 /* types for _dm_buftype */
461 #define	BUS_BUFTYPE_INVALID	0
462 #define	BUS_BUFTYPE_LINEAR	1
463 #define	BUS_BUFTYPE_MBUF	2
464 #define	BUS_BUFTYPE_UIO		3
465 #define	BUS_BUFTYPE_RAW		4
466 
467 /* Forwards needed by prototypes below. */
468 struct mbuf;
469 struct proc;
470 struct uio;
471 
472 /*
473  * Operations performed by bus_dmamap_sync().
474  */
475 #define BUS_DMASYNC_PREREAD	0x01
476 #define BUS_DMASYNC_POSTREAD	0x02
477 #define BUS_DMASYNC_PREWRITE	0x04
478 #define BUS_DMASYNC_POSTWRITE	0x08
479 
480 typedef struct bus_dma_tag		*bus_dma_tag_t;
481 typedef struct bus_dmamap		*bus_dmamap_t;
482 
483 /*
484  *	bus_dma_segment_t
485  *
486  *	Describes a single contiguous DMA transaction.  Values
487  *	are suitable for programming into DMA registers.
488  */
489 struct bus_dma_segment {
490 	bus_addr_t	ds_addr;	/* DMA address */
491 	bus_size_t	ds_len;		/* length of transfer */
492 	/*
493 	 * Ugh. need this so can pass alignment down from bus_dmamem_alloc
494 	 * to scatter gather maps. only the first one is used so the rest is
495 	 * wasted space. bus_dma could do with fixing the api for this.
496 	 */
497 	 bus_size_t	_ds_boundary;	/* don't cross */
498 	 bus_size_t	_ds_align;	/* align to me */
499 };
500 typedef struct bus_dma_segment	bus_dma_segment_t;
501 
502 /*
503  *	bus_dma_tag_t
504  *
505  *	A machine-dependent opaque type describing the implementation of
506  *	DMA for a given bus.
507  */
508 
509 struct bus_dma_tag {
510 	void	*_cookie;		/* cookie used in the guts */
511 
512 	/*
513 	 * DMA mapping methods.
514 	 */
515 	int	(*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
516 		    bus_size_t, bus_size_t, int, bus_dmamap_t *);
517 	void	(*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
518 	int	(*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
519 		    bus_size_t, struct proc *, int);
520 	int	(*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
521 		    struct mbuf *, int);
522 	int	(*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
523 		    struct uio *, int);
524 	int	(*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
525 		    bus_dma_segment_t *, int, bus_size_t, int);
526 	void	(*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
527 	void	(*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
528 		    bus_addr_t, bus_size_t, int);
529 
530 	/*
531 	 * DMA memory utility functions.
532 	 */
533 	int	(*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
534 		    bus_size_t, bus_dma_segment_t *, int, int *, int);
535 	void	(*_dmamem_free)(bus_dma_tag_t,
536 		    bus_dma_segment_t *, int);
537 	int	(*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
538 		    int, size_t, caddr_t *, int);
539 	void	(*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
540 	paddr_t	(*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
541 		    int, off_t, int, int);
542 };
543 
544 #define	bus_dmamap_create(t, s, n, m, b, f, p)			\
545 	(*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
546 #define	bus_dmamap_destroy(t, p)				\
547 	(*(t)->_dmamap_destroy)((t), (p))
548 #define	bus_dmamap_load(t, m, b, s, p, f)			\
549 	(*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
550 #define	bus_dmamap_load_mbuf(t, m, b, f)			\
551 	(*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
552 #define	bus_dmamap_load_uio(t, m, u, f)				\
553 	(*(t)->_dmamap_load_uio)((t), (m), (u), (f))
554 #define	bus_dmamap_load_raw(t, m, sg, n, s, f)			\
555 	(*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
556 #define	bus_dmamap_unload(t, p)					\
557 	(*(t)->_dmamap_unload)((t), (p))
558 #define	bus_dmamap_sync(t, p, o, l, ops)			\
559 	(void)((t)->_dmamap_sync ?				\
560 	    (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
561 
562 #define	bus_dmamem_alloc(t, s, a, b, sg, n, r, f)		\
563 	(*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
564 #define	bus_dmamem_free(t, sg, n)				\
565 	(*(t)->_dmamem_free)((t), (sg), (n))
566 #define	bus_dmamem_map(t, sg, n, s, k, f)			\
567 	(*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
568 #define	bus_dmamem_unmap(t, k, s)				\
569 	(*(t)->_dmamem_unmap)((t), (k), (s))
570 #define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
571 	(*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
572 
573 /*
574  *	bus_dmamap_t
575  *
576  *	Describes a DMA mapping.
577  */
578 struct bus_dmamap {
579 	/*
580 	 * PRIVATE MEMBERS: not for use by machine-independent code.
581 	 */
582 	bus_size_t	_dm_size;	/* largest DMA transfer mappable */
583 	int		_dm_segcnt;	/* number of segs this map can map */
584 	bus_size_t	_dm_maxsegsz;	/* largest possible segment */
585 	bus_size_t	_dm_boundary;	/* don't cross this */
586 	int		_dm_flags;	/* misc. flags */
587 
588 	void		*_dm_cookie;	/* cookie for bus-specific functions */
589 
590 	/*
591 	 * PUBLIC MEMBERS: these are used by machine-independent code.
592 	 */
593 	bus_size_t	dm_mapsize;	/* size of the mapping */
594 	int		dm_nsegs;	/* # valid segments in mapping */
595 	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
596 };
597 
598 int	_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
599 	    bus_size_t, int, bus_dmamap_t *);
600 void	_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
601 int	_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
602 	    bus_size_t, struct proc *, int);
603 int	_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
604 	    struct mbuf *, int);
605 int	_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
606 	    struct uio *, int);
607 int	_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
608 	    bus_dma_segment_t *, int, bus_size_t, int);
609 void	_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
610 void	_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
611 	    bus_size_t, int);
612 
613 int	_bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
614 	    bus_size_t alignment, bus_size_t boundary,
615 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
616 void	_bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
617 	    int nsegs);
618 int	_bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
619 	    int nsegs, size_t size, caddr_t *kvap, int flags);
620 void	_bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
621 	    size_t size);
622 paddr_t	_bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
623 	    int nsegs, off_t off, int prot, int flags);
624 
625 int	_bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
626 	    bus_size_t alignment, bus_size_t boundary,
627 	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
628 	    paddr_t low, paddr_t high);
629 
630 struct extent;
631 
632 /* Scatter gather bus_dma functions. */
633 struct sg_cookie {
634 	struct mutex	 sg_mtx;
635 	struct extent	*sg_ex;
636 	void		*sg_hdl;
637 	void		(*bind_page)(void *, bus_addr_t, paddr_t, int);
638 	void		(*unbind_page)(void *, bus_addr_t);
639 	void		(*flush_tlb)(void *);
640 };
641 
642 /*
643  * per-map DVMA page table
644  */
645 struct sg_page_entry {
646 	SPLAY_ENTRY(sg_page_entry)	spe_node;
647 	paddr_t				spe_pa;
648 	bus_addr_t			spe_va;
649 };
650 
651 /* for sg_dma this will be in the map's dm_cookie. */
652 struct sg_page_map {
653 	SPLAY_HEAD(sg_page_tree, sg_page_entry) spm_tree;
654 
655 	void			*spm_origbuf;	/* pointer to original data */
656 	int			 spm_buftype;	/* type of data */
657 	struct proc		*spm_proc;	/* proc that owns the mapping */
658 
659 	int			 spm_maxpage;	/* Size of allocated page map */
660 	int			 spm_pagecnt;	/* Number of entries in use */
661 	bus_addr_t		 spm_start;	/* dva when bound */
662 	bus_size_t		 spm_size;	/* size of bound map */
663 	struct sg_page_entry	 spm_map[1];
664 };
665 
666 struct sg_cookie	*sg_dmatag_init(char *, void *, bus_addr_t, bus_size_t,
667 			    void (*)(void *, vaddr_t, paddr_t, int),
668 			    void (*)(void *, vaddr_t), void (*)(void *));
669 void	sg_dmatag_destroy(struct sg_cookie *);
670 int	sg_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
671 	    bus_size_t, int, bus_dmamap_t *);
672 void	sg_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
673 void	sg_dmamap_set_alignment(bus_dma_tag_t, bus_dmamap_t, u_long);
674 int	sg_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
675 	    struct proc *, int);
676 int	sg_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
677 	    struct mbuf *, int);
678 int	sg_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t, struct uio *, int);
679 int	sg_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t, bus_dma_segment_t *,
680 	    int, bus_size_t, int);
681 void	sg_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
682 int	sg_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t,
683 	    struct proc *, int, int *, int);
684 int	sg_dmamap_load_physarray(bus_dma_tag_t, bus_dmamap_t, paddr_t *,
685 	    int, int, int *, int);
686 int	sg_dmamem_alloc(bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t,
687 	    bus_dma_segment_t *, int, int *, int);
688 
689 
690 #endif /* _I386_BUS_H_ */
691