[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/amd64/include/bus.h

Version: -  FREEBSD  -  FREEBSD7  -  FREEBSD71  -  FREEBSD70  -  FREEBSD6  -  FREEBSD64  -  FREEBSD63  -  FREEBSD62  -  FREEBSD61  -  FREEBSD60  -  FREEBSD5  -  FREEBSD55  -  FREEBSD54  -  FREEBSD53  -  FREEBSD52  -  FREEBSD51  -  FREEBSD50  -  FREEBSD4  -  FREEBSD3  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  OPENSOLARIS  -  minix-3-1-1  -  TRUSTEDBSD-SEBSD  -  FREEBSD-LIBC  -  FREEBSD7-LIBC  -  FREEBSD6-LIBC  -  GLIBC27 
SearchContext: -  none  -  excerpts  -  bigexcerpts 

  1 /*-
  2  * Copyright (c) KATO Takenori, 1999.
  3  *
  4  * All rights reserved.  Unpublished rights reserved under the copyright
  5  * laws of Japan.
  6  *
  7  * Redistribution and use in source and binary forms, with or without
  8  * modification, are permitted provided that the following conditions
  9  * are met:
 10  * 
 11  * 1. Redistributions of source code must retain the above copyright
 12  *    notice, this list of conditions and the following disclaimer as
 13  *    the first lines of this file unmodified.
 14  * 2. Redistributions in binary form must reproduce the above copyright
 15  *    notice, this list of conditions and the following disclaimer in the
 16  *    documentation and/or other materials provided with the distribution.
 17  * 3. The name of the author may not be used to endorse or promote products
 18  *    derived from this software without specific prior written permission.
 19  * 
 20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 30  *
 31  * $FreeBSD: src/sys/amd64/include/bus.h,v 1.17 2006/03/14 00:01:56 peter Exp $
 32  */
 33 
 34 /*      $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $    */
 35 
 36 /*-
 37  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
 38  * All rights reserved.
 39  *
 40  * This code is derived from software contributed to The NetBSD Foundation
 41  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
 42  * NASA Ames Research Center.
 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 the NetBSD
 55  *      Foundation, Inc. and its contributors.
 56  * 4. Neither the name of The NetBSD Foundation nor the names of its
 57  *    contributors may be used to endorse or promote products derived
 58  *    from this software without specific prior written permission.
 59  *
 60  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 61  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 62  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 63  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 64  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 65  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 66  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 67  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 68  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 69  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 70  * POSSIBILITY OF SUCH DAMAGE.
 71  */
 72 
 73 /*-
 74  * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
 75  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
 76  *
 77  * Redistribution and use in source and binary forms, with or without
 78  * modification, are permitted provided that the following conditions
 79  * are met:
 80  * 1. Redistributions of source code must retain the above copyright
 81  *    notice, this list of conditions and the following disclaimer.
 82  * 2. Redistributions in binary form must reproduce the above copyright
 83  *    notice, this list of conditions and the following disclaimer in the
 84  *    documentation and/or other materials provided with the distribution.
 85  * 3. All advertising materials mentioning features or use of this software
 86  *    must display the following acknowledgement:
 87  *      This product includes software developed by Christopher G. Demetriou
 88  *      for the NetBSD Project.
 89  * 4. The name of the author may not be used to endorse or promote products
 90  *    derived from this software without specific prior written permission
 91  *
 92  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 93  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 94  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 95  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 96  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 97  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 98  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 99  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
100  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
101  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
102  */
103 
104 #ifndef _AMD64_BUS_H_
105 #define _AMD64_BUS_H_
106 
107 #include <machine/_bus.h>
108 #include <machine/cpufunc.h>
109 
110 /*
111  * Values for the amd64 bus space tag, not to be used directly by MI code.
112  */
113 #define AMD64_BUS_SPACE_IO      0       /* space is i/o space */
114 #define AMD64_BUS_SPACE_MEM     1       /* space is mem space */
115 
116 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
117 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
118 #define BUS_SPACE_MAXSIZE       0xFFFFFFFF
119 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
120 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
121 #define BUS_SPACE_MAXADDR       0xFFFFFFFFFFFFFFFFULL
122 
123 #define BUS_SPACE_UNRESTRICTED  (~0)
124 
125 /*
126  * Map a region of device bus space into CPU virtual address space.
127  */
128 
129 static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
130                                   bus_size_t size, int flags,
131                                   bus_space_handle_t *bshp);
132 
133 static __inline int
134 bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
135               bus_size_t size __unused, int flags __unused,
136               bus_space_handle_t *bshp)
137 {
138 
139         *bshp = addr;
140         return (0);
141 }
142 
143 /*
144  * Unmap a region of device bus space.
145  */
146 
147 static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
148                                      bus_size_t size);
149 
150 static __inline void
151 bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
152                 bus_size_t size __unused)
153 {
154 }
155 
156 /*
157  * Get a new handle for a subregion of an already-mapped area of bus space.
158  */
159 
160 static __inline int bus_space_subregion(bus_space_tag_t t,
161                                         bus_space_handle_t bsh,
162                                         bus_size_t offset, bus_size_t size,
163                                         bus_space_handle_t *nbshp);
164 
165 static __inline int
166 bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh,
167                     bus_size_t offset, bus_size_t size __unused,
168                     bus_space_handle_t *nbshp)
169 {
170 
171         *nbshp = bsh + offset;
172         return (0);
173 }
174 
175 /*
176  * Allocate a region of memory that is accessible to devices in bus space.
177  */
178 
179 int     bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
180                         bus_addr_t rend, bus_size_t size, bus_size_t align,
181                         bus_size_t boundary, int flags, bus_addr_t *addrp,
182                         bus_space_handle_t *bshp);
183 
184 /*
185  * Free a region of bus space accessible memory.
186  */
187 
188 static __inline void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
189                                     bus_size_t size);
190 
191 static __inline void
192 bus_space_free(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
193                bus_size_t size __unused)
194 {
195 }
196 
197 
198 /*
199  * Read a 1, 2, 4, or 8 byte quantity from bus space
200  * described by tag/handle/offset.
201  */
202 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
203                                           bus_space_handle_t handle,
204                                           bus_size_t offset);
205 
206 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
207                                            bus_space_handle_t handle,
208                                            bus_size_t offset);
209 
210 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
211                                            bus_space_handle_t handle,
212                                            bus_size_t offset);
213 
214 static __inline u_int8_t
215 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
216                  bus_size_t offset)
217 {
218 
219         if (tag == AMD64_BUS_SPACE_IO)
220                 return (inb(handle + offset));
221         return (*(volatile u_int8_t *)(handle + offset));
222 }
223 
224 static __inline u_int16_t
225 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
226                  bus_size_t offset)
227 {
228 
229         if (tag == AMD64_BUS_SPACE_IO)
230                 return (inw(handle + offset));
231         return (*(volatile u_int16_t *)(handle + offset));
232 }
233 
234 static __inline u_int32_t
235 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
236                  bus_size_t offset)
237 {
238 
239         if (tag == AMD64_BUS_SPACE_IO)
240                 return (inl(handle + offset));
241         return (*(volatile u_int32_t *)(handle + offset));
242 }
243 
244 #if 0   /* Cause a link error for bus_space_read_8 */
245 #define bus_space_read_8(t, h, o)       !!! bus_space_read_8 unimplemented !!!
246 #endif
247 
248 /*
249  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
250  * described by tag/handle/offset and copy into buffer provided.
251  */
252 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
253                                             bus_space_handle_t bsh,
254                                             bus_size_t offset, u_int8_t *addr,
255                                             size_t count);
256 
257 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
258                                             bus_space_handle_t bsh,
259                                             bus_size_t offset, u_int16_t *addr,
260                                             size_t count);
261 
262 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
263                                             bus_space_handle_t bsh,
264                                             bus_size_t offset, u_int32_t *addr,
265                                             size_t count);
266 
267 static __inline void
268 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
269                        bus_size_t offset, u_int8_t *addr, size_t count)
270 {
271 
272         if (tag == AMD64_BUS_SPACE_IO)
273                 insb(bsh + offset, addr, count);
274         else {
275 #ifdef __GNUCLIKE_ASM
276                 __asm __volatile("                              \n\
277                         cld                                     \n\
278                 1:      movb (%2),%%al                          \n\
279                         stosb                                   \n\
280                         loop 1b"                                :
281                     "=D" (addr), "=c" (count)                   :
282                     "r" (bsh + offset), "" (addr), "1" (count) :
283                     "%eax", "memory");
284 #endif
285         }
286 }
287 
288 static __inline void
289 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
290                        bus_size_t offset, u_int16_t *addr, size_t count)
291 {
292 
293         if (tag == AMD64_BUS_SPACE_IO)
294                 insw(bsh + offset, addr, count);
295         else {
296 #ifdef __GNUCLIKE_ASM
297                 __asm __volatile("                              \n\
298                         cld                                     \n\
299                 1:      movw (%2),%%ax                          \n\
300                         stosw                                   \n\
301                         loop 1b"                                :
302                     "=D" (addr), "=c" (count)                   :
303                     "r" (bsh + offset), "" (addr), "1" (count) :
304                     "%eax", "memory");
305 #endif
306         }
307 }
308 
309 static __inline void
310 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
311                        bus_size_t offset, u_int32_t *addr, size_t count)
312 {
313 
314         if (tag == AMD64_BUS_SPACE_IO)
315                 insl(bsh + offset, addr, count);
316         else {
317 #ifdef __GNUCLIKE_ASM
318                 __asm __volatile("                              \n\
319                         cld                                     \n\
320                 1:      movl (%2),%%eax                         \n\
321                         stosl                                   \n\
322                         loop 1b"                                :
323                     "=D" (addr), "=c" (count)                   :
324                     "r" (bsh + offset), "" (addr), "1" (count) :
325                     "%eax", "memory");
326 #endif
327         }
328 }
329 
330 #if 0   /* Cause a link error for bus_space_read_multi_8 */
331 #define bus_space_read_multi_8  !!! bus_space_read_multi_8 unimplemented !!!
332 #endif
333 
334 /*
335  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
336  * described by tag/handle and starting at `offset' and copy into
337  * buffer provided.
338  */
339 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
340                                              bus_space_handle_t bsh,
341                                              bus_size_t offset, u_int8_t *addr,
342                                              size_t count);
343 
344 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
345                                              bus_space_handle_t bsh,
346                                              bus_size_t offset, u_int16_t *addr,
347                                              size_t count);
348 
349 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
350                                              bus_space_handle_t bsh,
351                                              bus_size_t offset, u_int32_t *addr,
352                                              size_t count);
353 
354 
355 static __inline void
356 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
357                         bus_size_t offset, u_int8_t *addr, size_t count)
358 {
359 
360         if (tag == AMD64_BUS_SPACE_IO) {
361                 int _port_ = bsh + offset;
362 #ifdef __GNUCLIKE_ASM
363                 __asm __volatile("                              \n\
364                         cld                                     \n\
365                 1:      inb %w2,%%al                            \n\
366                         stosb                                   \n\
367                         incl %2                                 \n\
368                         loop 1b"                                :
369                     "=D" (addr), "=c" (count), "=d" (_port_)    :
370                     "" (addr), "1" (count), "2" (_port_)       :
371                     "%eax", "memory", "cc");
372 #endif
373         } else {
374                 bus_space_handle_t _port_ = bsh + offset;
375 #ifdef __GNUCLIKE_ASM
376                 __asm __volatile("                              \n\
377                         cld                                     \n\
378                         repne                                   \n\
379                         movsb"                                  :
380                     "=D" (addr), "=c" (count), "=S" (_port_)    :
381                     "" (addr), "1" (count), "2" (_port_)       :
382                     "memory", "cc");
383 #endif
384         }
385 }
386 
387 static __inline void
388 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
389                         bus_size_t offset, u_int16_t *addr, size_t count)
390 {
391 
392         if (tag == AMD64_BUS_SPACE_IO) {
393                 int _port_ = bsh + offset;
394 #ifdef __GNUCLIKE_ASM
395                 __asm __volatile("                              \n\
396                         cld                                     \n\
397                 1:      inw %w2,%%ax                            \n\
398                         stosw                                   \n\
399                         addl $2,%2                              \n\
400                         loop 1b"                                :
401                     "=D" (addr), "=c" (count), "=d" (_port_)    :
402                     "" (addr), "1" (count), "2" (_port_)       :
403                     "%eax", "memory", "cc");
404 #endif
405         } else {
406                 bus_space_handle_t _port_ = bsh + offset;
407 #ifdef __GNUCLIKE_ASM
408                 __asm __volatile("                              \n\
409                         cld                                     \n\
410                         repne                                   \n\
411                         movsw"                                  :
412                     "=D" (addr), "=c" (count), "=S" (_port_)    :
413                     "" (addr), "1" (count), "2" (_port_)       :
414                     "memory", "cc");
415 #endif
416         }
417 }
418 
419 static __inline void
420 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
421                         bus_size_t offset, u_int32_t *addr, size_t count)
422 {
423 
424         if (tag == AMD64_BUS_SPACE_IO) {
425                 int _port_ = bsh + offset;
426 #ifdef __GNUCLIKE_ASM
427                 __asm __volatile("                              \n\
428                         cld                                     \n\
429                 1:      inl %w2,%%eax                           \n\
430                         stosl                                   \n\
431                         addl $4,%2                              \n\
432                         loop 1b"                                :
433                     "=D" (addr), "=c" (count), "=d" (_port_)    :
434                     "" (addr), "1" (count), "2" (_port_)       :
435                     "%eax", "memory", "cc");
436 #endif
437         } else {
438                 bus_space_handle_t _port_ = bsh + offset;
439 #ifdef __GNUCLIKE_ASM
440                 __asm __volatile("                              \n\
441                         cld                                     \n\
442                         repne                                   \n\
443                         movsl"                                  :
444                     "=D" (addr), "=c" (count), "=S" (_port_)    :
445                     "" (addr), "1" (count), "2" (_port_)       :
446                     "memory", "cc");
447 #endif
448         }
449 }
450 
451 #if 0   /* Cause a link error for bus_space_read_region_8 */
452 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
453 #endif
454 
455 /*
456  * Write the 1, 2, 4, or 8 byte value `value' to bus space
457  * described by tag/handle/offset.
458  */
459 
460 static __inline void bus_space_write_1(bus_space_tag_t tag,
461                                        bus_space_handle_t bsh,
462                                        bus_size_t offset, u_int8_t value);
463 
464 static __inline void bus_space_write_2(bus_space_tag_t tag,
465                                        bus_space_handle_t bsh,
466                                        bus_size_t offset, u_int16_t value);
467 
468 static __inline void bus_space_write_4(bus_space_tag_t tag,
469                                        bus_space_handle_t bsh,
470                                        bus_size_t offset, u_int32_t value);
471 
472 static __inline void
473 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
474                        bus_size_t offset, u_int8_t value)
475 {
476 
477         if (tag == AMD64_BUS_SPACE_IO)
478                 outb(bsh + offset, value);
479         else
480                 *(volatile u_int8_t *)(bsh + offset) = value;
481 }
482 
483 static __inline void
484 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
485                        bus_size_t offset, u_int16_t value)
486 {
487 
488         if (tag == AMD64_BUS_SPACE_IO)
489                 outw(bsh + offset, value);
490         else
491                 *(volatile u_int16_t *)(bsh + offset) = value;
492 }
493 
494 static __inline void
495 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
496                        bus_size_t offset, u_int32_t value)
497 {
498 
499         if (tag == AMD64_BUS_SPACE_IO)
500                 outl(bsh + offset, value);
501         else
502                 *(volatile u_int32_t *)(bsh + offset) = value;
503 }
504 
505 #if 0   /* Cause a link error for bus_space_write_8 */
506 #define bus_space_write_8       !!! bus_space_write_8 not implemented !!!
507 #endif
508 
509 /*
510  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
511  * provided to bus space described by tag/handle/offset.
512  */
513 
514 static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
515                                              bus_space_handle_t bsh,
516                                              bus_size_t offset,
517                                              const u_int8_t *addr,
518                                              size_t count);
519 static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
520                                              bus_space_handle_t bsh,
521                                              bus_size_t offset,
522                                              const u_int16_t *addr,
523                                              size_t count);
524 
525 static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
526                                              bus_space_handle_t bsh,
527                                              bus_size_t offset,
528                                              const u_int32_t *addr,
529                                              size_t count);
530 
531 static __inline void
532 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
533                         bus_size_t offset, const u_int8_t *addr, size_t count)
534 {
535 
536         if (tag == AMD64_BUS_SPACE_IO)
537                 outsb(bsh + offset, addr, count);
538         else {
539 #ifdef __GNUCLIKE_ASM
540                 __asm __volatile("                              \n\
541                         cld                                     \n\
542                 1:      lodsb                                   \n\
543                         movb %%al,(%2)                          \n\
544                         loop 1b"                                :
545                     "=S" (addr), "=c" (count)                   :
546                     "r" (bsh + offset), "" (addr), "1" (count) :
547                     "%eax", "memory", "cc");
548 #endif
549         }
550 }
551 
552 static __inline void
553 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
554                         bus_size_t offset, const u_int16_t *addr, size_t count)
555 {
556 
557         if (tag == AMD64_BUS_SPACE_IO)
558                 outsw(bsh + offset, addr, count);
559         else {
560 #ifdef __GNUCLIKE_ASM
561                 __asm __volatile("                              \n\
562                         cld                                     \n\
563                 1:      lodsw                                   \n\
564                         movw %%ax,(%2)                          \n\
565                         loop 1b"                                :
566                     "=S" (addr), "=c" (count)                   :
567                     "r" (bsh + offset), "" (addr), "1" (count) :
568                     "%eax", "memory", "cc");
569 #endif
570         }
571 }
572 
573 static __inline void
574 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
575                         bus_size_t offset, const u_int32_t *addr, size_t count)
576 {
577 
578         if (tag == AMD64_BUS_SPACE_IO)
579                 outsl(bsh + offset, addr, count);
580         else {
581 #ifdef __GNUCLIKE_ASM
582                 __asm __volatile("                              \n\
583                         cld                                     \n\
584                 1:      lodsl                                   \n\
585                         movl %%eax,(%2)                         \n\
586                         loop 1b"                                :
587                     "=S" (addr), "=c" (count)                   :
588                     "r" (bsh + offset), "" (addr), "1" (count) :
589                     "%eax", "memory", "cc");
590 #endif
591         }
592 }
593 
594 #if 0   /* Cause a link error for bus_space_write_multi_8 */
595 #define bus_space_write_multi_8(t, h, o, a, c)                          \
596                         !!! bus_space_write_multi_8 unimplemented !!!
597 #endif
598 
599 /*
600  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
601  * to bus space described by tag/handle starting at `offset'.
602  */
603 
604 static __inline void bus_space_write_region_1(bus_space_tag_t tag,
605                                               bus_space_handle_t bsh,
606                                               bus_size_t offset,
607                                               const u_int8_t *addr,
608                                               size_t count);
609 static __inline void bus_space_write_region_2(bus_space_tag_t tag,
610                                               bus_space_handle_t bsh,
611                                               bus_size_t offset,
612                                               const u_int16_t *addr,
613                                               size_t count);
614 static __inline void bus_space_write_region_4(bus_space_tag_t tag,
615                                               bus_space_handle_t bsh,
616                                               bus_size_t offset,
617                                               const u_int32_t *addr,
618                                               size_t count);
619 
620 static __inline void
621 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
622                          bus_size_t offset, const u_int8_t *addr, size_t count)
623 {
624 
625         if (tag == AMD64_BUS_SPACE_IO) {
626                 int _port_ = bsh + offset;
627 #ifdef __GNUCLIKE_ASM
628                 __asm __volatile("                              \n\
629                         cld                                     \n\
630                 1:      lodsb                                   \n\
631                         outb %%al,%w0                           \n\
632                         incl %0                                 \n\
633                         loop 1b"                                :
634                     "=d" (_port_), "=S" (addr), "=c" (count)    :
635                     "" (_port_), "1" (addr), "2" (count)       :
636                     "%eax", "memory", "cc");
637 #endif
638         } else {
639                 bus_space_handle_t _port_ = bsh + offset;
640 #ifdef __GNUCLIKE_ASM
641                 __asm __volatile("                              \n\
642                         cld                                     \n\
643                         repne                                   \n\
644                         movsb"                                  :
645                     "=D" (_port_), "=S" (addr), "=c" (count)    :
646                     "" (_port_), "1" (addr), "2" (count)       :
647                     "memory", "cc");
648 #endif
649         }
650 }
651 
652 static __inline void
653 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
654                          bus_size_t offset, const u_int16_t *addr, size_t count)
655 {
656 
657         if (tag == AMD64_BUS_SPACE_IO) {
658                 int _port_ = bsh + offset;
659 #ifdef __GNUCLIKE_ASM
660                 __asm __volatile("                              \n\
661                         cld                                     \n\
662                 1:      lodsw                                   \n\
663                         outw %%ax,%w0                           \n\
664                         addl $2,%0                              \n\
665                         loop 1b"                                :
666                     "=d" (_port_), "=S" (addr), "=c" (count)    :
667                     "" (_port_), "1" (addr), "2" (count)       :
668                     "%eax", "memory", "cc");
669 #endif
670         } else {
671                 bus_space_handle_t _port_ = bsh + offset;
672 #ifdef __GNUCLIKE_ASM
673                 __asm __volatile("                              \n\
674                         cld                                     \n\
675                         repne                                   \n\
676                         movsw"                                  :
677                     "=D" (_port_), "=S" (addr), "=c" (count)    :
678                     "" (_port_), "1" (addr), "2" (count)       :
679                     "memory", "cc");
680 #endif
681         }
682 }
683 
684 static __inline void
685 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
686                          bus_size_t offset, const u_int32_t *addr, size_t count)
687 {
688 
689         if (tag == AMD64_BUS_SPACE_IO) {
690                 int _port_ = bsh + offset;
691 #ifdef __GNUCLIKE_ASM
692                 __asm __volatile("                              \n\
693                         cld                                     \n\
694                 1:      lodsl                                   \n\
695                         outl %%eax,%w0                          \n\
696                         addl $4,%0                              \n\
697                         loop 1b"                                :
698                     "=d" (_port_), "=S" (addr), "=c" (count)    :
699                     "" (_port_), "1" (addr), "2" (count)       :
700                     "%eax", "memory", "cc");
701 #endif
702         } else {
703                 bus_space_handle_t _port_ = bsh + offset;
704 #ifdef __GNUCLIKE_ASM
705                 __asm __volatile("                              \n\
706                         cld                                     \n\
707                         repne                                   \n\
708                         movsl"                                  :
709                     "=D" (_port_), "=S" (addr), "=c" (count)    :
710                     "" (_port_), "1" (addr), "2" (count)       :
711                     "memory", "cc");
712 #endif
713         }
714 }
715 
716 #if 0   /* Cause a link error for bus_space_write_region_8 */
717 #define bus_space_write_region_8                                        \
718                         !!! bus_space_write_region_8 unimplemented !!!
719 #endif
720 
721 /*
722  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
723  * by tag/handle/offset `count' times.
724  */
725 
726 static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
727                                            bus_space_handle_t bsh,
728                                            bus_size_t offset,
729                                            u_int8_t value, size_t count);
730 static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
731                                            bus_space_handle_t bsh,
732                                            bus_size_t offset,
733                                            u_int16_t value, size_t count);
734 static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
735                                            bus_space_handle_t bsh,
736                                            bus_size_t offset,
737                                            u_int32_t value, size_t count);
738 
739 static __inline void
740 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
741                       bus_size_t offset, u_int8_t value, size_t count)
742 {
743         bus_space_handle_t addr = bsh + offset;
744 
745         if (tag == AMD64_BUS_SPACE_IO)
746                 while (count--)
747                         outb(addr, value);
748         else
749                 while (count--)
750                         *(volatile u_int8_t *)(addr) = value;
751 }
752 
753 static __inline void
754 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
755                      bus_size_t offset, u_int16_t value, size_t count)
756 {
757         bus_space_handle_t addr = bsh + offset;
758 
759         if (tag == AMD64_BUS_SPACE_IO)
760                 while (count--)
761                         outw(addr, value);
762         else
763                 while (count--)
764                         *(volatile u_int16_t *)(addr) = value;
765 }
766 
767 static __inline void
768 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
769                       bus_size_t offset, u_int32_t value, size_t count)
770 {
771         bus_space_handle_t addr = bsh + offset;
772 
773         if (tag == AMD64_BUS_SPACE_IO)
774                 while (count--)
775                         outl(addr, value);
776         else
777                 while (count--)
778                         *(volatile u_int32_t *)(addr) = value;
779 }
780 
781 #if 0   /* Cause a link error for bus_space_set_multi_8 */
782 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
783 #endif
784 
785 /*
786  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
787  * by tag/handle starting at `offset'.
788  */
789 
790 static __inline void bus_space_set_region_1(bus_space_tag_t tag,
791                                             bus_space_handle_t bsh,
792                                             bus_size_t offset, u_int8_t value,
793                                             size_t count);
794 static __inline void bus_space_set_region_2(bus_space_tag_t tag,
795                                             bus_space_handle_t bsh,
796                                             bus_size_t offset, u_int16_t value,
797                                             size_t count);
798 static __inline void bus_space_set_region_4(bus_space_tag_t tag,
799                                             bus_space_handle_t bsh,
800                                             bus_size_t offset, u_int32_t value,
801                                             size_t count);
802 
803 static __inline void
804 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
805                        bus_size_t offset, u_int8_t value, size_t count)
806 {
807         bus_space_handle_t addr = bsh + offset;
808 
809         if (tag == AMD64_BUS_SPACE_IO)
810                 for (; count != 0; count--, addr++)
811                         outb(addr, value);
812         else
813                 for (; count != 0; count--, addr++)
814                         *(volatile u_int8_t *)(addr) = value;
815 }
816 
817 static __inline void
818 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
819                        bus_size_t offset, u_int16_t value, size_t count)
820 {
821         bus_space_handle_t addr = bsh + offset;
822 
823         if (tag == AMD64_BUS_SPACE_IO)
824                 for (; count != 0; count--, addr += 2)
825                         outw(addr, value);
826         else
827                 for (; count != 0; count--, addr += 2)
828                         *(volatile u_int16_t *)(addr) = value;
829 }
830 
831 static __inline void
832 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
833                        bus_size_t offset, u_int32_t value, size_t count)
834 {
835         bus_space_handle_t addr = bsh + offset;
836 
837         if (tag == AMD64_BUS_SPACE_IO)
838                 for (; count != 0; count--, addr += 4)
839                         outl(addr, value);
840         else
841                 for (; count != 0; count--, addr += 4)
842                         *(volatile u_int32_t *)(addr) = value;
843 }
844 
845 #if 0   /* Cause a link error for bus_space_set_region_8 */
846 #define bus_space_set_region_8  !!! bus_space_set_region_8 unimplemented !!!
847 #endif
848 
849 /*
850  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
851  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
852  */
853 
854 static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
855                                              bus_space_handle_t bsh1,
856                                              bus_size_t off1,
857                                              bus_space_handle_t bsh2,
858                                              bus_size_t off2, size_t count);
859 
860 static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
861                                              bus_space_handle_t bsh1,
862                                              bus_size_t off1,
863                                              bus_space_handle_t bsh2,
864                                              bus_size_t off2, size_t count);
865 
866 static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
867                                              bus_space_handle_t bsh1,
868                                              bus_size_t off1,
869                                              bus_space_handle_t bsh2,
870                                              bus_size_t off2, size_t count);
871 
872 static __inline void
873 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
874                         bus_size_t off1, bus_space_handle_t bsh2,
875                         bus_size_t off2, size_t count)
876 {
877         bus_space_handle_t addr1 = bsh1 + off1;
878         bus_space_handle_t addr2 = bsh2 + off2;
879 
880         if (tag == AMD64_BUS_SPACE_IO) {
881                 if (addr1 >= addr2) {
882                         /* src after dest: copy forward */
883                         for (; count != 0; count--, addr1++, addr2++)
884                                 outb(addr2, inb(addr1));
885                 } else {
886                         /* dest after src: copy backwards */
887                         for (addr1 += (count - 1), addr2 += (count - 1);
888                             count != 0; count--, addr1--, addr2--)
889                                 outb(addr2, inb(addr1));
890                 }
891         } else {
892                 if (addr1 >= addr2) {