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