Fix kernel compile error in last commit due to lack of types.h in some sources
[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.10 2006/11/07 06:43:22 dillon Exp $
72  */
73
74 #ifndef _CPU_BUS_AT386_H_
75 #define _CPU_BUS_AT386_H_
76
77 #include <machine/cpufunc.h>
78
79 /*
80  * Values for the i386 bus space tag, not to be used directly by MI code.
81  */
82 #define I386_BUS_SPACE_IO       0       /* space is i/o space */
83 #define I386_BUS_SPACE_MEM      1       /* space is mem space */
84
85 /*
86  * Bus address and size types
87  */
88 typedef u_int32_t bus_addr_t;
89 typedef u_int32_t bus_size_t;
90
91 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
92 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
93 #define BUS_SPACE_MAXSIZE       (64 * 1024) /* Maximum supported size */
94 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
95 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
96 #define BUS_SPACE_MAXADDR       BUS_SPACE_MAXADDR_32BIT
97
98 #define BUS_SPACE_UNRESTRICTED  (~0)
99
100 /*
101  * Access methods for bus resources and address space.
102  */
103 typedef int bus_space_tag_t;
104 typedef u_int bus_space_handle_t;
105
106 /*
107  * Map a region of device bus space into CPU virtual address space.
108  */
109
110 #define BUS_SPACE_MAP_CACHEABLE         0x01
111 #define BUS_SPACE_MAP_LINEAR            0x02
112
113 int     bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
114                       int flags, bus_space_handle_t *bshp);
115
116 /*
117  * Unmap a region of device bus space.
118  */
119
120 static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
121                                      bus_size_t size);
122
123 static __inline void
124 bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused, bus_size_t size __unused )
125 {
126 }
127
128 /*
129  * Get a new handle for a subregion of an already-mapped area of bus space.
130  */
131
132 static __inline int bus_space_subregion(bus_space_tag_t t,
133                                         bus_space_handle_t bsh,
134                                         bus_size_t offset, bus_size_t size,
135                                         bus_space_handle_t *nbshp);
136
137 static __inline int
138 bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh,
139                     bus_size_t offset, bus_size_t size __unused,
140                     bus_space_handle_t *nbshp)
141 {
142
143         *nbshp = bsh + offset;
144         return (0);
145 }
146
147 static __inline void *
148 bus_space_kva(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t offset)
149 {
150         if (tag == I386_BUS_SPACE_IO)
151                 return ((void *)0);
152         return ((void *)(handle + offset));
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 __unused, bus_space_handle_t bsh __unused, bus_size_t size __unused)
173 {
174 }
175
176 /*
177  * Read a 1, 2, 4, or 8 byte quantity from bus space
178  * described by tag/handle/offset.
179  */
180 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
181                                           bus_space_handle_t handle,
182                                           bus_size_t offset);
183
184 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
185                                            bus_space_handle_t handle,
186                                            bus_size_t offset);
187
188 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
189                                            bus_space_handle_t handle,
190                                            bus_size_t offset);
191
192 static __inline u_int8_t
193 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
194                  bus_size_t offset)
195 {
196         if (tag == I386_BUS_SPACE_IO)
197                 return (inb(handle + offset));
198         return (*(volatile u_int8_t *)(handle + offset));
199 }
200
201 static __inline u_int16_t
202 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
203                  bus_size_t offset)
204 {
205         if (tag == I386_BUS_SPACE_IO)
206                 return (inw(handle + offset));
207         return (*(volatile u_int16_t *)(handle + offset));
208 }
209
210 static __inline u_int32_t
211 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
212                  bus_size_t offset)
213 {
214         if (tag == I386_BUS_SPACE_IO)
215                 return (inl(handle + offset));
216         return (*(volatile u_int32_t *)(handle + offset));
217 }
218
219 /*
220  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
221  * described by tag/handle/offset and copy into buffer provided.
222  */
223 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
224                                             bus_space_handle_t bsh,
225                                             bus_size_t offset, u_int8_t *addr,
226                                             size_t count);
227
228 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
229                                             bus_space_handle_t bsh,
230                                             bus_size_t offset, u_int16_t *addr,
231                                             size_t count);
232
233 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
234                                             bus_space_handle_t bsh,
235                                             bus_size_t offset, u_int32_t *addr,
236                                             size_t count);
237
238 static __inline void
239 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
240                        bus_size_t offset, u_int8_t *addr, size_t count)
241 {
242         if (tag == I386_BUS_SPACE_IO) {
243                 insb(bsh + offset, addr, count);
244         } else {
245                 __asm __volatile("                              \n\
246                         cld                                     \n\
247                 1:      movb (%2),%%al                          \n\
248                         stosb                                   \n\
249                         loop 1b"                                :
250                     "=D" (addr), "=c" (count)                   :
251                     "r" (bsh + offset), "0" (addr), "1" (count) :
252                     "%eax", "memory");
253         }
254 }
255
256 static __inline void
257 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
258                        bus_size_t offset, u_int16_t *addr, size_t count)
259 {
260         if (tag == I386_BUS_SPACE_IO) {
261                 insw(bsh + offset, addr, count);
262         } else {
263                 __asm __volatile("                              \n\
264                         cld                                     \n\
265                 1:      movw (%2),%%ax                          \n\
266                         stosw                                   \n\
267                         loop 1b"                                :
268                     "=D" (addr), "=c" (count)                   :
269                     "r" (bsh + offset), "0" (addr), "1" (count) :
270                     "%eax", "memory");
271         }
272 }
273
274 static __inline void
275 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
276                        bus_size_t offset, u_int32_t *addr, size_t count)
277 {
278         if (tag == I386_BUS_SPACE_IO) {
279                 insl(bsh + offset, addr, count);
280         } else {
281                 __asm __volatile("                              \n\
282                         cld                                     \n\
283                 1:      movl (%2),%%eax                         \n\
284                         stosl                                   \n\
285                         loop 1b"                                :
286                     "=D" (addr), "=c" (count)                   :
287                     "r" (bsh + offset), "0" (addr), "1" (count) :
288                     "%eax", "memory");
289         }
290 }
291
292 /*
293  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
294  * described by tag/handle and starting at `offset' and copy into
295  * buffer provided.
296  */
297 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
298                                              bus_space_handle_t bsh,
299                                              bus_size_t offset, u_int8_t *addr,
300                                              size_t count);
301
302 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
303                                              bus_space_handle_t bsh,
304                                              bus_size_t offset, u_int16_t *addr,
305                                              size_t count);
306
307 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
308                                              bus_space_handle_t bsh,
309                                              bus_size_t offset, u_int32_t *addr,
310                                              size_t count);
311
312
313 static __inline void
314 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
315                         bus_size_t offset, u_int8_t *addr, size_t count)
316 {
317         if (tag == I386_BUS_SPACE_IO) {
318                 int _port_ = bsh + offset;                      \
319                 __asm __volatile("                              \n\
320                         cld                                     \n\
321                 1:      inb %w2,%%al                            \n\
322                         stosb                                   \n\
323                         incl %2                                 \n\
324                         loop 1b"                                :
325                     "=D" (addr), "=c" (count), "=d" (_port_)    :
326                     "0" (addr), "1" (count), "2" (_port_)       :
327                     "%eax", "memory", "cc");
328         } else {
329                 int _port_ = bsh + offset;                      \
330                 __asm __volatile("                              \n\
331                         cld                                     \n\
332                         repne                                   \n\
333                         movsb"                                  :
334                     "=D" (addr), "=c" (count), "=S" (_port_)    :
335                     "0" (addr), "1" (count), "2" (_port_)       :
336                     "memory", "cc");
337         }
338 }
339
340 static __inline void
341 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
342                         bus_size_t offset, u_int16_t *addr, size_t count)
343 {
344         if (tag == I386_BUS_SPACE_IO) {
345                 int _port_ = bsh + offset;                      \
346                 __asm __volatile("                              \n\
347                         cld                                     \n\
348                 1:      inw %w2,%%ax                            \n\
349                         stosw                                   \n\
350                         addl $2,%2                              \n\
351                         loop 1b"                                :
352                     "=D" (addr), "=c" (count), "=d" (_port_)    :
353                     "0" (addr), "1" (count), "2" (_port_)       :
354                     "%eax", "memory", "cc");
355         } else {
356                 int _port_ = bsh + offset;                      \
357                 __asm __volatile("                              \n\
358                         cld                                     \n\
359                         repne                                   \n\
360                         movsw"                                  :
361                     "=D" (addr), "=c" (count), "=S" (_port_)    :
362                     "0" (addr), "1" (count), "2" (_port_)       :
363                     "memory", "cc");
364         }
365 }
366
367 static __inline void
368 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
369                         bus_size_t offset, u_int32_t *addr, size_t count)
370 {
371         if (tag == I386_BUS_SPACE_IO) {
372                 int _port_ = bsh + offset;                      \
373                 __asm __volatile("                              \n\
374                         cld                                     \n\
375                 1:      inl %w2,%%eax                           \n\
376                         stosl                                   \n\
377                         addl $4,%2                              \n\
378                         loop 1b"                                :
379                     "=D" (addr), "=c" (count), "=d" (_port_)    :
380                     "0" (addr), "1" (count), "2" (_port_)       :
381                     "%eax", "memory", "cc");
382         } else {
383                 int _port_ = bsh + offset;                      \
384                 __asm __volatile("                              \n\
385                         cld                                     \n\
386                         repne                                   \n\
387                         movsl"                                  :
388                     "=D" (addr), "=c" (count), "=S" (_port_)    :
389                     "0" (addr), "1" (count), "2" (_port_)       :
390                     "memory", "cc");
391         }
392 }
393
394 /*
395  * Write the 1, 2, 4, or 8 byte value `value' to bus space
396  * described by tag/handle/offset.
397  */
398
399 static __inline void bus_space_write_1(bus_space_tag_t tag,
400                                        bus_space_handle_t bsh,
401                                        bus_size_t offset, u_int8_t value);
402
403 static __inline void bus_space_write_2(bus_space_tag_t tag,
404                                        bus_space_handle_t bsh,
405                                        bus_size_t offset, u_int16_t value);
406
407 static __inline void bus_space_write_4(bus_space_tag_t tag,
408                                        bus_space_handle_t bsh,
409                                        bus_size_t offset, u_int32_t value);
410
411 static __inline void
412 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
413                        bus_size_t offset, u_int8_t value)
414 {
415         if (tag == I386_BUS_SPACE_IO)
416                 outb(bsh + offset, value);
417         else
418                 *(volatile u_int8_t *)(bsh + offset) = value;
419 }
420
421 static __inline void
422 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
423                        bus_size_t offset, u_int16_t value)
424 {
425         if (tag == I386_BUS_SPACE_IO)
426                 outw(bsh + offset, value);
427         else
428                 *(volatile u_int16_t *)(bsh + offset) = value;
429 }
430
431 static __inline void
432 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
433                        bus_size_t offset, u_int32_t value)
434 {
435         if (tag == I386_BUS_SPACE_IO)
436                 outl(bsh + offset, value);
437         else
438                 *(volatile u_int32_t *)(bsh + offset) = value;
439 }
440
441 /*
442  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
443  * provided to bus space described by tag/handle/offset.
444  */
445
446 static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
447                                              bus_space_handle_t bsh,
448                                              bus_size_t offset,
449                                              const u_int8_t *addr,
450                                              size_t count);
451 static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
452                                              bus_space_handle_t bsh,
453                                              bus_size_t offset,
454                                              const u_int16_t *addr,
455                                              size_t count);
456
457 static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
458                                              bus_space_handle_t bsh,
459                                              bus_size_t offset,
460                                              const u_int32_t *addr,
461                                              size_t count);
462
463 static __inline void
464 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
465                         bus_size_t offset, const u_int8_t *addr, size_t count)
466 {
467         if (tag == I386_BUS_SPACE_IO) {
468                 outsb(bsh + offset, addr, count);
469         } else {
470                 __asm __volatile("                              \n\
471                         cld                                     \n\
472                 1:      lodsb                                   \n\
473                         movb %%al,(%2)                          \n\
474                         loop 1b"                                :
475                     "=S" (addr), "=c" (count)                   :
476                     "r" (bsh + offset), "0" (addr), "1" (count) :
477                     "%eax", "memory", "cc");
478         }
479 }
480
481 static __inline void
482 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
483                         bus_size_t offset, const u_int16_t *addr, size_t count)
484 {
485         if (tag == I386_BUS_SPACE_IO) {
486                 outsw(bsh + offset, addr, count);
487         } else {
488                 __asm __volatile("                              \n\
489                         cld                                     \n\
490                 1:      lodsw                                   \n\
491                         movw %%ax,(%2)                          \n\
492                         loop 1b"                                :
493                     "=S" (addr), "=c" (count)                   :
494                     "r" (bsh + offset), "0" (addr), "1" (count) :
495                     "%eax", "memory", "cc");
496         }
497 }
498
499 static __inline void
500 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
501                         bus_size_t offset, const u_int32_t *addr, size_t count)
502 {
503         if (tag == I386_BUS_SPACE_IO) {
504                 outsl(bsh + offset, addr, count);
505         } else {
506                 __asm __volatile("                              \n\
507                         cld                                     \n\
508                 1:      lodsl                                   \n\
509                         movl %%eax,(%2)                         \n\
510                         loop 1b"                                :
511                     "=S" (addr), "=c" (count)                   :
512                     "r" (bsh + offset), "0" (addr), "1" (count) :
513                     "%eax", "memory", "cc");
514         }
515 }
516
517 /*
518  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
519  * to bus space described by tag/handle starting at `offset'.
520  */
521
522 static __inline void bus_space_write_region_1(bus_space_tag_t tag,
523                                               bus_space_handle_t bsh,
524                                               bus_size_t offset,
525                                               const u_int8_t *addr,
526                                               size_t count);
527 static __inline void bus_space_write_region_2(bus_space_tag_t tag,
528                                               bus_space_handle_t bsh,
529                                               bus_size_t offset,
530                                               const u_int16_t *addr,
531                                               size_t count);
532 static __inline void bus_space_write_region_4(bus_space_tag_t tag,
533                                               bus_space_handle_t bsh,
534                                               bus_size_t offset,
535                                               const u_int32_t *addr,
536                                               size_t count);
537
538 static __inline void
539 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
540                          bus_size_t offset, const u_int8_t *addr, size_t count)
541 {
542         if (tag == I386_BUS_SPACE_IO) {
543                 int _port_ = bsh + offset;                      \
544                 __asm __volatile("                              \n\
545                         cld                                     \n\
546                 1:      lodsb                                   \n\
547                         outb %%al,%w0                           \n\
548                         incl %0                                 \n\
549                         loop 1b"                                :
550                     "=d" (_port_), "=S" (addr), "=c" (count)    :
551                     "0" (_port_), "1" (addr), "2" (count)       :
552                     "%eax", "memory", "cc");
553         } else {
554                 int _port_ = bsh + offset;                      \
555                 __asm __volatile("                              \n\
556                         cld                                     \n\
557                         repne                                   \n\
558                         movsb"                                  :
559                     "=D" (_port_), "=S" (addr), "=c" (count)    :
560                     "0" (_port_), "1" (addr), "2" (count)       :
561                     "memory", "cc");
562         }
563 }
564
565 static __inline void
566 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
567                          bus_size_t offset, const u_int16_t *addr, size_t count)
568 {
569         if (tag == I386_BUS_SPACE_IO) {
570                 int _port_ = bsh + offset;                      \
571                 __asm __volatile("                              \n\
572                         cld                                     \n\
573                 1:      lodsw                                   \n\
574                         outw %%ax,%w0                           \n\
575                         addl $2,%0                              \n\
576                         loop 1b"                                :
577                     "=d" (_port_), "=S" (addr), "=c" (count)    :
578                     "0" (_port_), "1" (addr), "2" (count)       :
579                     "%eax", "memory", "cc");
580         } else {
581                 int _port_ = bsh + offset;                      \
582                 __asm __volatile("                              \n\
583                         cld                                     \n\
584                         repne                                   \n\
585                         movsw"                                  :
586                     "=D" (_port_), "=S" (addr), "=c" (count)    :
587                     "0" (_port_), "1" (addr), "2" (count)       :
588                     "memory", "cc");
589         }
590 }
591
592 static __inline void
593 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
594                          bus_size_t offset, const u_int32_t *addr, size_t count)
595 {
596         if (tag == I386_BUS_SPACE_IO) {
597                 int _port_ = bsh + offset;                      \
598                 __asm __volatile("                              \n\
599                         cld                                     \n\
600                 1:      lodsl                                   \n\
601                         outl %%eax,%w0                          \n\
602                         addl $4,%0                              \n\
603                         loop 1b"                                :
604                     "=d" (_port_), "=S" (addr), "=c" (count)    :
605                     "0" (_port_), "1" (addr), "2" (count)       :
606                     "%eax", "memory", "cc");
607         } else {
608                 int _port_ = bsh + offset;                      \
609                 __asm __volatile("                              \n\
610                         cld                                     \n\
611                         repne                                   \n\
612                         movsl"                                  :
613                     "=D" (_port_), "=S" (addr), "=c" (count)    :
614                     "0" (_port_), "1" (addr), "2" (count)       :
615                     "memory", "cc");
616         }
617 }
618
619 /*
620  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
621  * by tag/handle/offset `count' times.
622  */
623
624 static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
625                                            bus_space_handle_t bsh,
626                                            bus_size_t offset,
627                                            u_int8_t value, size_t count);
628 static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
629                                            bus_space_handle_t bsh,
630                                            bus_size_t offset,
631                                            u_int16_t value, size_t count);
632 static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
633                                            bus_space_handle_t bsh,
634                                            bus_size_t offset,
635                                            u_int32_t value, size_t count);
636
637 static __inline void
638 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
639                       bus_size_t offset, u_int8_t value, size_t count)
640 {
641         bus_space_handle_t addr = bsh + offset;
642
643         if (tag == I386_BUS_SPACE_IO) {
644                 while (count--)
645                         outb(addr, value);
646         } else {
647                 while (count--)
648                         *(volatile u_int8_t *)(addr) = value;
649         }
650 }
651
652 static __inline void
653 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
654                      bus_size_t offset, u_int16_t value, size_t count)
655 {
656         bus_space_handle_t addr = bsh + offset;
657
658         if (tag == I386_BUS_SPACE_IO) {
659                 while (count--)
660                         outw(addr, value);
661         } else {
662                 while (count--)
663                         *(volatile u_int16_t *)(addr) = value;
664         }
665 }
666
667 static __inline void
668 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
669                       bus_size_t offset, u_int32_t value, size_t count)
670 {
671         bus_space_handle_t addr = bsh + offset;
672
673         if (tag == I386_BUS_SPACE_IO) {
674                 while (count--)
675                         outl(addr, value);
676         } else {
677                 while (count--)
678                         *(volatile u_int32_t *)(addr) = value;
679         }
680 }
681
682 /*
683  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
684  * by tag/handle starting at `offset'.
685  */
686
687 static __inline void bus_space_set_region_1(bus_space_tag_t tag,
688                                             bus_space_handle_t bsh,
689                                             bus_size_t offset, u_int8_t value,
690                                             size_t count);
691 static __inline void bus_space_set_region_2(bus_space_tag_t tag,
692                                             bus_space_handle_t bsh,
693                                             bus_size_t offset, u_int16_t value,
694                                             size_t count);
695 static __inline void bus_space_set_region_4(bus_space_tag_t tag,
696                                             bus_space_handle_t bsh,
697                                             bus_size_t offset, u_int32_t value,
698                                             size_t count);
699
700 static __inline void
701 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
702                        bus_size_t offset, u_int8_t value, size_t count)
703 {
704         bus_space_handle_t addr = bsh + offset;
705
706         if (tag == I386_BUS_SPACE_IO) {
707                 for (; count != 0; count--, addr++)
708                         outb(addr, value);
709         } else {
710                 for (; count != 0; count--, addr++)
711                         *(volatile u_int8_t *)(addr) = value;
712         }
713 }
714
715 static __inline void
716 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
717                        bus_size_t offset, u_int16_t value, size_t count)
718 {
719         bus_space_handle_t addr = bsh + offset;
720
721         if (tag == I386_BUS_SPACE_IO) {
722                 for (; count != 0; count--, addr += 2)
723                         outw(addr, value);
724         } else {
725                 for (; count != 0; count--, addr += 2)
726                         *(volatile u_int16_t *)(addr) = value;
727         }
728 }
729
730 static __inline void
731 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
732                        bus_size_t offset, u_int32_t value, size_t count)
733 {
734         bus_space_handle_t addr = bsh + offset;
735
736         if (tag == I386_BUS_SPACE_IO) {
737                 for (; count != 0; count--, addr += 4)
738                         outl(addr, value);
739         } else {
740                 for (; count != 0; count--, addr += 4)
741                         *(volatile u_int32_t *)(addr) = value;
742         }
743 }
744
745 /*
746  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
747  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
748  */
749
750 static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
751                                              bus_space_handle_t bsh1,
752                                              bus_size_t off1,
753                                              bus_space_handle_t bsh2,
754                                              bus_size_t off2, size_t count);
755
756 static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
757                                              bus_space_handle_t bsh1,
758                                              bus_size_t off1,
759                                              bus_space_handle_t bsh2,
760                                              bus_size_t off2, size_t count);
761
762 static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
763                                              bus_space_handle_t bsh1,
764                                              bus_size_t off1,
765                                              bus_space_handle_t bsh2,
766                                              bus_size_t off2, size_t count);
767
768 static __inline void
769 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
770                         bus_size_t off1, bus_space_handle_t bsh2,
771                         bus_size_t off2, size_t count)
772 {
773         bus_space_handle_t addr1 = bsh1 + off1;
774         bus_space_handle_t addr2 = bsh2 + off2;
775
776         if (tag == I386_BUS_SPACE_IO) {
777                 if (addr1 >= addr2) {
778                         /* src after dest: copy forward */
779                         for (; count != 0; count--, addr1++, addr2++)
780                                 outb(addr2, inb(addr1));
781                 } else {
782                         /* dest after src: copy backwards */
783                         for (addr1 += (count - 1), addr2 += (count - 1);
784                             count != 0; count--, addr1--, addr2--)
785                                 outb(addr2, inb(addr1));
786                 }
787         } else {
788                 if (addr1 >= addr2) {
789                         /* src after dest: copy forward */
790                         for (; count != 0; count--, addr1++, addr2++)
791                                 *(volatile u_int8_t *)(addr2) =
792                                     *(volatile u_int8_t *)(addr1);
793                 } else {
794                         /* dest after src: copy backwards */
795                         for (addr1 += (count - 1), addr2 += (count - 1);
796                             count != 0; count--, addr1--, addr2--)
797                                 *(volatile u_int8_t *)(addr2) =
798                                     *(volatile u_int8_t *)(addr1);
799                 }
800         }
801 }
802
803 static __inline void
804 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
805                         bus_size_t off1, bus_space_handle_t bsh2,
806                         bus_size_t off2, size_t count)
807 {
808         bus_space_handle_t addr1 = bsh1 + off1;
809         bus_space_handle_t addr2 = bsh2 + off2;
810
811         if (tag == I386_BUS_SPACE_IO) {
812                 if (addr1 >= addr2) {
813                         /* src after dest: copy forward */
814                         for (; count != 0; count--, addr1 += 2, addr2 += 2)
815                                 outw(addr2, inw(addr1));
816                 } else {
817                         /* dest after src: copy backwards */
818                         for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
819                             count != 0; count--, addr1 -= 2, addr2 -= 2)
820                                 outw(addr2, inw(addr1));
821                 }
822         } else {
823                 if (addr1 >= addr2) {
824                         /* src after dest: copy forward */
825                         for (; count != 0; count--, addr1 += 2, addr2 += 2)
826                                 *(volatile u_int16_t *)(addr2) =
827                                     *(volatile u_int16_t *)(addr1);
828                 } else {
829                         /* dest after src: copy backwards */
830                         for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
831                             count != 0; count--, addr1 -= 2, addr2 -= 2)
832                                 *(volatile u_int16_t *)(addr2) =
833                                     *(volatile u_int16_t *)(addr1);
834                 }
835         }
836 }
837
838 static __inline void
839 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
840                         bus_size_t off1, bus_space_handle_t bsh2,
841                         bus_size_t off2, size_t count)
842 {
843         bus_space_handle_t addr1 = bsh1 + off1;
844         bus_space_handle_t addr2 = bsh2 + off2;
845
846         if (tag == I386_BUS_SPACE_IO) {
847                 if (addr1 >= addr2) {
848                         /* src after dest: copy forward */
849                         for (; count != 0; count--, addr1 += 4, addr2 += 4)
850                                 outl(addr2, inl(addr1));
851                 } else {
852                         /* dest after src: copy backwards */
853                         for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
854                             count != 0; count--, addr1 -= 4, addr2 -= 4)
855                                 outl(addr2, inl(addr1));
856                 }
857         } else {
858                 if (addr1 >= addr2) {
859                         /* src after dest: copy forward */
860                         for (; count != 0; count--, addr1 += 4, addr2 += 4)
861                                 *(volatile u_int32_t *)(addr2) =
862                                     *(volatile u_int32_t *)(addr1);
863                 } else {
864                         /* dest after src: copy backwards */
865                         for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
866                             count != 0; count--, addr1 -= 4, addr2 -= 4)
867                                 *(volatile u_int32_t *)(addr2) =
868                                     *(volatile u_int32_t *)(addr1);
869                 }
870         }
871 }
872
873 /*
874  * Bus read/write barrier methods.
875  *
876  *      void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
877  *                             bus_size_t offset, bus_size_t len, int flags);
878  *
879  * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
880  * prevent reordering by the compiler; all Intel x86 processors currently
881  * retire operations outside the CPU in program order.
882  */
883 #define BUS_SPACE_BARRIER_READ  0x01            /* force read barrier */
884 #define BUS_SPACE_BARRIER_WRITE 0x02            /* force write barrier */
885
886 static __inline void
887 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
888                 bus_size_t offset __unused, bus_size_t len __unused, int flags)
889 {
890         if (flags & BUS_SPACE_BARRIER_READ)
891                 __asm __volatile("lock; addl $0,0(%%esp)" : : : "memory");
892         else
893                 __asm __volatile("" : : : "memory");
894 }
895
896 #endif /* _CPU_BUS_AT386_H_ */