FreeBSD/Linux Kernel Cross Reference
sys/i386/include/bus.h
1 /* $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 /*
41 * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
42 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by Christopher G. Demetriou
55 * for the NetBSD Project.
56 * 4. The name of the author may not be used to endorse or promote products
57 * derived from this software without specific prior written permission
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69 */
70 /* $FreeBSD: src/sys/i386/include/bus.h,v 1.3.2.2 1999/09/05 08:11:39 peter Exp $ */
71
72 #ifndef _I386_BUS_H_
73 #define _I386_BUS_H_
74
75 #include <machine/cpufunc.h>
76
77 /*
78 * Values for the i386 bus space tag, not to be used directly by MI code.
79 */
80 #define I386_BUS_SPACE_IO 0 /* space is i/o space */
81 #define I386_BUS_SPACE_MEM 1 /* space is mem space */
82
83 /*
84 * Bus address and size types
85 */
86 typedef u_long bus_addr_t;
87 typedef u_long bus_size_t;
88
89 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
90 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
91 #define BUS_SPACE_MAXSIZE (64 * 1024) /* Maximum supported size */
92 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
93 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
94 #define BUS_SPACE_MAXADDR 0xFFFFFFFF
95
96 #define BUS_SPACE_UNRESTRICTED (~0)
97
98 /*
99 * Access methods for bus resources and address space.
100 */
101 typedef int bus_space_tag_t;
102 typedef u_long bus_space_handle_t;
103
104 /*
105 * Map a region of device bus space into CPU virtual address space.
106 */
107
108 #define BUS_SPACE_MAP_CACHEABLE 0x01
109 #define BUS_SPACE_MAP_LINEAR 0x02
110
111 int bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
112 int flags, bus_space_handle_t *bshp);
113
114 /*
115 * Unmap a region of device bus space.
116 */
117
118 void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
119 bus_size_t size);
120
121 /*
122 * Get a new handle for a subregion of an already-mapped area of bus space.
123 */
124
125 int bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
126 bus_size_t offset, bus_size_t size,
127 bus_space_handle_t *nbshp);
128
129 /*
130 * Allocate a region of memory that is accessible to devices in bus space.
131 */
132
133 int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
134 bus_addr_t rend, bus_size_t size, bus_size_t align,
135 bus_size_t boundary, int flags, bus_addr_t *addrp,
136 bus_space_handle_t *bshp);
137
138 /*
139 * Free a region of bus space accessible memory.
140 */
141
142 void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
143 bus_size_t size);
144
145 #if defined(_I386_BUS_PIO_H_) || defined(_I386_BUS_MEMIO_H_)
146
147 /*
148 * Read a 1, 2, 4, or 8 byte quantity from bus space
149 * described by tag/handle/offset.
150 */
151 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
152 bus_space_handle_t handle,
153 bus_size_t offset);
154
155 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
156 bus_space_handle_t handle,
157 bus_size_t offset);
158
159 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
160 bus_space_handle_t handle,
161 bus_size_t offset);
162
163 static __inline u_int8_t
164 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
165 bus_size_t offset)
166 {
167 #if defined (_I386_BUS_PIO_H_)
168 #if defined (_I386_BUS_MEMIO_H_)
169 if (tag == I386_BUS_SPACE_IO)
170 #endif
171 return (inb(handle + offset));
172 #endif
173 #if defined (_I386_BUS_MEMIO_H_)
174 return (*(volatile u_int8_t *)(handle + offset));
175 #endif
176 }
177
178 static __inline u_int16_t
179 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
180 bus_size_t offset)
181 {
182 #if defined(_I386_BUS_PIO_H_)
183 #if defined(_I386_BUS_MEMIO_H_)
184 if (tag == I386_BUS_SPACE_IO)
185 #endif
186 return (inw(handle + offset));
187 #endif
188 #if defined(_I386_BUS_MEMIO_H_)
189 return (*(volatile u_int16_t *)(handle + offset));
190 #endif
191 }
192
193 static __inline u_int32_t
194 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
195 bus_size_t offset)
196 {
197 #if defined(_I386_BUS_PIO_H_)
198 #if defined(_I386_BUS_MEMIO_H_)
199 if (tag == I386_BUS_SPACE_IO)
200 #endif
201 return (inl(handle + offset));
202 #endif
203 #if defined(_I386_BUS_MEMIO_H_)
204 return (*(volatile u_int32_t *)(handle + offset));
205 #endif
206 }
207
208 #if 0 /* Cause a link error for bus_space_read_8 */
209 #define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!!
210 #endif
211
212 /*
213 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
214 * described by tag/handle/offset and copy into buffer provided.
215 */
216 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
217 bus_space_handle_t bsh,
218 bus_size_t offset, u_int8_t *addr,
219 size_t count);
220
221 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
222 bus_space_handle_t bsh,
223 bus_size_t offset, u_int16_t *addr,
224 size_t count);
225
226 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
227 bus_space_handle_t bsh,
228 bus_size_t offset, u_int32_t *addr,
229 size_t count);
230
231 static __inline void
232 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
233 bus_size_t offset, u_int8_t *addr, size_t count)
234 {
235 #if defined(_I386_BUS_PIO_H_)
236 #if defined(_I386_BUS_MEMIO_H_)
237 if (tag == I386_BUS_SPACE_IO)
238 #endif
239 insb(bsh + offset, addr, count);
240 #endif
241 #if defined(_I386_BUS_MEMIO_H_)
242 #if defined(_I386_BUS_PIO_H_)
243 else
244 #endif
245 {
246 int __x __asm__("%eax");
247 __asm __volatile(" \n\
248 cld \n\
249 1: movb (%1),%%al \n\
250 stosb \n\
251 loop 1b" :
252 "=&a" (__x) :
253 "r" (bsh + offset), "D" (addr), "c" (count) :
254 "%edi", "%ecx", "memory");
255 }
256 #endif
257 }
258
259 static __inline void
260 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
261 bus_size_t offset, u_int16_t *addr, size_t count)
262 {
263 #if defined(_I386_BUS_PIO_H_)
264 #if defined(_I386_BUS_MEMIO_H_)
265 if (tag == I386_BUS_SPACE_IO)
266 #endif
267 insw(bsh + offset, addr, count);
268 #endif
269 #if defined(_I386_BUS_MEMIO_H_)
270 #if defined(_I386_BUS_PIO_H_)
271 else
272 #endif
273 {
274 int __x __asm__("%eax");
275 __asm __volatile(" \n\
276 cld \n\
277 1: movw (%1),%%ax \n\
278 stosw \n\
279 loop 1b" :
280 "=&a" (__x) :
281 "r" (bsh + offset), "D" (addr), "c" (count) :
282 "%edi", "%ecx", "memory");
283 }
284 #endif
285 }
286
287 static __inline void
288 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
289 bus_size_t offset, u_int32_t *addr, size_t count)
290 {
291 #if defined(_I386_BUS_PIO_H_)
292 #if defined(_I386_BUS_MEMIO_H_)
293 if (tag == I386_BUS_SPACE_IO)
294 #endif
295 insl(bsh + offset, addr, count);
296 #endif
297 #if defined(_I386_BUS_MEMIO_H_)
298 #if defined(_I386_BUS_PIO_H_)
299 else
300 #endif
301 {
302 int __x __asm__("%eax");
303 __asm __volatile(" \n\
304 cld \n\
305 1: movl (%1),%%eax \n\
306 stosl \n\
307 loop 1b" :
308 "=&a" (__x) :
309 "r" (bsh + offset), "D" (addr), "c" (count) :
310 "%edi", "%ecx", "memory");
311 }
312 #endif
313 }
314
315 #if 0 /* Cause a link error for bus_space_read_multi_8 */
316 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!!
317 #endif
318
319 /*
320 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
321 * described by tag/handle and starting at `offset' and copy into
322 * buffer provided.
323 */
324 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
325 bus_space_handle_t bsh,
326 bus_size_t offset, u_int8_t *addr,
327 size_t count);
328
329 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
330 bus_space_handle_t bsh,
331 bus_size_t offset, u_int16_t *addr,
332 size_t count);
333
334 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
335 bus_space_handle_t bsh,
336 bus_size_t offset, u_int32_t *addr,
337 size_t count);
338
339
340 static __inline void
341 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
342 bus_size_t offset, u_int8_t *addr, size_t count)
343 {
344 #if defined(_I386_BUS_PIO_H_)
345 #if defined(_I386_BUS_MEMIO_H_)
346 if (tag == I386_BUS_SPACE_IO)
347 #endif
348 {
349 int __x __asm__("%eax");
350 __asm __volatile(" \n\
351 cld \n\
352 1: inb %w1,%%al \n\
353 stosb \n\
354 incl %1 \n\
355 loop 1b" :
356 "=&a" (__x) :
357 "d" (bsh + offset), "D" (addr), "c" (count) :
358 "%edx", "%edi", "%ecx", "memory");
359 }
360 #endif
361 #if defined(_I386_BUS_MEMIO_H_)
362 #if defined(_I386_BUS_PIO_H_)
363 else
364 #endif
365 {
366 __asm __volatile(" \n\
367 cld \n\
368 repne \n\
369 movsb" :
370 :
371 "S" (bsh + offset), "D" (addr), "c" (count) :
372 "%esi", "%edi", "%ecx", "memory");
373 }
374 #endif
375 }
376
377 static __inline void
378 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
379 bus_size_t offset, u_int16_t *addr, size_t count)
380 {
381 #if defined(_I386_BUS_PIO_H_)
382 #if defined(_I386_BUS_MEMIO_H_)
383 if (tag == I386_BUS_SPACE_IO)
384 #endif
385 {
386 int __x __asm__("%eax");
387 __asm __volatile(" \n\
388 cld \n\
389 1: inw %w1,%%ax \n\
390 stosw \n\
391 addl $2,%1 \n\
392 loop 1b" :
393 "=&a" (__x) :
394 "d" (bsh + offset), "D" (addr), "c" (count) :
395 "%edx", "%edi", "%ecx", "memory");
396 }
397 #endif
398 #if defined(_I386_BUS_MEMIO_H_)
399 #if defined(_I386_BUS_PIO_H_)
400 else
401 #endif
402 {
403 __asm __volatile(" \n\
404 cld \n\
405 repne \n\
406 movsw" :
407 :
408 "S" (bsh + offset), "D" (addr), "c" (count) :
409 "%esi", "%edi", "%ecx", "memory");
410 }
411 #endif
412 }
413
414 static __inline void
415 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
416 bus_size_t offset, u_int32_t *addr, size_t count)
417 {
418 #if defined(_I386_BUS_PIO_H_)
419 #if defined(_I386_BUS_MEMIO_H_)
420 if (tag == I386_BUS_SPACE_IO)
421 #endif
422 {
423 int __x __asm__("%eax");
424 __asm __volatile(" \n\
425 cld \n\
426 1: inl %w1,%%eax \n\
427 stosl \n\
428 addl $4,%1 \n\
429 loop 1b" :
430 "=&a" (__x) :
431 "d" (bsh + offset), "D" (addr), "c" (count) :
432 "%edx", "%edi", "%ecx", "memory");
433 }
434 #endif
435 #if defined(_I386_BUS_MEMIO_H_)
436 #if defined(_I386_BUS_PIO_H_)
437 else
438 #endif
439 {
440 __asm __volatile(" \n\
441 cld \n\
442 repne \n\
443 movsl" :
444 :
445 "S" (bsh + offset), "D" (addr), "c" (count) :
446 "%esi", "%edi", "%ecx", "memory");
447 }
448 #endif
449 }
450
451 #if 0 /* Cause a link error for bus_space_read_region_8 */
452 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
453 #endif
454
455 /*
456 * Write the 1, 2, 4, or 8 byte value `value' to bus space
457 * described by tag/handle/offset.
458 */
459
460 static __inline void bus_space_write_1(bus_space_tag_t tag,
461 bus_space_handle_t bsh,
462 bus_size_t offset, u_int8_t value);
463
464 static __inline void bus_space_write_2(bus_space_tag_t tag,
465 bus_space_handle_t bsh,
466 bus_size_t offset, u_int16_t value);
467
468 static __inline void bus_space_write_4(bus_space_tag_t tag,
469 bus_space_handle_t bsh,
470 bus_size_t offset, u_int32_t value);
471
472 static __inline void
473 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
474 bus_size_t offset, u_int8_t value)
475 {
476 #if defined(_I386_BUS_PIO_H_)
477 #if defined(_I386_BUS_MEMIO_H_)
478 if (tag == I386_BUS_SPACE_IO)
479 #endif
480 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
490 static __inline void
491 bus_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
508 static __inline void
509 bus_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
535 static __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);
540 static __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
546 static __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
552 static __inline void
553 bus_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
580 static __inline void
581 bus_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
608 static __inline void
609 bus_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
646 static __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);
651 static __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);
656 static __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
662 static __inline void
663 bus_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
699 static __inline void
700 bus_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
736 static __inline void
737 bus_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
783 static __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);
787 static __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);
791 static __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
796 static __inline void
797 bus_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
818 static __inline void
819 bus_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
840 static __inline void
841 bus_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
871 static __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);
875 static __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);
879 static __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
884 static __inline void
885 bus_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
906 static __inline void
907 bus_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
928 static __inline void
929 bus_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
959 static __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
965 static __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
971 static __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
977 static __inline void
978 bus_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
1023 static __inline void
1024 bus_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
1069 static __inline void
1070 bus_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. */
1148 struct mbuf;
1149 struct uio;
1150
1151 /*
1152 * bus_dmasync_op_t
1153 *
1154 * Operations performed by bus_dmamap_sync().
1155 */
1156 typedef 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 */
1171 typedef struct bus_dma_tag *bus_dma_tag_t;
1172
1173 /*
1174 * bus_dmamap_t
1175 *
1176 * DMA mapping instance information.
1177 */
1178 typedef 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 */
1186 typedef 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 */
1195 typedef 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 */
1218 int 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
1224 int 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 */
1230 int 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 */
1236 int 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 */
1243 int 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 */
1250 void 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 */
1256 typedef 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 */
1261 int 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 */
1268 void _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 */
1276 void _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_ */
Cache object: ce014f917c772b13b6161f69776a7e58
|