]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - sys/amd64/include/bus.h
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / sys / amd64 / include / bus.h
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$
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), "0" (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), "0" (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), "0" (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                     "0" (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                     "0" (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                     "0" (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                     "0" (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                     "0" (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                     "0" (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), "0" (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), "0" (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), "0" (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                     "0" (_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                     "0" (_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                     "0" (_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                     "0" (_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                     "0" (_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                     "0" (_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) {
893                         /* src after dest: copy forward */
894                         for (; count != 0; count--, addr1++, addr2++)
895                                 *(volatile u_int8_t *)(addr2) =
896                                     *(volatile u_int8_t *)(addr1);
897                 } else {
898                         /* dest after src: copy backwards */
899                         for (addr1 += (count - 1), addr2 += (count - 1);
900                             count != 0; count--, addr1--, addr2--)
901                                 *(volatile u_int8_t *)(addr2) =
902                                     *(volatile u_int8_t *)(addr1);
903                 }
904         }
905 }
906
907 static __inline void
908 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
909                         bus_size_t off1, bus_space_handle_t bsh2,
910                         bus_size_t off2, size_t count)
911 {
912         bus_space_handle_t addr1 = bsh1 + off1;
913         bus_space_handle_t addr2 = bsh2 + off2;
914
915         if (tag == AMD64_BUS_SPACE_IO) {
916                 if (addr1 >= addr2) {
917                         /* src after dest: copy forward */
918                         for (; count != 0; count--, addr1 += 2, addr2 += 2)
919                                 outw(addr2, inw(addr1));
920                 } else {
921                         /* dest after src: copy backwards */
922                         for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
923                             count != 0; count--, addr1 -= 2, addr2 -= 2)
924                                 outw(addr2, inw(addr1));
925                 }
926         } else {
927                 if (addr1 >= addr2) {
928                         /* src after dest: copy forward */
929                         for (; count != 0; count--, addr1 += 2, addr2 += 2)
930                                 *(volatile u_int16_t *)(addr2) =
931                                     *(volatile u_int16_t *)(addr1);
932                 } else {
933                         /* dest after src: copy backwards */
934                         for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
935                             count != 0; count--, addr1 -= 2, addr2 -= 2)
936                                 *(volatile u_int16_t *)(addr2) =
937                                     *(volatile u_int16_t *)(addr1);
938                 }
939         }
940 }
941
942 static __inline void
943 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
944                         bus_size_t off1, bus_space_handle_t bsh2,
945                         bus_size_t off2, size_t count)
946 {
947         bus_space_handle_t addr1 = bsh1 + off1;
948         bus_space_handle_t addr2 = bsh2 + off2;
949
950         if (tag == AMD64_BUS_SPACE_IO) {
951                 if (addr1 >= addr2) {
952                         /* src after dest: copy forward */
953                         for (; count != 0; count--, addr1 += 4, addr2 += 4)
954                                 outl(addr2, inl(addr1));
955                 } else {
956                         /* dest after src: copy backwards */
957                         for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
958                             count != 0; count--, addr1 -= 4, addr2 -= 4)
959                                 outl(addr2, inl(addr1));
960                 }
961         } else {
962                 if (addr1 >= addr2) {
963                         /* src after dest: copy forward */
964                         for (; count != 0; count--, addr1 += 4, addr2 += 4)
965                                 *(volatile u_int32_t *)(addr2) =
966                                     *(volatile u_int32_t *)(addr1);
967                 } else {
968                         /* dest after src: copy backwards */
969                         for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
970                             count != 0; count--, addr1 -= 4, addr2 -= 4)
971                                 *(volatile u_int32_t *)(addr2) =
972                                     *(volatile u_int32_t *)(addr1);
973                 }
974         }
975 }
976
977 #if 0   /* Cause a link error for bus_space_copy_8 */
978 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!!
979 #endif
980
981 /*
982  * Bus read/write barrier methods.
983  *
984  *      void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
985  *                             bus_size_t offset, bus_size_t len, int flags);
986  *
987  *
988  * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
989  * prevent reordering by the compiler; all Intel x86 processors currently
990  * retire operations outside the CPU in program order.
991  */
992 #define BUS_SPACE_BARRIER_READ  0x01            /* force read barrier */
993 #define BUS_SPACE_BARRIER_WRITE 0x02            /* force write barrier */
994
995 static __inline void
996 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
997                   bus_size_t offset __unused, bus_size_t len __unused, int flags)
998 {
999 #ifdef __GNUCLIKE_ASM
1000         if (flags & BUS_SPACE_BARRIER_READ)
1001                 __asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory");
1002         else
1003                 __asm __volatile("" : : : "memory");
1004 #endif
1005 }
1006
1007 #ifdef BUS_SPACE_NO_LEGACY
1008 #undef inb
1009 #undef outb
1010 #define inb(a) compiler_error
1011 #define inw(a) compiler_error
1012 #define inl(a) compiler_error
1013 #define outb(a, b) compiler_error
1014 #define outw(a, b) compiler_error
1015 #define outl(a, b) compiler_error
1016 #endif
1017
1018 #include <machine/bus_dma.h>
1019
1020 /*
1021  * Stream accesses are the same as normal accesses on amd64; there are no
1022  * supported bus systems with an endianess different from the host one.
1023  */
1024 #define bus_space_read_stream_1(t, h, o)        bus_space_read_1((t), (h), (o))
1025 #define bus_space_read_stream_2(t, h, o)        bus_space_read_2((t), (h), (o))
1026 #define bus_space_read_stream_4(t, h, o)        bus_space_read_4((t), (h), (o))
1027
1028 #define bus_space_read_multi_stream_1(t, h, o, a, c) \
1029         bus_space_read_multi_1((t), (h), (o), (a), (c))
1030 #define bus_space_read_multi_stream_2(t, h, o, a, c) \
1031         bus_space_read_multi_2((t), (h), (o), (a), (c))
1032 #define bus_space_read_multi_stream_4(t, h, o, a, c) \
1033         bus_space_read_multi_4((t), (h), (o), (a), (c))
1034
1035 #define bus_space_write_stream_1(t, h, o, v) \
1036         bus_space_write_1((t), (h), (o), (v))
1037 #define bus_space_write_stream_2(t, h, o, v) \
1038         bus_space_write_2((t), (h), (o), (v))
1039 #define bus_space_write_stream_4(t, h, o, v) \
1040         bus_space_write_4((t), (h), (o), (v))
1041
1042 #define bus_space_write_multi_stream_1(t, h, o, a, c) \
1043         bus_space_write_multi_1((t), (h), (o), (a), (c))
1044 #define bus_space_write_multi_stream_2(t, h, o, a, c) \
1045         bus_space_write_multi_2((t), (h), (o), (a), (c))
1046 #define bus_space_write_multi_stream_4(t, h, o, a, c) \
1047         bus_space_write_multi_4((t), (h), (o), (a), (c))
1048
1049 #define bus_space_set_multi_stream_1(t, h, o, v, c) \
1050         bus_space_set_multi_1((t), (h), (o), (v), (c))
1051 #define bus_space_set_multi_stream_2(t, h, o, v, c) \
1052         bus_space_set_multi_2((t), (h), (o), (v), (c))
1053 #define bus_space_set_multi_stream_4(t, h, o, v, c) \
1054         bus_space_set_multi_4((t), (h), (o), (v), (c))
1055
1056 #define bus_space_read_region_stream_1(t, h, o, a, c) \
1057         bus_space_read_region_1((t), (h), (o), (a), (c))
1058 #define bus_space_read_region_stream_2(t, h, o, a, c) \
1059         bus_space_read_region_2((t), (h), (o), (a), (c))
1060 #define bus_space_read_region_stream_4(t, h, o, a, c) \
1061         bus_space_read_region_4((t), (h), (o), (a), (c))
1062
1063 #define bus_space_write_region_stream_1(t, h, o, a, c) \
1064         bus_space_write_region_1((t), (h), (o), (a), (c))
1065 #define bus_space_write_region_stream_2(t, h, o, a, c) \
1066         bus_space_write_region_2((t), (h), (o), (a), (c))
1067 #define bus_space_write_region_stream_4(t, h, o, a, c) \
1068         bus_space_write_region_4((t), (h), (o), (a), (c))
1069
1070 #define bus_space_set_region_stream_1(t, h, o, v, c) \
1071         bus_space_set_region_1((t), (h), (o), (v), (c))
1072 #define bus_space_set_region_stream_2(t, h, o, v, c) \
1073         bus_space_set_region_2((t), (h), (o), (v), (c))
1074 #define bus_space_set_region_stream_4(t, h, o, v, c) \
1075         bus_space_set_region_4((t), (h), (o), (v), (c))
1076
1077 #define bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \
1078         bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
1079 #define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \
1080         bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c))
1081 #define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \
1082         bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c))
1083
1084 #endif /* _AMD64_BUS_H_ */