Annotation of sys/arch/i386/include/bus.h, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: bus.h,v 1.40 2007/02/20 21:15:01 tom 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: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the NetBSD
23: * Foundation, Inc. and its contributors.
24: * 4. Neither the name of The NetBSD Foundation nor the names of its
25: * contributors may be used to endorse or promote products derived
26: * from this software without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38: * POSSIBILITY OF SUCH DAMAGE.
39: */
40:
41: /*
42: * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
43: * Copyright (c) 1996 Jason R. Thorpe. All rights reserved.
44: * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
45: *
46: * Redistribution and use in source and binary forms, with or without
47: * modification, are permitted provided that the following conditions
48: * are met:
49: * 1. Redistributions of source code must retain the above copyright
50: * notice, this list of conditions and the following disclaimer.
51: * 2. Redistributions in binary form must reproduce the above copyright
52: * notice, this list of conditions and the following disclaimer in the
53: * documentation and/or other materials provided with the distribution.
54: * 3. All advertising materials mentioning features or use of this software
55: * must display the following acknowledgement:
56: * This product includes software developed by Christopher G. Demetriou
57: * for the NetBSD Project.
58: * 4. The name of the author may not be used to endorse or promote products
59: * derived from this software without specific prior written permission
60: *
61: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
62: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
63: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
64: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
65: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
66: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
67: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
68: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
69: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
70: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
71: */
72:
73: #ifndef _I386_BUS_H_
74: #define _I386_BUS_H_
75:
76: #include <machine/pio.h>
77:
78: /*
79: * Values for the i386 bus space tag, not to be used directly by MI code.
80: */
81: #define I386_BUS_SPACE_IO 0 /* space is i/o space */
82: #define I386_BUS_SPACE_MEM 1 /* space is mem space */
83:
84: /*
85: * Bus address and size types
86: */
87: typedef u_long bus_addr_t;
88: typedef u_long bus_size_t;
89:
90: /*
91: * Access methods for bus resources and address space.
92: */
93: typedef int bus_space_tag_t;
94: typedef u_long bus_space_handle_t;
95:
96: int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
97: bus_size_t size, int cacheable, bus_space_handle_t *bshp);
98: /* like bus_space_map(), but without extent map checking/allocation */
99: int _bus_space_map(bus_space_tag_t t, bus_addr_t addr,
100: bus_size_t size, int cacheable, bus_space_handle_t *bshp);
101: void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
102: bus_size_t size);
103: /* like bus_space_unmap(), but without extent map deallocation */
104: void _bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
105: bus_size_t, bus_addr_t *);
106: int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
107: bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
108:
109: int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
110: bus_addr_t rend, bus_size_t size, bus_size_t align,
111: bus_size_t boundary, int cacheable, bus_addr_t *addrp,
112: bus_space_handle_t *bshp);
113: void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
114: bus_size_t size);
115:
116: /*
117: * u_intN_t bus_space_read_N(bus_space_tag_t tag,
118: * bus_space_handle_t bsh, bus_size_t offset);
119: *
120: * Read a 1, 2, 4, or 8 byte quantity from bus space
121: * described by tag/handle/offset.
122: */
123:
124: #define bus_space_read_1(t, h, o) \
125: ((t) == I386_BUS_SPACE_IO ? (inb((h) + (o))) : \
126: (*(volatile u_int8_t *)((h) + (o))))
127:
128: #define bus_space_read_2(t, h, o) \
129: ((t) == I386_BUS_SPACE_IO ? (inw((h) + (o))) : \
130: (*(volatile u_int16_t *)((h) + (o))))
131:
132: #define bus_space_read_4(t, h, o) \
133: ((t) == I386_BUS_SPACE_IO ? (inl((h) + (o))) : \
134: (*(volatile u_int32_t *)((h) + (o))))
135:
136: #if 0 /* Cause a link error for bus_space_read_8 */
137: #define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!!
138: #endif
139:
140: /*
141: * void bus_space_read_multi_N(bus_space_tag_t tag,
142: * bus_space_handle_t bsh, bus_size_t offset,
143: * u_intN_t *addr, size_t count);
144: *
145: * Read `count' 1, 2, 4, or 8 byte quantities from bus space
146: * described by tag/handle/offset and copy into buffer provided.
147: */
148:
149: #define bus_space_read_multi_1(t, h, o, a, cnt) do { \
150: if ((t) == I386_BUS_SPACE_IO) { \
151: insb((h) + (o), (a), (cnt)); \
152: } else {void *_addr=(a); int _cnt=(cnt); \
153: __asm __volatile(" \
154: cld ; \
155: 1: movb (%2),%%al ; \
156: stosb ; \
157: loop 1b" : \
158: "+D" (_addr), "+c" (_cnt) : "r" ((h) + (o)) : \
159: "%eax", "memory", "cc"); \
160: } \
161: } while (0)
162:
163: #define bus_space_read_multi_2(t, h, o, a, cnt) do { \
164: if ((t) == I386_BUS_SPACE_IO) { \
165: insw((h) + (o), (a), (cnt)); \
166: } else {void *_addr=(a); int _cnt=(cnt); \
167: __asm __volatile(" \
168: cld ; \
169: 1: movw (%2),%%ax ; \
170: stosw ; \
171: loop 1b" : \
172: "+D" (_addr), "+c" (_cnt) : "r" ((h) + (o)) : \
173: "%eax", "memory", "cc"); \
174: } \
175: } while (0)
176:
177: #define bus_space_read_multi_4(t, h, o, a, cnt) do { \
178: if ((t) == I386_BUS_SPACE_IO) { \
179: insl((h) + (o), (a), (cnt)); \
180: } else {void *_addr=(a); int _cnt=(cnt); \
181: __asm __volatile(" \
182: cld ; \
183: 1: movl (%2),%%eax ; \
184: stosl ; \
185: loop 1b" : \
186: "+D" (_addr), "+c" (_cnt) : "r" ((h) + (o)) : \
187: "%eax", "memory", "cc"); \
188: } \
189: } while (0)
190:
191: #if 0 /* Cause a link error for bus_space_read_multi_8 */
192: #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!!
193: #endif
194:
195: /*
196: * void bus_space_read_raw_multi_N(bus_space_tag_t tag,
197: * bus_space_handle_t bsh, bus_size_t offset,
198: * u_int8_t *addr, size_t count);
199: *
200: * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
201: * described by tag/handle/offset and copy into buffer provided. The buffer
202: * must have proper alignment for the N byte wide entities. Furthermore
203: * possible byte-swapping should be done by these functions.
204: */
205:
206: #define bus_space_read_raw_multi_2(t, h, o, a, c) \
207: bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
208: #define bus_space_read_raw_multi_4(t, h, o, a, c) \
209: bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
210:
211: #if 0 /* Cause a link error for bus_space_read_raw_multi_8 */
212: #define bus_space_read_raw_multi_8 \
213: !!! bus_space_read_raw_multi_8 unimplemented !!!
214: #endif
215:
216: /*
217: * void bus_space_read_region_N(bus_space_tag_t tag,
218: * bus_space_handle_t bsh, bus_size_t offset,
219: * u_intN_t *addr, size_t count);
220: *
221: * Read `count' 1, 2, 4, or 8 byte quantities from bus space
222: * described by tag/handle and starting at `offset' and copy into
223: * buffer provided.
224: */
225:
226: #define bus_space_read_region_1(t, h, o, a, cnt) do { \
227: int _cnt = (cnt); void *_addr = (a); int _port = (h)+(o); \
228: if ((t) == I386_BUS_SPACE_IO) { \
229: __asm __volatile(" \
230: cld ; \
231: 1: inb %w2,%%al ; \
232: stosb ; \
233: incl %2 ; \
234: loop 1b" : \
235: "+D" (_addr), "+c" (_cnt), "+d" (_port) :: \
236: "%eax", "memory", "cc"); \
237: } else \
238: i386_space_copy(_port, _addr, 1, _cnt); \
239: } while (0)
240:
241: #define bus_space_read_region_2(t, h, o, a, cnt) do { \
242: int _cnt = (cnt); void *_addr = (a); int _port = (h)+(o); \
243: if ((t) == I386_BUS_SPACE_IO) { \
244: __asm __volatile(" \
245: cld ; \
246: 1: inw %w2,%%ax ; \
247: stosw ; \
248: addl $2,%2 ; \
249: loop 1b" : \
250: "+D" (_addr), "+c" (_cnt), "+d" (_port) :: \
251: "%eax", "memory", "cc"); \
252: } else \
253: i386_space_copy(_port, _addr, 2, _cnt); \
254: } while (0)
255:
256: #define bus_space_read_region_4(t, h, o, a, cnt) do { \
257: int _cnt = (cnt); void *_addr = (a); int _port = (h)+(o); \
258: if ((t) == I386_BUS_SPACE_IO) { \
259: __asm __volatile(" \
260: cld ; \
261: 1: inl %w2,%%eax ; \
262: stosl ; \
263: addl $4,%2 ; \
264: loop 1b" : \
265: "+D" (_addr), "+c" (_cnt), "+d" (_port) :: \
266: "%eax", "memory", "cc"); \
267: } else \
268: i386_space_copy(_port, _addr, 4, _cnt); \
269: } while (0)
270:
271: #if 0 /* Cause a link error for bus_space_read_region_8 */
272: #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
273: #endif
274:
275: /*
276: * void bus_space_read_raw_region_N(bus_space_tag_t tag,
277: * bus_space_handle_t bsh, bus_size_t offset,
278: * u_int8_t *addr, size_t count);
279: *
280: * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
281: * described by tag/handle and starting at `offset' and copy into
282: * buffer provided. The buffer must have proper alignment for the N byte
283: * wide entities. Furthermore possible byte-swapping should be done by
284: * these functions.
285: */
286:
287: #define bus_space_read_raw_region_2(t, h, o, a, c) \
288: bus_space_read_region_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
289: #define bus_space_read_raw_region_4(t, h, o, a, c) \
290: bus_space_read_region_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
291:
292: #if 0 /* Cause a link error for bus_space_read_raw_region_8 */
293: #define bus_space_read_raw_region_8 \
294: !!! bus_space_read_raw_region_8 unimplemented !!!
295: #endif
296:
297: /*
298: * void bus_space_write_N(bus_space_tag_t tag,
299: * bus_space_handle_t bsh, bus_size_t offset,
300: * u_intN_t value);
301: *
302: * Write the 1, 2, 4, or 8 byte value `value' to bus space
303: * described by tag/handle/offset.
304: */
305:
306: #define bus_space_write_1(t, h, o, v) do { \
307: if ((t) == I386_BUS_SPACE_IO) \
308: outb((h) + (o), (v)); \
309: else \
310: ((void)(*(volatile u_int8_t *)((h) + (o)) = (v))); \
311: } while (0)
312:
313: #define bus_space_write_2(t, h, o, v) do { \
314: if ((t) == I386_BUS_SPACE_IO) \
315: outw((h) + (o), (v)); \
316: else \
317: ((void)(*(volatile u_int16_t *)((h) + (o)) = (v))); \
318: } while (0)
319:
320: #define bus_space_write_4(t, h, o, v) do { \
321: if ((t) == I386_BUS_SPACE_IO) \
322: outl((h) + (o), (v)); \
323: else \
324: ((void)(*(volatile u_int32_t *)((h) + (o)) = (v))); \
325: } while (0)
326:
327: #if 0 /* Cause a link error for bus_space_write_8 */
328: #define bus_space_write_8 !!! bus_space_write_8 not implemented !!!
329: #endif
330:
331: /*
332: * void bus_space_write_multi_N(bus_space_tag_t tag,
333: * bus_space_handle_t bsh, bus_size_t offset,
334: * const u_intN_t *addr, size_t count);
335: *
336: * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
337: * provided to bus space described by tag/handle/offset.
338: */
339:
340: #define bus_space_write_multi_1(t, h, o, a, cnt) do { \
341: if ((t) == I386_BUS_SPACE_IO) { \
342: outsb((h) + (o), (a), (cnt)); \
343: } else {const void *_addr=(a); int _cnt=(cnt); \
344: __asm __volatile(" \
345: cld ; \
346: 1: lodsb ; \
347: movb %%al,(%2) ; \
348: loop 1b" : \
349: "+S" (_addr), "+c" (_cnt) : "r" ((h) + (o)) : \
350: "%eax", "memory", "cc"); \
351: } \
352: } while (0)
353:
354: #define bus_space_write_multi_2(t, h, o, a, cnt) do { \
355: if ((t) == I386_BUS_SPACE_IO) { \
356: outsw((h) + (o), (a), (cnt)); \
357: } else {const void *_addr=(a); int _cnt=(cnt); \
358: __asm __volatile(" \
359: cld ; \
360: 1: lodsw ; \
361: movw %%ax,(%2) ; \
362: loop 1b" : \
363: "+S" (_addr), "+c" (_cnt) : "r" ((h) + (o)) : \
364: "%eax", "memory", "cc"); \
365: } \
366: } while (0)
367:
368: #define bus_space_write_multi_4(t, h, o, a, cnt) do { \
369: if ((t) == I386_BUS_SPACE_IO) { \
370: outsl((h) + (o), (a), (cnt)); \
371: } else {const void *_addr=(a); int _cnt=(cnt); \
372: __asm __volatile(" \
373: cld ; \
374: 1: lodsl ; \
375: movl %%eax,(%2) ; \
376: loop 1b" : \
377: "+S" (_addr), "+c" (_cnt) : "r" ((h) + (o)) : \
378: "%eax", "memory", "cc"); \
379: } \
380: } while (0)
381:
382: #if 0 /* Cause a link error for bus_space_write_multi_8 */
383: #define bus_space_write_multi_8(t, h, o, a, c) \
384: !!! bus_space_write_multi_8 unimplemented !!!
385: #endif
386:
387: /*
388: * void bus_space_write_raw_multi_N(bus_space_tag_t tag,
389: * bus_space_handle_t bsh, bus_size_t offset,
390: * const u_int8_t *addr, size_t count);
391: *
392: * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer
393: * provided to bus space described by tag/handle/offset. The buffer
394: * must have proper alignment for the N byte wide entities. Furthermore
395: * possible byte-swapping should be done by these functions.
396: */
397:
398: #define bus_space_write_raw_multi_2(t, h, o, a, c) \
399: bus_space_write_multi_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
400: #define bus_space_write_raw_multi_4(t, h, o, a, c) \
401: bus_space_write_multi_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
402:
403: #if 0 /* Cause a link error for bus_space_write_raw_multi_8 */
404: #define bus_space_write_raw_multi_8 \
405: !!! bus_space_write_raw_multi_8 unimplemented !!!
406: #endif
407:
408: /*
409: * void bus_space_write_region_N(bus_space_tag_t tag,
410: * bus_space_handle_t bsh, bus_size_t offset,
411: * const u_intN_t *addr, size_t count);
412: *
413: * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
414: * to bus space described by tag/handle starting at `offset'.
415: */
416:
417: #define bus_space_write_region_1(t, h, o, a, cnt) do { \
418: int _port = (h)+(o); const void *_addr=(a); int _cnt=(cnt); \
419: if ((t) == I386_BUS_SPACE_IO) { \
420: __asm __volatile(" \
421: cld ; \
422: 1: lodsb ; \
423: outb %%al,%w0 ; \
424: incl %0 ; \
425: loop 1b" : \
426: "+d" (_port), "+S" (_addr), "+c" (_cnt) :: \
427: "%eax", "memory", "cc"); \
428: } else \
429: i386_space_copy(_addr, _port, 1, _cnt); \
430: } while (0)
431:
432: #define bus_space_write_region_2(t, h, o, a, cnt) do { \
433: int _port = (h)+(o); const void *_addr=(a); int _cnt=(cnt); \
434: if ((t) == I386_BUS_SPACE_IO) { \
435: __asm __volatile(" \
436: cld ; \
437: 1: lodsw ; \
438: outw %%ax,%w0 ; \
439: addl $2,%0 ; \
440: loop 1b" : \
441: "+d" (_port), "+S" (_addr), "+c" (_cnt) :: \
442: "%eax", "memory", "cc"); \
443: } else \
444: i386_space_copy(_addr, _port, 2, _cnt); \
445: } while (0)
446:
447: #define bus_space_write_region_4(t, h, o, a, cnt) do { \
448: int _port = (h)+(o); const void *_addr=(a); int _cnt=(cnt); \
449: if ((t) == I386_BUS_SPACE_IO) { \
450: __asm __volatile(" \
451: cld ; \
452: 1: lodsl ; \
453: outl %%eax,%w0 ; \
454: addl $4,%0 ; \
455: loop 1b" : \
456: "+d" (_port), "+S" (_addr), "+c" (_cnt) :: \
457: "%eax", "memory", "cc"); \
458: } else \
459: i386_space_copy(_addr, _port, 4, _cnt); \
460: } while (0)
461:
462: #if 0 /* Cause a link error for bus_space_write_region_8 */
463: #define bus_space_write_region_8 \
464: !!! bus_space_write_region_8 unimplemented !!!
465: #endif
466:
467: /*
468: * void bus_space_write_raw_region_N(bus_space_tag_t tag,
469: * bus_space_handle_t bsh, bus_size_t offset,
470: * const u_int8_t *addr, size_t count);
471: *
472: * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space
473: * described by tag/handle and starting at `offset' from the
474: * buffer provided. The buffer must have proper alignment for the N byte
475: * wide entities. Furthermore possible byte-swapping should be done by
476: * these functions.
477: */
478:
479: #define bus_space_write_raw_region_2(t, h, o, a, c) \
480: bus_space_write_region_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
481: #define bus_space_write_raw_region_4(t, h, o, a, c) \
482: bus_space_write_region_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
483:
484: #if 0 /* Cause a link error for bus_space_write_raw_region_8 */
485: #define bus_space_write_raw_region_8 \
486: !!! bus_space_write_raw_region_8 unimplemented !!!
487: #endif
488:
489: /*
490: * void bus_space_set_multi_N(bus_space_tag_t tag,
491: * bus_space_handle_t bsh, bus_size_t offset,
492: * u_intN_t val, size_t count);
493: *
494: * Write the 1, 2, 4, or 8 byte value `val' to bus space described
495: * by tag/handle/offset `count' times.
496: */
497:
498: #define bus_space_set_multi_1(t, h, o, v, cnt) do { \
499: int _cnt=(cnt); \
500: if ((t) == I386_BUS_SPACE_IO) { \
501: __asm __volatile(" \
502: cld ; \
503: 1: outb %b2, %w1 ; \
504: loop 1b" : \
505: "+c" (_cnt) : "d" ((h) + (o)), "a" ((v)) : \
506: "cc"); \
507: } else { \
508: __asm __volatile(" \
509: cld ; \
510: 1: movb %b2, (%1) ; \
511: loop 1b" : \
512: "+c" (_cnt) : "D" ((h) + (o)), "a" ((v)) : \
513: "cc", "memory"); \
514: } \
515: } while (0)
516:
517: #define bus_space_set_multi_2(t, h, o, v, cnt) do { \
518: int _cnt=(cnt); \
519: if ((t) == I386_BUS_SPACE_IO) { \
520: __asm __volatile(" \
521: cld ; \
522: 1: outw %w2, %w1 ; \
523: loop 1b" : \
524: "+c" (_cnt) : "d" ((h) + (o)), "a" ((v)) : \
525: "cc"); \
526: } else { \
527: __asm __volatile(" \
528: cld ; \
529: 1: movw %w2, (%1) ; \
530: loop 1b" : \
531: "+c" (_cnt) : "D" ((h) + (o)), "a" ((v)) : \
532: "cc", "memory"); \
533: } \
534: } while (0)
535:
536: #define bus_space_set_multi_4(t, h, o, v, cnt) do { \
537: int _cnt=(cnt); \
538: if ((t) == I386_BUS_SPACE_IO) { \
539: __asm __volatile(" \
540: cld ; \
541: 1: outl %2,%w1 ; \
542: loop 1b" : \
543: "+c" (_cnt) : "d" ((h) + (o)), "a" ((v)) : \
544: "cc"); \
545: } else { \
546: __asm __volatile(" \
547: cld ; \
548: 1: movl %2,(%1) ; \
549: loop 1b" : \
550: "+c" (_cnt) : "D" ((h) + (o)), "a" ((v)) : \
551: "cc", "memory"); \
552: } \
553: } while (0)
554:
555: #if 0 /* Cause a link error for bus_space_set_multi_8 */
556: #define bus_space_set_multi_8 \
557: !!! bus_space_set_multi_8 unimplemented !!!
558: #endif
559:
560: /*
561: * void bus_space_set_region_N(bus_space_tag_t tag,
562: * bus_space_handle_t bsh, bus_size_t offset,
563: * u_intN_t val, size_t count);
564: *
565: * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
566: * by tag/handle starting at `offset'.
567: */
568:
569: #define bus_space_set_region_1(t, h, o, v, cnt) do { \
570: int _port = (h)+(o); int _cnt = (cnt); \
571: if ((t) == I386_BUS_SPACE_IO) { \
572: __asm __volatile(" \
573: 1: outb %%al,%w0 ; \
574: incl %0 ; \
575: loop 1b" : \
576: "+d" (_port), "+c" (_cnt) : "a" ((v)) : \
577: "cc"); \
578: } else { \
579: __asm __volatile(" \
580: cld ; \
581: repne ; \
582: stosb" : \
583: "+D" (_port), "+c" (_cnt) : "a" ((v)) : \
584: "memory", "cc"); \
585: } \
586: } while (0)
587:
588: #define bus_space_set_region_2(t, h, o, v, cnt) do { \
589: int _port = (h)+(o); int _cnt = (cnt); \
590: if ((t) == I386_BUS_SPACE_IO) { \
591: __asm __volatile(" \
592: 1: outw %%ax,%w0 ; \
593: addl $2, %0 ; \
594: loop 1b" : \
595: "+d" (_port), "+c" (_cnt) : "a" ((v)) : \
596: "cc"); \
597: } else { \
598: __asm __volatile(" \
599: cld ; \
600: repne ; \
601: stosw" : \
602: "+D" (_port), "+c" (_cnt) : "a" ((v)) : \
603: "memory", "cc"); \
604: } \
605: } while (0)
606:
607: #define bus_space_set_region_4(t, h, o, v, cnt) do { \
608: int _port = (h)+(o); int _cnt = (cnt); \
609: if ((t) == I386_BUS_SPACE_IO) { \
610: __asm __volatile(" \
611: 1: outl %%eax,%w0 ; \
612: addl $4, %0 ; \
613: loop 1b" : \
614: "+d" (_port), "+c" (_cnt) : "a" ((v)) : \
615: "cc"); \
616: } else { \
617: __asm __volatile(" \
618: cld ; \
619: repne ; \
620: stosl" : \
621: "+D" (_port), "+c" (_cnt) : "a" ((v)) : \
622: "memory", "cc"); \
623: } \
624: } while (0)
625:
626: #if 0 /* Cause a link error for bus_space_set_region_8 */
627: #define bus_space_set_region_8 \
628: !!! bus_space_set_region_8 unimplemented !!!
629: #endif
630:
631: /*
632: * void bus_space_copy_N(bus_space_tag_t tag,
633: * bus_space_handle_t bsh1, bus_size_t off1,
634: * bus_space_handle_t bsh2, bus_size_t off2,
635: * size_t count);
636: *
637: * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
638: * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
639: */
640:
641: #define bus_space_copy_1(t, h1, o1, h2, o2, cnt) do { \
642: int _port1 = (h1)+(o1); int _port2 = (h2)+(o2); int _cnt=(cnt); \
643: if ((t) == I386_BUS_SPACE_IO) { \
644: __asm __volatile(" \
645: 1: movl %k1,%%edx ; \
646: inb %%dx,%%al ; \
647: movl %k0,%%edx ; \
648: outb %%al,%%dx ; \
649: incl %0 ; \
650: incl %1 ; \
651: loop 1b" : \
652: "+D" (_port2), "+S" (_port1), "+c" ((_cnt)) :: \
653: "%edx", "%eax", "cc"); \
654: } else \
655: i386_space_copy(_port1, _port2, 1, _cnt); \
656: } while (0)
657:
658: #define bus_space_copy_2(t, h1, o1, h2, o2, cnt) do { \
659: int _port1 = (h1)+(o1); int _port2 = (h2)+(o2); int _cnt=(cnt); \
660: if ((t) == I386_BUS_SPACE_IO) { \
661: __asm __volatile(" \
662: 1: movl %k1,%%edx ; \
663: inw %%dx,%%ax ; \
664: movl %k0,%%edx ; \
665: outw %%ax,%%dx ; \
666: addl $2, %0 ; \
667: addl $2, %1 ; \
668: loop 1b" : \
669: "+D" (_port2), "+ES" (_port1), "+c" ((_cnt)) :: \
670: "%edx", "%eax", "cc"); \
671: } else \
672: i386_space_copy(_port1, _port2, 2, _cnt); \
673: } while (0)
674:
675: #define bus_space_copy_4(t, h1, o1, h2, o2, cnt) do { \
676: int _port1 = (h1)+(o1); int _port2 = (h2)+(o2); int _cnt=(cnt); \
677: if ((t) == I386_BUS_SPACE_IO) { \
678: __asm __volatile(" \
679: 1: movl %k1,%%edx ; \
680: inl %%dx,%%eax ; \
681: movl %k0,%%edx ; \
682: outl %%eax,%%dx ; \
683: addl $4, %0 ; \
684: addl $4, %1 ; \
685: loop 1b" : \
686: "+D" (_port2), "+ES" (_port1), "+c" ((_cnt)) :: \
687: "%edx", "%eax", "cc"); \
688: } else \
689: i386_space_copy(_port1, _port2, 4, _cnt); \
690: } while (0)
691:
692: #if 0 /* Cause a link error for bus_space_copy_8 */
693: #define bus_space_copy_8 \
694: !!! bus_space_copy_8 unimplemented !!!
695: #endif
696:
697: #define i386_space_copy1(a1, a2, cnt, movs, df) \
698: __asm __volatile(df "\n\trep\n\t" movs : \
699: "+S" (a1), "+D" (a2), "+c" (cnt) :: "memory", "cc");
700:
701: #define i386_space_copy(a1, a2, sz, cnt) do { \
702: if ((void *)(a1) < (void *)(a2)) { \
703: a1 += ((cnt) - 1) * (sz); a2 += ((cnt) - 1) * (sz); \
704: switch (sz) { \
705: case 1: i386_space_copy1(a1,a2,cnt,"movsb","std");break;\
706: case 2: i386_space_copy1(a1,a2,cnt,"movsw","std");break;\
707: case 4: i386_space_copy1(a1,a2,cnt,"movsl","std");break;\
708: } \
709: } else \
710: switch (sz) { \
711: case 1: i386_space_copy1(a1,a2,cnt,"movsb","cld");break;\
712: case 2: i386_space_copy1(a1,a2,cnt,"movsw","cld");break;\
713: case 4: i386_space_copy1(a1,a2,cnt,"movsl","cld");break;\
714: } \
715: } while (0)
716:
717: /*
718: * Bus read/write barrier methods.
719: *
720: * void bus_space_barrier(bus_space_tag_t tag,
721: * bus_space_handle_t bsh, bus_size_t offset,
722: * bus_size_t len, int flags);
723: *
724: * Note: the i386 does not currently require barriers, but we must
725: * provide the flags to MI code.
726: */
727: #define bus_space_barrier(t, h, o, l, f) \
728: ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
729: #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
730: #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
731: /* Compatibility defines */
732: #define BUS_BARRIER_READ BUS_SPACE_BARRIER_READ
733: #define BUS_BARRIER_WRITE BUS_SPACE_BARRIER_WRITE
734:
735: /*
736: * Flags used in various bus DMA methods.
737: */
738: #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */
739: #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */
740: #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */
741: #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */
742: #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */
743: #define BUS_DMA_BUS2 0x020
744: #define BUS_DMA_BUS3 0x040
745: #define BUS_DMA_24BIT 0x080 /* isadma map */
746: #define BUS_DMA_STREAMING 0x100 /* hint: sequential, unidirectional */
747: #define BUS_DMA_READ 0x200 /* mapping is device -> memory only */
748: #define BUS_DMA_WRITE 0x400 /* mapping is memory -> device only */
749:
750: /* Forwards needed by prototypes below. */
751: struct mbuf;
752: struct proc;
753: struct uio;
754:
755: /*
756: * Operations performed by bus_dmamap_sync().
757: */
758: #define BUS_DMASYNC_PREREAD 0x01
759: #define BUS_DMASYNC_POSTREAD 0x02
760: #define BUS_DMASYNC_PREWRITE 0x04
761: #define BUS_DMASYNC_POSTWRITE 0x08
762:
763: typedef struct i386_bus_dma_tag *bus_dma_tag_t;
764: typedef struct i386_bus_dmamap *bus_dmamap_t;
765:
766: /*
767: * bus_dma_segment_t
768: *
769: * Describes a single contiguous DMA transaction. Values
770: * are suitable for programming into DMA registers.
771: */
772: struct i386_bus_dma_segment {
773: bus_addr_t ds_addr; /* DMA address */
774: bus_size_t ds_len; /* length of transfer */
775: };
776: typedef struct i386_bus_dma_segment bus_dma_segment_t;
777:
778: /*
779: * bus_dma_tag_t
780: *
781: * A machine-dependent opaque type describing the implementation of
782: * DMA for a given bus.
783: */
784:
785: struct i386_bus_dma_tag {
786: void *_cookie; /* cookie used in the guts */
787:
788: /*
789: * DMA mapping methods.
790: */
791: int (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
792: bus_size_t, bus_size_t, int, bus_dmamap_t *);
793: void (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
794: int (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
795: bus_size_t, struct proc *, int);
796: int (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
797: struct mbuf *, int);
798: int (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
799: struct uio *, int);
800: int (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
801: bus_dma_segment_t *, int, bus_size_t, int);
802: void (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
803: void (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
804: bus_addr_t, bus_size_t, int);
805:
806: /*
807: * DMA memory utility functions.
808: */
809: int (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
810: bus_size_t, bus_dma_segment_t *, int, int *, int);
811: void (*_dmamem_free)(bus_dma_tag_t,
812: bus_dma_segment_t *, int);
813: int (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
814: int, size_t, caddr_t *, int);
815: void (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
816: paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
817: int, off_t, int, int);
818: };
819:
820: #define bus_dmamap_create(t, s, n, m, b, f, p) \
821: (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
822: #define bus_dmamap_destroy(t, p) \
823: (*(t)->_dmamap_destroy)((t), (p))
824: #define bus_dmamap_load(t, m, b, s, p, f) \
825: (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
826: #define bus_dmamap_load_mbuf(t, m, b, f) \
827: (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
828: #define bus_dmamap_load_uio(t, m, u, f) \
829: (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
830: #define bus_dmamap_load_raw(t, m, sg, n, s, f) \
831: (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
832: #define bus_dmamap_unload(t, p) \
833: (*(t)->_dmamap_unload)((t), (p))
834: #define bus_dmamap_sync(t, p, o, l, ops) \
835: (void)((t)->_dmamap_sync ? \
836: (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
837:
838: #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
839: (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
840: #define bus_dmamem_free(t, sg, n) \
841: (*(t)->_dmamem_free)((t), (sg), (n))
842: #define bus_dmamem_map(t, sg, n, s, k, f) \
843: (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
844: #define bus_dmamem_unmap(t, k, s) \
845: (*(t)->_dmamem_unmap)((t), (k), (s))
846: #define bus_dmamem_mmap(t, sg, n, o, p, f) \
847: (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
848:
849: /*
850: * bus_dmamap_t
851: *
852: * Describes a DMA mapping.
853: */
854: struct i386_bus_dmamap {
855: /*
856: * PRIVATE MEMBERS: not for use by machine-independent code.
857: */
858: bus_size_t _dm_size; /* largest DMA transfer mappable */
859: int _dm_segcnt; /* number of segs this map can map */
860: bus_size_t _dm_maxsegsz; /* largest possible segment */
861: bus_size_t _dm_boundary; /* don't cross this */
862: int _dm_flags; /* misc. flags */
863:
864: void *_dm_cookie; /* cookie for bus-specific functions */
865:
866: /*
867: * PUBLIC MEMBERS: these are used by machine-independent code.
868: */
869: bus_size_t dm_mapsize; /* size of the mapping */
870: int dm_nsegs; /* # valid segments in mapping */
871: bus_dma_segment_t dm_segs[1]; /* segments; variable length */
872: };
873:
874: #ifdef _I386_BUS_DMA_PRIVATE
875: int _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
876: bus_size_t, int, bus_dmamap_t *);
877: void _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
878: int _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
879: bus_size_t, struct proc *, int);
880: int _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
881: struct mbuf *, int);
882: int _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
883: struct uio *, int);
884: int _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
885: bus_dma_segment_t *, int, bus_size_t, int);
886: void _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
887: void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
888: bus_size_t, int);
889:
890: int _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
891: bus_size_t alignment, bus_size_t boundary,
892: bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
893: void _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
894: int nsegs);
895: int _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
896: int nsegs, size_t size, caddr_t *kvap, int flags);
897: void _bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
898: size_t size);
899: paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
900: int nsegs, off_t off, int prot, int flags);
901:
902: int _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
903: bus_size_t alignment, bus_size_t boundary,
904: bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
905: paddr_t low, paddr_t high);
906: #endif /* _I386_BUS_DMA_PRIVATE */
907:
908: #endif /* _I386_BUS_H_ */
CVSweb