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