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: releng/5.3/sys/i386/include/bus_at386.h 126891 2004-03-12 21:45:33Z trhodes $ */
71
72 #ifndef _I386_BUS_AT386_H_
73 #define _I386_BUS_AT386_H_
74
75 #include <machine/cpufunc.h>
76
77 /*
78 * To remain compatible with NetBSD's interface, default to both memio and
79 * pio when neither of them is defined.
80 */
81 #if !defined(_I386_BUS_PIO_H_) && !defined(_I386_BUS_MEMIO_H_)
82 #define _I386_BUS_PIO_H_
83 #define _I386_BUS_MEMIO_H_
84 #endif
85
86 /*
87 * Values for the i386 bus space tag, not to be used directly by MI code.
88 */
89 #define I386_BUS_SPACE_IO 0 /* space is i/o space */
90 #define I386_BUS_SPACE_MEM 1 /* space is mem space */
91
92 /*
93 * Bus address and size types
94 */
95 #ifdef PAE
96 typedef uint64_t bus_addr_t;
97 #else
98 typedef uint32_t bus_addr_t;
99 #endif
100 typedef uint32_t bus_size_t;
101
102 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
103 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
104 #define BUS_SPACE_MAXSIZE 0xFFFFFFFF
105 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
106 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
107 #ifdef PAE
108 #define BUS_SPACE_MAXADDR 0xFFFFFFFFFFFFFFFFULL
109 #else
110 #define BUS_SPACE_MAXADDR 0xFFFFFFFF
111 #endif
112
113 #define BUS_SPACE_UNRESTRICTED (~0)
114
115 /*
116 * Access methods for bus resources and address space.
117 */
118 typedef int bus_space_tag_t;
119 typedef u_int bus_space_handle_t;
120
121 /*
122 * Map a region of device bus space into CPU virtual address space.
123 */
124
125 static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
126 bus_size_t size, int flags,
127 bus_space_handle_t *bshp);
128
129 static __inline int
130 bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
131 bus_size_t size __unused, int flags __unused,
132 bus_space_handle_t *bshp)
133 {
134
135 *bshp = addr;
136 return (0);
137 }
138
139 /*
140 * Unmap a region of device bus space.
141 */
142
143 static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
144 bus_size_t size);
145
146 static __inline void
147 bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
148 bus_size_t size __unused)
149 {
150 }
151
152 /*
153 * Get a new handle for a subregion of an already-mapped area of bus space.
154 */
155
156 static __inline int bus_space_subregion(bus_space_tag_t t,
157 bus_space_handle_t bsh,
158 bus_size_t offset, bus_size_t size,
159 bus_space_handle_t *nbshp);
160
161 static __inline int
162 bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh,
163 bus_size_t offset, bus_size_t size __unused,
164 bus_space_handle_t *nbshp)
165 {
166
167 *nbshp = bsh + offset;
168 return (0);
169 }
170
171 /*
172 * Allocate a region of memory that is accessible to devices in bus space.
173 */
174
175 int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
176 bus_addr_t rend, bus_size_t size, bus_size_t align,
177 bus_size_t boundary, int flags, bus_addr_t *addrp,
178 bus_space_handle_t *bshp);
179
180 /*
181 * Free a region of bus space accessible memory.
182 */
183
184 static __inline void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
185 bus_size_t size);
186
187 static __inline void
188 bus_space_free(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
189 bus_size_t size __unused)
190 {
191 }
192
193
194 #if defined(_I386_BUS_PIO_H_) || defined(_I386_BUS_MEMIO_H_)
195
196 /*
197 * Read a 1, 2, 4, or 8 byte quantity from bus space
198 * described by tag/handle/offset.
199 */
200 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
201 bus_space_handle_t handle,
202 bus_size_t offset);
203
204 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
205 bus_space_handle_t handle,
206 bus_size_t offset);
207
208 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
209 bus_space_handle_t handle,
210 bus_size_t offset);
211
212 static __inline u_int8_t
213 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
214 bus_size_t offset)
215 {
216 #if defined (_I386_BUS_PIO_H_)
217 #if defined (_I386_BUS_MEMIO_H_)
218 if (tag == I386_BUS_SPACE_IO)
219 #endif
220 return (inb(handle + offset));
221 #endif
222 #if defined (_I386_BUS_MEMIO_H_)
223 return (*(volatile u_int8_t *)(handle + offset));
224 #endif
225 }
226
227 static __inline u_int16_t
228 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
229 bus_size_t offset)
230 {
231 #if defined(_I386_BUS_PIO_H_)
232 #if defined(_I386_BUS_MEMIO_H_)
233 if (tag == I386_BUS_SPACE_IO)
234 #endif
235 return (inw(handle + offset));
236 #endif
237 #if defined(_I386_BUS_MEMIO_H_)
238 return (*(volatile u_int16_t *)(handle + offset));
239 #endif
240 }
241
242 static __inline u_int32_t
243 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
244 bus_size_t offset)
245 {
246 #if defined(_I386_BUS_PIO_H_)
247 #if defined(_I386_BUS_MEMIO_H_)
248 if (tag == I386_BUS_SPACE_IO)
249 #endif
250 return (inl(handle + offset));
251 #endif
252 #if defined(_I386_BUS_MEMIO_H_)
253 return (*(volatile u_int32_t *)(handle + offset));
254 #endif
255 }
256
257 #if 0 /* Cause a link error for bus_space_read_8 */
258 #define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!!
259 #endif
260
261 /*
262 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
263 * described by tag/handle/offset and copy into buffer provided.
264 */
265 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
266 bus_space_handle_t bsh,
267 bus_size_t offset, u_int8_t *addr,
268 size_t count);
269
270 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
271 bus_space_handle_t bsh,
272 bus_size_t offset, u_int16_t *addr,
273 size_t count);
274
275 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
276 bus_space_handle_t bsh,
277 bus_size_t offset, u_int32_t *addr,
278 size_t count);
279
280 static __inline void
281 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
282 bus_size_t offset, u_int8_t *addr, size_t count)
283 {
284 #if defined(_I386_BUS_PIO_H_)
285 #if defined(_I386_BUS_MEMIO_H_)
286 if (tag == I386_BUS_SPACE_IO)
287 #endif
288 insb(bsh + offset, addr, count);
289 #endif
290 #if defined(_I386_BUS_MEMIO_H_)
291 #if defined(_I386_BUS_PIO_H_)
292 else
293 #endif
294 {
295 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
296 __asm __volatile(" \n\
297 cld \n\
298 1: movb (%2),%%al \n\
299 stosb \n\
300 loop 1b" :
301 "=D" (addr), "=c" (count) :
302 "r" (bsh + offset), "" (addr), "1" (count) :
303 "%eax", "memory");
304 #else
305 # ifndef lint
306 # error "no assembler code for your compiler"
307 # endif
308 #endif
309 }
310 #endif
311 }
312
313 static __inline void
314 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
315 bus_size_t offset, u_int16_t *addr, size_t count)
316 {
317 #if defined(_I386_BUS_PIO_H_)
318 #if defined(_I386_BUS_MEMIO_H_)
319 if (tag == I386_BUS_SPACE_IO)
320 #endif
321 insw(bsh + offset, addr, count);
322 #endif
323 #if defined(_I386_BUS_MEMIO_H_)
324 #if defined(_I386_BUS_PIO_H_)
325 else
326 #endif
327 {
328 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
329 __asm __volatile(" \n\
330 cld \n\
331 1: movw (%2),%%ax \n\
332 stosw \n\
333 loop 1b" :
334 "=D" (addr), "=c" (count) :
335 "r" (bsh + offset), "" (addr), "1" (count) :
336 "%eax", "memory");
337 #else
338 # ifndef lint
339 # error "no assembler code for your compiler"
340 # endif
341 #endif
342 }
343 #endif
344 }
345
346 static __inline void
347 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
348 bus_size_t offset, u_int32_t *addr, size_t count)
349 {
350 #if defined(_I386_BUS_PIO_H_)
351 #if defined(_I386_BUS_MEMIO_H_)
352 if (tag == I386_BUS_SPACE_IO)
353 #endif
354 insl(bsh + offset, addr, count);
355 #endif
356 #if defined(_I386_BUS_MEMIO_H_)
357 #if defined(_I386_BUS_PIO_H_)
358 else
359 #endif
360 {
361 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
362 __asm __volatile(" \n\
363 cld \n\
364 1: movl (%2),%%eax \n\
365 stosl \n\
366 loop 1b" :
367 "=D" (addr), "=c" (count) :
368 "r" (bsh + offset), "" (addr), "1" (count) :
369 "%eax", "memory");
370 #else
371 # ifndef lint
372 # error "no assembler code for your compiler"
373 # endif
374 #endif
375 }
376 #endif
377 }
378
379 #if 0 /* Cause a link error for bus_space_read_multi_8 */
380 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!!
381 #endif
382
383 /*
384 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
385 * described by tag/handle and starting at `offset' and copy into
386 * buffer provided.
387 */
388 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
389 bus_space_handle_t bsh,
390 bus_size_t offset, u_int8_t *addr,
391 size_t count);
392
393 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
394 bus_space_handle_t bsh,
395 bus_size_t offset, u_int16_t *addr,
396 size_t count);
397
398 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
399 bus_space_handle_t bsh,
400 bus_size_t offset, u_int32_t *addr,
401 size_t count);
402
403
404 static __inline void
405 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
406 bus_size_t offset, u_int8_t *addr, size_t count)
407 {
408 #if defined(_I386_BUS_PIO_H_)
409 #if defined(_I386_BUS_MEMIO_H_)
410 if (tag == I386_BUS_SPACE_IO)
411 #endif
412 {
413 int _port_ = bsh + offset;
414 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
415 __asm __volatile(" \n\
416 cld \n\
417 1: inb %w2,%%al \n\
418 stosb \n\
419 incl %2 \n\
420 loop 1b" :
421 "=D" (addr), "=c" (count), "=d" (_port_) :
422 "" (addr), "1" (count), "2" (_port_) :
423 "%eax", "memory", "cc");
424 #else
425 # ifndef lint
426 # error "no assembler code for your compiler"
427 # endif
428 #endif
429 }
430 #endif
431 #if defined(_I386_BUS_MEMIO_H_)
432 #if defined(_I386_BUS_PIO_H_)
433 else
434 #endif
435 {
436 int _port_ = bsh + offset;
437 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
438 __asm __volatile(" \n\
439 cld \n\
440 repne \n\
441 movsb" :
442 "=D" (addr), "=c" (count), "=S" (_port_) :
443 "" (addr), "1" (count), "2" (_port_) :
444 "memory", "cc");
445 #else
446 # ifndef lint
447 # error "no assembler code for your compiler"
448 # endif
449 #endif
450 }
451 #endif
452 }
453
454 static __inline void
455 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
456 bus_size_t offset, u_int16_t *addr, size_t count)
457 {
458 #if defined(_I386_BUS_PIO_H_)
459 #if defined(_I386_BUS_MEMIO_H_)
460 if (tag == I386_BUS_SPACE_IO)
461 #endif
462 {
463 int _port_ = bsh + offset;
464 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
465 __asm __volatile(" \n\
466 cld \n\
467 1: inw %w2,%%ax \n\
468 stosw \n\
469 addl $2,%2 \n\
470 loop 1b" :
471 "=D" (addr), "=c" (count), "=d" (_port_) :
472 "" (addr), "1" (count), "2" (_port_) :
473 "%eax", "memory", "cc");
474 #else
475 # ifndef lint
476 # error "no assembler code for your compiler"
477 # endif
478 #endif
479 }
480 #endif
481 #if defined(_I386_BUS_MEMIO_H_)
482 #if defined(_I386_BUS_PIO_H_)
483 else
484 #endif
485 {
486 int _port_ = bsh + offset;
487 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
488 __asm __volatile(" \n\
489 cld \n\
490 repne \n\
491 movsw" :
492 "=D" (addr), "=c" (count), "=S" (_port_) :
493 "" (addr), "1" (count), "2" (_port_) :
494 "memory", "cc");
495 #else
496 # ifndef lint
497 # error "no assembler code for your compiler"
498 # endif
499 #endif
500 }
501 #endif
502 }
503
504 static __inline void
505 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
506 bus_size_t offset, u_int32_t *addr, size_t count)
507 {
508 #if defined(_I386_BUS_PIO_H_)
509 #if defined(_I386_BUS_MEMIO_H_)
510 if (tag == I386_BUS_SPACE_IO)
511 #endif
512 {
513 int _port_ = bsh + offset;
514 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
515 __asm __volatile(" \n\
516 cld \n\
517 1: inl %w2,%%eax \n\
518 stosl \n\
519 addl $4,%2 \n\
520 loop 1b" :
521 "=D" (addr), "=c" (count), "=d" (_port_) :
522 "" (addr), "1" (count), "2" (_port_) :
523 "%eax", "memory", "cc");
524 #else
525 # ifndef lint
526 # error "no assembler code for your compiler"
527 # endif
528 #endif
529 }
530 #endif
531 #if defined(_I386_BUS_MEMIO_H_)
532 #if defined(_I386_BUS_PIO_H_)
533 else
534 #endif
535 {
536 int _port_ = bsh + offset;
537 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
538 __asm __volatile(" \n\
539 cld \n\
540 repne \n\
541 movsl" :
542 "=D" (addr), "=c" (count), "=S" (_port_) :
543 "" (addr), "1" (count), "2" (_port_) :
544 "memory", "cc");
545 #else
546 # ifndef lint
547 # error "no assembler code for your compiler"
548 # endif
549 #endif
550 }
551 #endif
552 }
553
554 #if 0 /* Cause a link error for bus_space_read_region_8 */
555 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
556 #endif
557
558 /*
559 * Write the 1, 2, 4, or 8 byte value `value' to bus space
560 * described by tag/handle/offset.
561 */
562
563 static __inline void bus_space_write_1(bus_space_tag_t tag,
564 bus_space_handle_t bsh,
565 bus_size_t offset, u_int8_t value);
566
567 static __inline void bus_space_write_2(bus_space_tag_t tag,
568 bus_space_handle_t bsh,
569 bus_size_t offset, u_int16_t value);
570
571 static __inline void bus_space_write_4(bus_space_tag_t tag,
572 bus_space_handle_t bsh,
573 bus_size_t offset, u_int32_t value);
574
575 static __inline void
576 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
577 bus_size_t offset, u_int8_t value)
578 {
579 #if defined(_I386_BUS_PIO_H_)
580 #if defined(_I386_BUS_MEMIO_H_)
581 if (tag == I386_BUS_SPACE_IO)
582 #endif
583 outb(bsh + offset, value);
584 #endif
585 #if defined(_I386_BUS_MEMIO_H_)
586 #if defined(_I386_BUS_PIO_H_)
587 else
588 #endif
589 *(volatile u_int8_t *)(bsh + offset) = value;
590 #endif
591 }
592
593 static __inline void
594 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
595 bus_size_t offset, u_int16_t value)
596 {
597 #if defined(_I386_BUS_PIO_H_)
598 #if defined(_I386_BUS_MEMIO_H_)
599 if (tag == I386_BUS_SPACE_IO)
600 #endif
601 outw(bsh + offset, value);
602 #endif
603 #if defined(_I386_BUS_MEMIO_H_)
604 #if defined(_I386_BUS_PIO_H_)
605 else
606 #endif
607 *(volatile u_int16_t *)(bsh + offset) = value;
608 #endif
609 }
610
611 static __inline void
612 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
613 bus_size_t offset, u_int32_t value)
614 {
615 #if defined(_I386_BUS_PIO_H_)
616 #if defined(_I386_BUS_MEMIO_H_)
617 if (tag == I386_BUS_SPACE_IO)
618 #endif
619 outl(bsh + offset, value);
620 #endif
621 #if defined(_I386_BUS_MEMIO_H_)
622 #if defined(_I386_BUS_PIO_H_)
623 else
624 #endif
625 *(volatile u_int32_t *)(bsh + offset) = value;
626 #endif
627 }
628
629 #if 0 /* Cause a link error for bus_space_write_8 */
630 #define bus_space_write_8 !!! bus_space_write_8 not implemented !!!
631 #endif
632
633 /*
634 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
635 * provided to bus space described by tag/handle/offset.
636 */
637
638 static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
639 bus_space_handle_t bsh,
640 bus_size_t offset,
641 const u_int8_t *addr,
642 size_t count);
643 static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
644 bus_space_handle_t bsh,
645 bus_size_t offset,
646 const u_int16_t *addr,
647 size_t count);
648
649 static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
650 bus_space_handle_t bsh,
651 bus_size_t offset,
652 const u_int32_t *addr,
653 size_t count);
654
655 static __inline void
656 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
657 bus_size_t offset, const u_int8_t *addr, size_t count)
658 {
659 #if defined(_I386_BUS_PIO_H_)
660 #if defined(_I386_BUS_MEMIO_H_)
661 if (tag == I386_BUS_SPACE_IO)
662 #endif
663 outsb(bsh + offset, addr, count);
664 #endif
665 #if defined(_I386_BUS_MEMIO_H_)
666 #if defined(_I386_BUS_PIO_H_)
667 else
668 #endif
669 {
670 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
671 __asm __volatile(" \n\
672 cld \n\
673 1: lodsb \n\
674 movb %%al,(%2) \n\
675 loop 1b" :
676 "=S" (addr), "=c" (count) :
677 "r" (bsh + offset), "" (addr), "1" (count) :
678 "%eax", "memory", "cc");
679 #else
680 # ifndef lint
681 # error "no assembler code for your compiler"
682 # endif
683 #endif
684 }
685 #endif
686 }
687
688 static __inline void
689 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
690 bus_size_t offset, const u_int16_t *addr, size_t count)
691 {
692 #if defined(_I386_BUS_PIO_H_)
693 #if defined(_I386_BUS_MEMIO_H_)
694 if (tag == I386_BUS_SPACE_IO)
695 #endif
696 outsw(bsh + offset, addr, count);
697 #endif
698 #if defined(_I386_BUS_MEMIO_H_)
699 #if defined(_I386_BUS_PIO_H_)
700 else
701 #endif
702 {
703 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
704 __asm __volatile(" \n\
705 cld \n\
706 1: lodsw \n\
707 movw %%ax,(%2) \n\
708 loop 1b" :
709 "=S" (addr), "=c" (count) :
710 "r" (bsh + offset), "" (addr), "1" (count) :
711 "%eax", "memory", "cc");
712 #else
713 # ifndef lint
714 # error "no assembler code for your compiler"
715 # endif
716 #endif
717 }
718 #endif
719 }
720
721 static __inline void
722 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
723 bus_size_t offset, const u_int32_t *addr, size_t count)
724 {
725 #if defined(_I386_BUS_PIO_H_)
726 #if defined(_I386_BUS_MEMIO_H_)
727 if (tag == I386_BUS_SPACE_IO)
728 #endif
729 outsl(bsh + offset, addr, count);
730 #endif
731 #if defined(_I386_BUS_MEMIO_H_)
732 #if defined(_I386_BUS_PIO_H_)
733 else
734 #endif
735 {
736 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
737 __asm __volatile(" \n\
738 cld \n\
739 1: lodsl \n\
740 movl %%eax,(%2) \n\
741 loop 1b" :
742 "=S" (addr), "=c" (count) :
743 "r" (bsh + offset), "" (addr), "1" (count) :
744 "%eax", "memory", "cc");
745 #else
746 # ifndef lint
747 # error "no assembler code for your compiler"
748 # endif
749 #endif
750 }
751 #endif
752 }
753
754 #if 0 /* Cause a link error for bus_space_write_multi_8 */
755 #define bus_space_write_multi_8(t, h, o, a, c) \
756 !!! bus_space_write_multi_8 unimplemented !!!
757 #endif
758
759 /*
760 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
761 * to bus space described by tag/handle starting at `offset'.
762 */
763
764 static __inline void bus_space_write_region_1(bus_space_tag_t tag,
765 bus_space_handle_t bsh,
766 bus_size_t offset,
767 const u_int8_t *addr,
768 size_t count);
769 static __inline void bus_space_write_region_2(bus_space_tag_t tag,
770 bus_space_handle_t bsh,
771 bus_size_t offset,
772 const u_int16_t *addr,
773 size_t count);
774 static __inline void bus_space_write_region_4(bus_space_tag_t tag,
775 bus_space_handle_t bsh,
776 bus_size_t offset,
777 const u_int32_t *addr,
778 size_t count);
779
780 static __inline void
781 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
782 bus_size_t offset, const u_int8_t *addr, size_t count)
783 {
784 #if defined(_I386_BUS_PIO_H_)
785 #if defined(_I386_BUS_MEMIO_H_)
786 if (tag == I386_BUS_SPACE_IO)
787 #endif
788 {
789 int _port_ = bsh + offset;
790 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
791 __asm __volatile(" \n\
792 cld \n\
793 1: lodsb \n\
794 outb %%al,%w0 \n\
795 incl %0 \n\
796 loop 1b" :
797 "=d" (_port_), "=S" (addr), "=c" (count) :
798 "" (_port_), "1" (addr), "2" (count) :
799 "%eax", "memory", "cc");
800 #else
801 # ifndef lint
802 # error "no assembler code for your compiler"
803 # endif
804 #endif
805 }
806 #endif
807 #if defined(_I386_BUS_MEMIO_H_)
808 #if defined(_I386_BUS_PIO_H_)
809 else
810 #endif
811 {
812 int _port_ = bsh + offset;
813 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
814 __asm __volatile(" \n\
815 cld \n\
816 repne \n\
817 movsb" :
818 "=D" (_port_), "=S" (addr), "=c" (count) :
819 "" (_port_), "1" (addr), "2" (count) :
820 "memory", "cc");
821 #else
822 # ifndef lint
823 # error "no assembler code for your compiler"
824 # endif
825 #endif
826 }
827 #endif
828 }
829
830 static __inline void
831 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
832 bus_size_t offset, const u_int16_t *addr, size_t count)
833 {
834 #if defined(_I386_BUS_PIO_H_)
835 #if defined(_I386_BUS_MEMIO_H_)
836 if (tag == I386_BUS_SPACE_IO)
837 #endif
838 {
839 int _port_ = bsh + offset;
840 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
841 __asm __volatile(" \n\
842 cld \n\
843 1: lodsw \n\
844 outw %%ax,%w0 \n\
845 addl $2,%0 \n\
846 loop 1b" :
847 "=d" (_port_), "=S" (addr), "=c" (count) :
848 "" (_port_), "1" (addr), "2" (count) :
849 "%eax", "memory", "cc");
850 #else
851 # ifndef lint
852 # error "no assembler code for your compiler"
853 # endif
854 #endif
855 }
856 #endif
857 #if defined(_I386_BUS_MEMIO_H_)
858 #if defined(_I386_BUS_PIO_H_)
859 else
860 #endif
861 {
862 int _port_ = bsh + offset;
863 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
864 __asm __volatile(" \n\
865 cld \n\
866 repne \n\
867 movsw" :
868 "=D" (_port_), "=S" (addr), "=c" (count) :
869 "" (_port_), "1" (addr), "2" (count) :
870 "memory", "cc");
871 #else
872 # ifndef lint
873 # error "no assembler code for your compiler"
874 # endif
875 #endif
876 }
877 #endif
878 }
879
880 static __inline void
881 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
882 bus_size_t offset, const u_int32_t *addr, size_t count)
883 {
884 #if defined(_I386_BUS_PIO_H_)
885 #if defined(_I386_BUS_MEMIO_H_)
886 if (tag == I386_BUS_SPACE_IO)
887 #endif
888 {
889 int _port_ = bsh + offset;
890 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
891 __asm __volatile(" \n\
892 cld \n\
893 1: lodsl \n\
894 outl %%eax,%w0 \n\
895 addl $4,%0 \n\
896 loop 1b" :
897 "=d" (_port_), "=S" (addr), "=c" (count) :
898 "" (_port_), "1" (addr), "2" (count) :
899 "%eax", "memory", "cc");
900 #else
901 # ifndef lint
902 # error "no assembler code for your compiler"
903 # endif
904 #endif
905 }
906 #endif
907 #if defined(_I386_BUS_MEMIO_H_)
908 #if defined(_I386_BUS_PIO_H_)
909 else
910 #endif
911 {
912 int _port_ = bsh + offset;
913 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
914 __asm __volatile(" \n\
915 cld \n\
916 repne \n\
917 movsl" :
918 "=D" (_port_), "=S" (addr), "=c" (count) :
919 "" (_port_), "1" (addr), "2" (count) :
920 "memory", "cc");
921 #else
922 # ifndef lint
923 # error "no assembler code for your compiler"
924 # endif
925 #endif
926 }
927 #endif
928 }
929
930 #if 0 /* Cause a link error for bus_space_write_region_8 */
931 #define bus_space_write_region_8 \
932 !!! bus_space_write_region_8 unimplemented !!!
933 #endif
934
935 /*
936 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
937 * by tag/handle/offset `count' times.
938 */
939
940 static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
941 bus_space_handle_t bsh,
942 bus_size_t offset,
943 u_int8_t value, size_t count);
944 static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
945 bus_space_handle_t bsh,
946 bus_size_t offset,
947 u_int16_t value, size_t count);
948 static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
949 bus_space_handle_t bsh,
950 bus_size_t offset,
951 u_int32_t value, size_t count);
952
953 static __inline void
954 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
955 bus_size_t offset, u_int8_t value, size_t count)
956 {
957 bus_space_handle_t addr = bsh + offset;
958
959 #if defined(_I386_BUS_PIO_H_)
960 #if defined(_I386_BUS_MEMIO_H_)
961 if (tag == I386_BUS_SPACE_IO)
962 #endif
963 while (count--)
964 outb(addr, value);
965 #endif
966 #if defined(_I386_BUS_MEMIO_H_)
967 #if defined(_I386_BUS_PIO_H_)
968 else
969 #endif
970 while (count--)
971 *(volatile u_int8_t *)(addr) = value;
972 #endif
973 }
974
975 static __inline void
976 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
977 bus_size_t offset, u_int16_t value, size_t count)
978 {
979 bus_space_handle_t addr = bsh + offset;
980
981 #if defined(_I386_BUS_PIO_H_)
982 #if defined(_I386_BUS_MEMIO_H_)
983 if (tag == I386_BUS_SPACE_IO)
984 #endif
985 while (count--)
986 outw(addr, value);
987 #endif
988 #if defined(_I386_BUS_MEMIO_H_)
989 #if defined(_I386_BUS_PIO_H_)
990 else
991 #endif
992 while (count--)
993 *(volatile u_int16_t *)(addr) = value;
994 #endif
995 }
996
997 static __inline void
998 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
999 bus_size_t offset, u_int32_t value, size_t count)
1000 {
1001 bus_space_handle_t addr = bsh + offset;
1002
1003 #if defined(_I386_BUS_PIO_H_)
1004 #if defined(_I386_BUS_MEMIO_H_)
1005 if (tag == I386_BUS_SPACE_IO)
1006 #endif
1007 while (count--)
1008 outl(addr, value);
1009 #endif
1010 #if defined(_I386_BUS_MEMIO_H_)
1011 #if defined(_I386_BUS_PIO_H_)
1012 else
1013 #endif
1014 while (count--)
1015 *(volatile u_int32_t *)(addr) = value;
1016 #endif
1017 }
1018
1019 #if 0 /* Cause a link error for bus_space_set_multi_8 */
1020 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
1021 #endif
1022
1023 /*
1024 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
1025 * by tag/handle starting at `offset'.
1026 */
1027
1028 static __inline void bus_space_set_region_1(bus_space_tag_t tag,
1029 bus_space_handle_t bsh,
1030 bus_size_t offset, u_int8_t value,
1031 size_t count);
1032 static __inline void bus_space_set_region_2(bus_space_tag_t tag,
1033 bus_space_handle_t bsh,
1034 bus_size_t offset, u_int16_t value,
1035 size_t count);
1036 static __inline void bus_space_set_region_4(bus_space_tag_t tag,
1037 bus_space_handle_t bsh,
1038 bus_size_t offset, u_int32_t value,
1039 size_t count);
1040
1041 static __inline void
1042 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
1043 bus_size_t offset, u_int8_t value, size_t count)
1044 {
1045 bus_space_handle_t addr = bsh + offset;
1046
1047 #if defined(_I386_BUS_PIO_H_)
1048 #if defined(_I386_BUS_MEMIO_H_)
1049 if (tag == I386_BUS_SPACE_IO)
1050 #endif
1051 for (; count != 0; count--, addr++)
1052 outb(addr, value);
1053 #endif
1054 #if defined(_I386_BUS_MEMIO_H_)
1055 #if defined(_I386_BUS_PIO_H_)
1056 else
1057 #endif
1058 for (; count != 0; count--, addr++)
1059 *(volatile u_int8_t *)(addr) = value;
1060 #endif
1061 }
1062
1063 static __inline void
1064 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
1065 bus_size_t offset, u_int16_t value, size_t count)
1066 {
1067 bus_space_handle_t addr = bsh + offset;
1068
1069 #if defined(_I386_BUS_PIO_H_)
1070 #if defined(_I386_BUS_MEMIO_H_)
1071 if (tag == I386_BUS_SPACE_IO)
1072 #endif
1073 for (; count != 0; count--, addr += 2)
1074 outw(addr, value);
1075 #endif
1076 #if defined(_I386_BUS_MEMIO_H_)
1077 #if defined(_I386_BUS_PIO_H_)
1078 else
1079 #endif
1080 for (; count != 0; count--, addr += 2)
1081 *(volatile u_int16_t *)(addr) = value;
1082 #endif
1083 }
1084
1085 static __inline void
1086 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
1087 bus_size_t offset, u_int32_t value, size_t count)
1088 {
1089 bus_space_handle_t addr = bsh + offset;
1090
1091 #if defined(_I386_BUS_PIO_H_)
1092 #if defined(_I386_BUS_MEMIO_H_)
1093 if (tag == I386_BUS_SPACE_IO)
1094 #endif
1095 for (; count != 0; count--, addr += 4)
1096 outl(addr, value);
1097 #endif
1098 #if defined(_I386_BUS_MEMIO_H_)
1099 #if defined(_I386_BUS_PIO_H_)
1100 else
1101 #endif
1102 for (; count != 0; count--, addr += 4)
1103 *(volatile u_int32_t *)(addr) = value;
1104 #endif
1105 }
1106
1107 #if 0 /* Cause a link error for bus_space_set_region_8 */
1108 #define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!!
1109 #endif
1110
1111 /*
1112 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
1113 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
1114 */
1115
1116 static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
1117 bus_space_handle_t bsh1,
1118 bus_size_t off1,
1119 bus_space_handle_t bsh2,
1120 bus_size_t off2, size_t count);
1121
1122 static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
1123 bus_space_handle_t bsh1,
1124 bus_size_t off1,
1125 bus_space_handle_t bsh2,
1126 bus_size_t off2, size_t count);
1127
1128 static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
1129 bus_space_handle_t bsh1,
1130 bus_size_t off1,
1131 bus_space_handle_t bsh2,
1132 bus_size_t off2, size_t count);
1133
1134 static __inline void
1135 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
1136 bus_size_t off1, bus_space_handle_t bsh2,
1137 bus_size_t off2, size_t count)
1138 {
1139 bus_space_handle_t addr1 = bsh1 + off1;
1140 bus_space_handle_t addr2 = bsh2 + off2;
1141
1142 #if defined(_I386_BUS_PIO_H_)
1143 #if defined(_I386_BUS_MEMIO_H_)
1144 if (tag == I386_BUS_SPACE_IO)
1145 #endif
1146 {
1147 if (addr1 >= addr2) {
1148 /* src after dest: copy forward */
1149 for (; count != 0; count--, addr1++, addr2++)
1150 outb(addr2, inb(addr1));
1151 } else {
1152 /* dest after src: copy backwards */
1153 for (addr1 += (count - 1), addr2 += (count - 1);
1154 count != 0; count--, addr1--, addr2--)
1155 outb(addr2, inb(addr1));
1156 }
1157 }
1158 #endif
1159 #if defined(_I386_BUS_MEMIO_H_)
1160 #if defined(_I386_BUS_PIO_H_)
1161 else
1162 #endif
1163 {
1164 if (addr1 >= addr2) {
1165 /* src after dest: copy forward */
1166 for (; count != 0; count--, addr1++, addr2++)
1167 *(volatile u_int8_t *)(addr2) =
1168 *(volatile u_int8_t *)(addr1);
1169 } else {
1170 /* dest after src: copy backwards */
1171 for (addr1 += (count - 1), addr2 += (count - 1);
1172 count != 0; count--, addr1--, addr2--)
1173 *(volatile u_int8_t *)(addr2) =
1174 *(volatile u_int8_t *)(addr1);
1175 }
1176 }
1177 #endif
1178 }
1179
1180 static __inline void
1181 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
1182 bus_size_t off1, bus_space_handle_t bsh2,
1183 bus_size_t off2, size_t count)
1184 {
1185 bus_space_handle_t addr1 = bsh1 + off1;
1186 bus_space_handle_t addr2 = bsh2 + off2;
1187
1188 #if defined(_I386_BUS_PIO_H_)
1189 #if defined(_I386_BUS_MEMIO_H_)
1190 if (tag == I386_BUS_SPACE_IO)
1191 #endif
1192 {
1193 if (addr1 >= addr2) {
1194 /* src after dest: copy forward */
1195 for (; count != 0; count--, addr1 += 2, addr2 += 2)
1196 outw(addr2, inw(addr1));
1197 } else {
1198 /* dest after src: copy backwards */
1199 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
1200 count != 0; count--, addr1 -= 2, addr2 -= 2)
1201 outw(addr2, inw(addr1));
1202 }
1203 }
1204 #endif
1205 #if defined(_I386_BUS_MEMIO_H_)
1206 #if defined(_I386_BUS_PIO_H_)
1207 else
1208 #endif
1209 {
1210 if (addr1 >= addr2) {
1211 /* src after dest: copy forward */
1212 for (; count != 0; count--, addr1 += 2, addr2 += 2)
1213 *(volatile u_int16_t *)(addr2) =
1214 *(volatile u_int16_t *)(addr1);
1215 } else {
1216 /* dest after src: copy backwards */
1217 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
1218 count != 0; count--, addr1 -= 2, addr2 -= 2)
1219 *(volatile u_int16_t *)(addr2) =
1220 *(volatile u_int16_t *)(addr1);
1221 }
1222 }
1223 #endif
1224 }
1225
1226 static __inline void
1227 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
1228 bus_size_t off1, bus_space_handle_t bsh2,
1229 bus_size_t off2, size_t count)
1230 {
1231 bus_space_handle_t addr1 = bsh1 + off1;
1232 bus_space_handle_t addr2 = bsh2 + off2;
1233
1234 #if defined(_I386_BUS_PIO_H_)
1235 #if defined(_I386_BUS_MEMIO_H_)
1236 if (tag == I386_BUS_SPACE_IO)
1237 #endif
1238 {
1239 if (addr1 >= addr2) {
1240 /* src after dest: copy forward */
1241 for (; count != 0; count--, addr1 += 4, addr2 += 4)
1242 outl(addr2, inl(addr1));
1243 } else {
1244 /* dest after src: copy backwards */
1245 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
1246 count != 0; count--, addr1 -= 4, addr2 -= 4)
1247 outl(addr2, inl(addr1));
1248 }
1249 }
1250 #endif
1251 #if defined(_I386_BUS_MEMIO_H_)
1252 #if defined(_I386_BUS_PIO_H_)
1253 else
1254 #endif
1255 {
1256 if (addr1 >= addr2) {
1257 /* src after dest: copy forward */
1258 for (; count != 0; count--, addr1 += 4, addr2 += 4)
1259 *(volatile u_int32_t *)(addr2) =
1260 *(volatile u_int32_t *)(addr1);
1261 } else {
1262 /* dest after src: copy backwards */
1263 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
1264 count != 0; count--, addr1 -= 4, addr2 -= 4)
1265 *(volatile u_int32_t *)(addr2) =
1266 *(volatile u_int32_t *)(addr1);
1267 }
1268 }
1269 #endif
1270 }
1271
1272 #endif /* defined(_I386_BUS_PIO_H_) || defined(_I386_MEM_IO_H_) */
1273
1274 #if 0 /* Cause a link error for bus_space_copy_8 */
1275 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!!
1276 #endif
1277
1278 /*
1279 * Bus read/write barrier methods.
1280 *
1281 * void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
1282 * bus_size_t offset, bus_size_t len, int flags);
1283 *
1284 *
1285 * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
1286 * prevent reordering by the compiler; all Intel x86 processors currently
1287 * retire operations outside the CPU in program order.
1288 */
1289 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
1290 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
1291
1292 static __inline void
1293 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
1294 bus_size_t offset __unused, bus_size_t len __unused, int flags)
1295 {
1296 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
1297 if (flags & BUS_SPACE_BARRIER_READ)
1298 __asm __volatile("lock; addl $0,0(%%esp)" : : : "memory");
1299 else
1300 __asm __volatile("" : : : "memory");
1301 #else
1302 # ifndef lint
1303 # error "no assembler code for your compiler"
1304 # endif
1305 #endif
1306 }
1307
1308 #endif /* _I386_BUS_AT386_H_ */
Cache object: f5ada1c6b6469528e73330f42d74a46e
|