rename amd64 architecture to x86_64
[dragonfly.git] / sys / cpu / x86_64 / include / bus_dma.h
1 /*-
2  * Copyright (c) 2005 Scott Long
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #ifndef _CPU_BUS_DMA_H_
28 #define _CPU_BUS_DMA_H_
29
30 #include <machine/cpufunc.h>
31
32 /*
33  * Bus address and size types
34  */
35
36 typedef uint64_t bus_addr_t;
37 typedef uint64_t bus_size_t;
38
39 typedef uint64_t bus_space_tag_t;
40 typedef uint64_t bus_space_handle_t;
41
42 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
43 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
44 #define BUS_SPACE_MAXSIZE       (64 * 1024) /* Maximum supported size */
45 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
46 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
47 #define BUS_SPACE_MAXADDR       BUS_SPACE_MAXADDR_32BIT
48
49 #define BUS_SPACE_UNRESTRICTED  (~0)
50
51 /*
52  * Values for the amd64 bus space tag, not to be used directly by MI code.
53  */
54 #define X86_64_BUS_SPACE_IO     0       /* space is i/o space */
55 #define X86_64_BUS_SPACE_MEM    1       /* space is mem space */
56
57 /*
58  * Map a region of device bus space into CPU virtual address space.
59  */
60
61 static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
62                                   bus_size_t size, int flags,
63                                   bus_space_handle_t *bshp);
64
65 static __inline int
66 bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
67               bus_size_t size __unused, int flags __unused,
68               bus_space_handle_t *bshp)
69 {
70
71         *bshp = addr;
72         return (0);
73 }
74
75 /*
76  * Unmap a region of device bus space.
77  */
78
79 static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
80                                      bus_size_t size);
81
82 static __inline void
83 bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
84                 bus_size_t size __unused)
85 {
86 }
87
88 /*
89  * Get a new handle for a subregion of an already-mapped area of bus space.
90  */
91
92 static __inline int bus_space_subregion(bus_space_tag_t t,
93                                         bus_space_handle_t bsh,
94                                         bus_size_t offset, bus_size_t size,
95                                         bus_space_handle_t *nbshp);
96
97 static __inline int
98 bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh,
99                     bus_size_t offset, bus_size_t size __unused,
100                     bus_space_handle_t *nbshp)
101 {
102
103         *nbshp = bsh + offset;
104         return (0);
105 }
106
107 static __inline void *
108 bus_space_kva(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t offset)
109 {
110         if (tag == X86_64_BUS_SPACE_IO)
111                 return ((void *)0);
112         return ((void *)(handle + offset));
113 }
114
115 /*
116  * Allocate a region of memory that is accessible to devices in bus space.
117  */
118
119 int     bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
120                         bus_addr_t rend, bus_size_t size, bus_size_t align,
121                         bus_size_t boundary, int flags, bus_addr_t *addrp,
122                         bus_space_handle_t *bshp);
123
124 /*
125  * Free a region of bus space accessible memory.
126  */
127
128 static __inline void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
129                                     bus_size_t size);
130
131 static __inline void
132 bus_space_free(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
133                bus_size_t size __unused)
134 {
135 }
136
137
138 /*
139  * Read a 1, 2, 4, or 8 byte quantity from bus space
140  * described by tag/handle/offset.
141  */
142 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
143                                           bus_space_handle_t handle,
144                                           bus_size_t offset);
145
146 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
147                                            bus_space_handle_t handle,
148                                            bus_size_t offset);
149
150 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
151                                            bus_space_handle_t handle,
152                                            bus_size_t offset);
153
154 static __inline u_int8_t
155 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
156                  bus_size_t offset)
157 {
158
159         if (tag == X86_64_BUS_SPACE_IO)
160                 return (inb(handle + offset));
161         return (*(volatile u_int8_t *)(handle + offset));
162 }
163
164 static __inline u_int16_t
165 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
166                  bus_size_t offset)
167 {
168
169         if (tag == X86_64_BUS_SPACE_IO)
170                 return (inw(handle + offset));
171         return (*(volatile u_int16_t *)(handle + offset));
172 }
173
174 static __inline u_int32_t
175 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
176                  bus_size_t offset)
177 {
178
179         if (tag == X86_64_BUS_SPACE_IO)
180                 return (inl(handle + offset));
181         return (*(volatile u_int32_t *)(handle + offset));
182 }
183
184 #if 0   /* Cause a link error for bus_space_read_8 */
185 #define bus_space_read_8(t, h, o)       !!! bus_space_read_8 unimplemented !!!
186 #endif
187
188 /*
189  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
190  * described by tag/handle/offset and copy into buffer provided.
191  */
192 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
193                                             bus_space_handle_t bsh,
194                                             bus_size_t offset, u_int8_t *addr,
195                                             size_t count);
196
197 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
198                                             bus_space_handle_t bsh,
199                                             bus_size_t offset, u_int16_t *addr,
200                                             size_t count);
201
202 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
203                                             bus_space_handle_t bsh,
204                                             bus_size_t offset, u_int32_t *addr,
205                                             size_t count);
206
207 static __inline void
208 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
209                        bus_size_t offset, u_int8_t *addr, size_t count)
210 {
211
212         if (tag == X86_64_BUS_SPACE_IO)
213                 insb(bsh + offset, addr, count);
214         else {
215                 __asm __volatile("                              \n\
216                         cld                                     \n\
217                 1:      movb (%2),%%al                          \n\
218                         stosb                                   \n\
219                         loop 1b"                                :
220                     "=D" (addr), "=c" (count)                   :
221                     "r" (bsh + offset), "0" (addr), "1" (count) :
222                     "%eax", "memory");
223         }
224 }
225
226 static __inline void
227 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
228                        bus_size_t offset, u_int16_t *addr, size_t count)
229 {
230
231         if (tag == X86_64_BUS_SPACE_IO)
232                 insw(bsh + offset, addr, count);
233         else {
234                 __asm __volatile("                              \n\
235                         cld                                     \n\
236                 1:      movw (%2),%%ax                          \n\
237                         stosw                                   \n\
238                         loop 1b"                                :
239                     "=D" (addr), "=c" (count)                   :
240                     "r" (bsh + offset), "0" (addr), "1" (count) :
241                     "%eax", "memory");
242         }
243 }
244
245 static __inline void
246 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
247                        bus_size_t offset, u_int32_t *addr, size_t count)
248 {
249
250         if (tag == X86_64_BUS_SPACE_IO)
251                 insl(bsh + offset, addr, count);
252         else {
253                 __asm __volatile("                              \n\
254                         cld                                     \n\
255                 1:      movl (%2),%%eax                         \n\
256                         stosl                                   \n\
257                         loop 1b"                                :
258                     "=D" (addr), "=c" (count)                   :
259                     "r" (bsh + offset), "0" (addr), "1" (count) :
260                     "%eax", "memory");
261         }
262 }
263
264 #if 0   /* Cause a link error for bus_space_read_multi_8 */
265 #define bus_space_read_multi_8  !!! bus_space_read_multi_8 unimplemented !!!
266 #endif
267
268 /*
269  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
270  * described by tag/handle and starting at `offset' and copy into
271  * buffer provided.
272  */
273 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
274                                              bus_space_handle_t bsh,
275                                              bus_size_t offset, u_int8_t *addr,
276                                              size_t count);
277
278 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
279                                              bus_space_handle_t bsh,
280                                              bus_size_t offset, u_int16_t *addr,
281                                              size_t count);
282
283 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
284                                              bus_space_handle_t bsh,
285                                              bus_size_t offset, u_int32_t *addr,
286                                              size_t count);
287
288
289 static __inline void
290 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
291                         bus_size_t offset, u_int8_t *addr, size_t count)
292 {
293
294         if (tag == X86_64_BUS_SPACE_IO) {
295                 int _port_ = bsh + offset;
296                 __asm __volatile("                              \n\
297                         cld                                     \n\
298                 1:      inb %w2,%%al                            \n\
299                         stosb                                   \n\
300                         incl %2                                 \n\
301                         loop 1b"                                :
302                     "=D" (addr), "=c" (count), "=d" (_port_)    :
303                     "0" (addr), "1" (count), "2" (_port_)       :
304                     "%eax", "memory", "cc");
305         } else {
306                 bus_space_handle_t _port_ = bsh + offset;
307                 __asm __volatile("                              \n\
308                         cld                                     \n\
309                         repne                                   \n\
310                         movsb"                                  :
311                     "=D" (addr), "=c" (count), "=S" (_port_)    :
312                     "0" (addr), "1" (count), "2" (_port_)       :
313                     "memory", "cc");
314         }
315 }
316
317 static __inline void
318 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
319                         bus_size_t offset, u_int16_t *addr, size_t count)
320 {
321
322         if (tag == X86_64_BUS_SPACE_IO) {
323                 int _port_ = bsh + offset;
324                 __asm __volatile("                              \n\
325                         cld                                     \n\
326                 1:      inw %w2,%%ax                            \n\
327                         stosw                                   \n\
328                         addl $2,%2                              \n\
329                         loop 1b"                                :
330                     "=D" (addr), "=c" (count), "=d" (_port_)    :
331                     "0" (addr), "1" (count), "2" (_port_)       :
332                     "%eax", "memory", "cc");
333         } else {
334                 bus_space_handle_t _port_ = bsh + offset;
335                 __asm __volatile("                              \n\
336                         cld                                     \n\
337                         repne                                   \n\
338                         movsw"                                  :
339                     "=D" (addr), "=c" (count), "=S" (_port_)    :
340                     "0" (addr), "1" (count), "2" (_port_)       :
341                     "memory", "cc");
342         }
343 }
344
345 static __inline void
346 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
347                         bus_size_t offset, u_int32_t *addr, size_t count)
348 {
349
350         if (tag == X86_64_BUS_SPACE_IO) {
351                 int _port_ = bsh + offset;
352                 __asm __volatile("                              \n\
353                         cld                                     \n\
354                 1:      inl %w2,%%eax                           \n\
355                         stosl                                   \n\
356                         addl $4,%2                              \n\
357                         loop 1b"                                :
358                     "=D" (addr), "=c" (count), "=d" (_port_)    :
359                     "0" (addr), "1" (count), "2" (_port_)       :
360                     "%eax", "memory", "cc");
361         } else {
362                 bus_space_handle_t _port_ = bsh + offset;
363                 __asm __volatile("                              \n\
364                         cld                                     \n\
365                         repne                                   \n\
366                         movsl"                                  :
367                     "=D" (addr), "=c" (count), "=S" (_port_)    :
368                     "0" (addr), "1" (count), "2" (_port_)       :
369                     "memory", "cc");
370         }
371 }
372
373 #if 0   /* Cause a link error for bus_space_read_region_8 */
374 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
375 #endif
376
377 /*
378  * Write the 1, 2, 4, or 8 byte value `value' to bus space
379  * described by tag/handle/offset.
380  */
381
382 static __inline void bus_space_write_1(bus_space_tag_t tag,
383                                        bus_space_handle_t bsh,
384                                        bus_size_t offset, u_int8_t value);
385
386 static __inline void bus_space_write_2(bus_space_tag_t tag,
387                                        bus_space_handle_t bsh,
388                                        bus_size_t offset, u_int16_t value);
389
390 static __inline void bus_space_write_4(bus_space_tag_t tag,
391                                        bus_space_handle_t bsh,
392                                        bus_size_t offset, u_int32_t value);
393
394 static __inline void
395 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
396                        bus_size_t offset, u_int8_t value)
397 {
398
399         if (tag == X86_64_BUS_SPACE_IO)
400                 outb(bsh + offset, value);
401         else
402                 *(volatile u_int8_t *)(bsh + offset) = value;
403 }
404
405 static __inline void
406 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
407                        bus_size_t offset, u_int16_t value)
408 {
409
410         if (tag == X86_64_BUS_SPACE_IO)
411                 outw(bsh + offset, value);
412         else
413                 *(volatile u_int16_t *)(bsh + offset) = value;
414 }
415
416 static __inline void
417 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
418                        bus_size_t offset, u_int32_t value)
419 {
420
421         if (tag == X86_64_BUS_SPACE_IO)
422                 outl(bsh + offset, value);
423         else
424                 *(volatile u_int32_t *)(bsh + offset) = value;
425 }
426
427 #if 0   /* Cause a link error for bus_space_write_8 */
428 #define bus_space_write_8       !!! bus_space_write_8 not implemented !!!
429 #endif
430
431 /*
432  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
433  * provided to bus space described by tag/handle/offset.
434  */
435
436 static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
437                                              bus_space_handle_t bsh,
438                                              bus_size_t offset,
439                                              const u_int8_t *addr,
440                                              size_t count);
441 static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
442                                              bus_space_handle_t bsh,
443                                              bus_size_t offset,
444                                              const u_int16_t *addr,
445                                              size_t count);
446
447 static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
448                                              bus_space_handle_t bsh,
449                                              bus_size_t offset,
450                                              const u_int32_t *addr,
451                                              size_t count);
452
453 static __inline void
454 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
455                         bus_size_t offset, const u_int8_t *addr, size_t count)
456 {
457
458         if (tag == X86_64_BUS_SPACE_IO)
459                 outsb(bsh + offset, addr, count);
460         else {
461                 __asm __volatile("                              \n\
462                         cld                                     \n\
463                 1:      lodsb                                   \n\
464                         movb %%al,(%2)                          \n\
465                         loop 1b"                                :
466                     "=S" (addr), "=c" (count)                   :
467                     "r" (bsh + offset), "0" (addr), "1" (count) :
468                     "%eax", "memory", "cc");
469         }
470 }
471
472 static __inline void
473 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
474                         bus_size_t offset, const u_int16_t *addr, size_t count)
475 {
476
477         if (tag == X86_64_BUS_SPACE_IO)
478                 outsw(bsh + offset, addr, count);
479         else {
480                 __asm __volatile("                              \n\
481                         cld                                     \n\
482                 1:      lodsw                                   \n\
483                         movw %%ax,(%2)                          \n\
484                         loop 1b"                                :
485                     "=S" (addr), "=c" (count)                   :
486                     "r" (bsh + offset), "0" (addr), "1" (count) :
487                     "%eax", "memory", "cc");
488         }
489 }
490
491 static __inline void
492 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
493                         bus_size_t offset, const u_int32_t *addr, size_t count)
494 {
495
496         if (tag == X86_64_BUS_SPACE_IO)
497                 outsl(bsh + offset, addr, count);
498         else {
499                 __asm __volatile("                              \n\
500                         cld                                     \n\
501                 1:      lodsl                                   \n\
502                         movl %%eax,(%2)                         \n\
503                         loop 1b"                                :
504                     "=S" (addr), "=c" (count)                   :
505                     "r" (bsh + offset), "0" (addr), "1" (count) :
506                     "%eax", "memory", "cc");
507         }
508 }
509
510 #if 0   /* Cause a link error for bus_space_write_multi_8 */
511 #define bus_space_write_multi_8(t, h, o, a, c)                          \
512                         !!! bus_space_write_multi_8 unimplemented !!!
513 #endif
514
515 /*
516  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
517  * to bus space described by tag/handle starting at `offset'.
518  */
519
520 static __inline void bus_space_write_region_1(bus_space_tag_t tag,
521                                               bus_space_handle_t bsh,
522                                               bus_size_t offset,
523                                               const u_int8_t *addr,
524                                               size_t count);
525 static __inline void bus_space_write_region_2(bus_space_tag_t tag,
526                                               bus_space_handle_t bsh,
527                                               bus_size_t offset,
528                                               const u_int16_t *addr,
529                                               size_t count);
530 static __inline void bus_space_write_region_4(bus_space_tag_t tag,
531                                               bus_space_handle_t bsh,
532                                               bus_size_t offset,
533                                               const u_int32_t *addr,
534                                               size_t count);
535
536 static __inline void
537 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
538                          bus_size_t offset, const u_int8_t *addr, size_t count)
539 {
540
541         if (tag == X86_64_BUS_SPACE_IO) {
542                 int _port_ = bsh + offset;
543                 __asm __volatile("                              \n\
544                         cld                                     \n\
545                 1:      lodsb                                   \n\
546                         outb %%al,%w0                           \n\
547                         incl %0                                 \n\
548                         loop 1b"                                :
549                     "=d" (_port_), "=S" (addr), "=c" (count)    :
550                     "0" (_port_), "1" (addr), "2" (count)       :
551                     "%eax", "memory", "cc");
552         } else {
553                 bus_space_handle_t _port_ = bsh + offset;
554                 __asm __volatile("                              \n\
555                         cld                                     \n\
556                         repne                                   \n\
557                         movsb"                                  :
558                     "=D" (_port_), "=S" (addr), "=c" (count)    :
559                     "0" (_port_), "1" (addr), "2" (count)       :
560                     "memory", "cc");
561         }
562 }
563
564 static __inline void
565 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
566                          bus_size_t offset, const u_int16_t *addr, size_t count)
567 {
568
569         if (tag == X86_64_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                 bus_space_handle_t _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
597         if (tag == X86_64_BUS_SPACE_IO) {
598                 int _port_ = bsh + offset;
599                 __asm __volatile("                              \n\
600                         cld                                     \n\
601                 1:      lodsl                                   \n\
602                         outl %%eax,%w0                          \n\
603                         addl $4,%0                              \n\
604                         loop 1b"                                :
605                     "=d" (_port_), "=S" (addr), "=c" (count)    :
606                     "0" (_port_), "1" (addr), "2" (count)       :
607                     "%eax", "memory", "cc");
608         } else {
609                 bus_space_handle_t _port_ = bsh + offset;
610                 __asm __volatile("                              \n\
611                         cld                                     \n\
612                         repne                                   \n\
613                         movsl"                                  :
614                     "=D" (_port_), "=S" (addr), "=c" (count)    :
615                     "0" (_port_), "1" (addr), "2" (count)       :
616                     "memory", "cc");
617         }
618 }
619
620 #if 0   /* Cause a link error for bus_space_write_region_8 */
621 #define bus_space_write_region_8                                        \
622                         !!! bus_space_write_region_8 unimplemented !!!
623 #endif
624
625 /*
626  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
627  * by tag/handle/offset `count' times.
628  */
629
630 static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
631                                            bus_space_handle_t bsh,
632                                            bus_size_t offset,
633                                            u_int8_t value, size_t count);
634 static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
635                                            bus_space_handle_t bsh,
636                                            bus_size_t offset,
637                                            u_int16_t value, size_t count);
638 static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
639                                            bus_space_handle_t bsh,
640                                            bus_size_t offset,
641                                            u_int32_t value, size_t count);
642
643 static __inline void
644 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
645                       bus_size_t offset, u_int8_t value, size_t count)
646 {
647         bus_space_handle_t addr = bsh + offset;
648
649         if (tag == X86_64_BUS_SPACE_IO)
650                 while (count--)
651                         outb(addr, value);
652         else
653                 while (count--)
654                         *(volatile u_int8_t *)(addr) = value;
655 }
656
657 static __inline void
658 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
659                      bus_size_t offset, u_int16_t value, size_t count)
660 {
661         bus_space_handle_t addr = bsh + offset;
662
663         if (tag == X86_64_BUS_SPACE_IO)
664                 while (count--)
665                         outw(addr, value);
666         else
667                 while (count--)
668                         *(volatile u_int16_t *)(addr) = value;
669 }
670
671 static __inline void
672 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
673                       bus_size_t offset, u_int32_t value, size_t count)
674 {
675         bus_space_handle_t addr = bsh + offset;
676
677         if (tag == X86_64_BUS_SPACE_IO)
678                 while (count--)
679                         outl(addr, value);
680         else
681                 while (count--)
682                         *(volatile u_int32_t *)(addr) = value;
683 }
684
685 #if 0   /* Cause a link error for bus_space_set_multi_8 */
686 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
687 #endif
688
689 /*
690  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
691  * by tag/handle starting at `offset'.
692  */
693
694 static __inline void bus_space_set_region_1(bus_space_tag_t tag,
695                                             bus_space_handle_t bsh,
696                                             bus_size_t offset, u_int8_t value,
697                                             size_t count);
698 static __inline void bus_space_set_region_2(bus_space_tag_t tag,
699                                             bus_space_handle_t bsh,
700                                             bus_size_t offset, u_int16_t value,
701                                             size_t count);
702 static __inline void bus_space_set_region_4(bus_space_tag_t tag,
703                                             bus_space_handle_t bsh,
704                                             bus_size_t offset, u_int32_t value,
705                                             size_t count);
706
707 static __inline void
708 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
709                        bus_size_t offset, u_int8_t value, size_t count)
710 {
711         bus_space_handle_t addr = bsh + offset;
712
713         if (tag == X86_64_BUS_SPACE_IO)
714                 for (; count != 0; count--, addr++)
715                         outb(addr, value);
716         else
717                 for (; count != 0; count--, addr++)
718                         *(volatile u_int8_t *)(addr) = value;
719 }
720
721 static __inline void
722 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
723                        bus_size_t offset, u_int16_t value, size_t count)
724 {
725         bus_space_handle_t addr = bsh + offset;
726
727         if (tag == X86_64_BUS_SPACE_IO)
728                 for (; count != 0; count--, addr += 2)
729                         outw(addr, value);
730         else
731                 for (; count != 0; count--, addr += 2)
732                         *(volatile u_int16_t *)(addr) = value;
733 }
734
735 static __inline void
736 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
737                        bus_size_t offset, u_int32_t value, size_t count)
738 {
739         bus_space_handle_t addr = bsh + offset;
740
741         if (tag == X86_64_BUS_SPACE_IO)
742                 for (; count != 0; count--, addr += 4)
743                         outl(addr, value);
744         else
745                 for (; count != 0; count--, addr += 4)
746                         *(volatile u_int32_t *)(addr) = value;
747 }
748
749 #if 0   /* Cause a link error for bus_space_set_region_8 */
750 #define bus_space_set_region_8  !!! bus_space_set_region_8 unimplemented !!!
751 #endif
752
753 /*
754  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
755  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
756  */
757
758 static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
759                                              bus_space_handle_t bsh1,
760                                              bus_size_t off1,
761                                              bus_space_handle_t bsh2,
762                                              bus_size_t off2, size_t count);
763
764 static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
765                                              bus_space_handle_t bsh1,
766                                              bus_size_t off1,
767                                              bus_space_handle_t bsh2,
768                                              bus_size_t off2, size_t count);
769
770 static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
771                                              bus_space_handle_t bsh1,
772                                              bus_size_t off1,
773                                              bus_space_handle_t bsh2,
774                                              bus_size_t off2, size_t count);
775
776 static __inline void
777 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
778                         bus_size_t off1, bus_space_handle_t bsh2,
779                         bus_size_t off2, size_t count)
780 {
781         bus_space_handle_t addr1 = bsh1 + off1;
782         bus_space_handle_t addr2 = bsh2 + off2;
783
784         if (tag == X86_64_BUS_SPACE_IO) {
785                 if (addr1 >= addr2) {
786                         /* src after dest: copy forward */
787                         for (; count != 0; count--, addr1++, addr2++)
788                                 outb(addr2, inb(addr1));
789                 } else {
790                         /* dest after src: copy backwards */
791                         for (addr1 += (count - 1), addr2 += (count - 1);
792                             count != 0; count--, addr1--, addr2--)
793                                 outb(addr2, inb(addr1));
794                 }
795         } else {
796                 if (addr1 >= addr2) {
797                         /* src after dest: copy forward */
798                         for (; count != 0; count--, addr1++, addr2++)
799                                 *(volatile u_int8_t *)(addr2) =
800                                     *(volatile u_int8_t *)(addr1);
801                 } else {
802                         /* dest after src: copy backwards */
803                         for (addr1 += (count - 1), addr2 += (count - 1);
804                             count != 0; count--, addr1--, addr2--)
805                                 *(volatile u_int8_t *)(addr2) =
806                                     *(volatile u_int8_t *)(addr1);
807                 }
808         }
809 }
810
811 static __inline void
812 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
813                         bus_size_t off1, bus_space_handle_t bsh2,
814                         bus_size_t off2, size_t count)
815 {
816         bus_space_handle_t addr1 = bsh1 + off1;
817         bus_space_handle_t addr2 = bsh2 + off2;
818
819         if (tag == X86_64_BUS_SPACE_IO) {
820                 if (addr1 >= addr2) {
821                         /* src after dest: copy forward */
822                         for (; count != 0; count--, addr1 += 2, addr2 += 2)
823                                 outw(addr2, inw(addr1));
824                 } else {
825                         /* dest after src: copy backwards */
826                         for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
827                             count != 0; count--, addr1 -= 2, addr2 -= 2)
828                                 outw(addr2, inw(addr1));
829                 }
830         } else {
831                 if (addr1 >= addr2) {
832                         /* src after dest: copy forward */
833                         for (; count != 0; count--, addr1 += 2, addr2 += 2)
834                                 *(volatile u_int16_t *)(addr2) =
835                                     *(volatile u_int16_t *)(addr1);
836                 } else {
837                         /* dest after src: copy backwards */
838                         for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
839                             count != 0; count--, addr1 -= 2, addr2 -= 2)
840                                 *(volatile u_int16_t *)(addr2) =
841                                     *(volatile u_int16_t *)(addr1);
842                 }
843         }
844 }
845
846 static __inline void
847 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
848                         bus_size_t off1, bus_space_handle_t bsh2,
849                         bus_size_t off2, size_t count)
850 {
851         bus_space_handle_t addr1 = bsh1 + off1;
852         bus_space_handle_t addr2 = bsh2 + off2;
853
854         if (tag == X86_64_BUS_SPACE_IO) {
855                 if (addr1 >= addr2) {
856                         /* src after dest: copy forward */
857                         for (; count != 0; count--, addr1 += 4, addr2 += 4)
858                                 outl(addr2, inl(addr1));
859                 } else {
860                         /* dest after src: copy backwards */
861                         for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
862                             count != 0; count--, addr1 -= 4, addr2 -= 4)
863                                 outl(addr2, inl(addr1));
864                 }
865         } else {
866                 if (addr1 >= addr2) {
867                         /* src after dest: copy forward */
868                         for (; count != 0; count--, addr1 += 4, addr2 += 4)
869                                 *(volatile u_int32_t *)(addr2) =
870                                     *(volatile u_int32_t *)(addr1);
871                 } else {
872                         /* dest after src: copy backwards */
873                         for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
874                             count != 0; count--, addr1 -= 4, addr2 -= 4)
875                                 *(volatile u_int32_t *)(addr2) =
876                                     *(volatile u_int32_t *)(addr1);
877                 }
878         }
879 }
880
881 #if 0   /* Cause a link error for bus_space_copy_8 */
882 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!!
883 #endif
884
885 /*
886  * Bus read/write barrier methods.
887  *
888  *      void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
889  *                             bus_size_t offset, bus_size_t len, int flags);
890  *
891  *
892  * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
893  * prevent reordering by the compiler; all Intel x86 processors currently
894  * retire operations outside the CPU in program order.
895  */
896 #define BUS_SPACE_BARRIER_READ  0x01            /* force read barrier */
897 #define BUS_SPACE_BARRIER_WRITE 0x02            /* force write barrier */
898
899 static __inline void
900 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
901                   bus_size_t offset __unused, bus_size_t len __unused, int flags)
902 {
903         if (flags & BUS_SPACE_BARRIER_READ)
904                 __asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory");
905         else
906                 __asm __volatile("" : : : "memory");
907 }
908
909 /*
910  * Stream accesses are the same as normal accesses on amd64; there are no
911  * supported bus systems with an endianess different from the host one.
912  */
913 #define bus_space_read_stream_1(t, h, o)        bus_space_read_1((t), (h), (o))
914 #define bus_space_read_stream_2(t, h, o)        bus_space_read_2((t), (h), (o))
915 #define bus_space_read_stream_4(t, h, o)        bus_space_read_4((t), (h), (o))
916
917 #define bus_space_read_multi_stream_1(t, h, o, a, c) \
918         bus_space_read_multi_1((t), (h), (o), (a), (c))
919 #define bus_space_read_multi_stream_2(t, h, o, a, c) \
920         bus_space_read_multi_2((t), (h), (o), (a), (c))
921 #define bus_space_read_multi_stream_4(t, h, o, a, c) \
922         bus_space_read_multi_4((t), (h), (o), (a), (c))
923
924 #define bus_space_write_stream_1(t, h, o, v) \
925         bus_space_write_1((t), (h), (o), (v))
926 #define bus_space_write_stream_2(t, h, o, v) \
927         bus_space_write_2((t), (h), (o), (v))
928 #define bus_space_write_stream_4(t, h, o, v) \
929         bus_space_write_4((t), (h), (o), (v))
930
931 #define bus_space_write_multi_stream_1(t, h, o, a, c) \
932         bus_space_write_multi_1((t), (h), (o), (a), (c))
933 #define bus_space_write_multi_stream_2(t, h, o, a, c) \
934         bus_space_write_multi_2((t), (h), (o), (a), (c))
935 #define bus_space_write_multi_stream_4(t, h, o, a, c) \
936         bus_space_write_multi_4((t), (h), (o), (a), (c))
937
938 #define bus_space_set_multi_stream_1(t, h, o, v, c) \
939         bus_space_set_multi_1((t), (h), (o), (v), (c))
940 #define bus_space_set_multi_stream_2(t, h, o, v, c) \
941         bus_space_set_multi_2((t), (h), (o), (v), (c))
942 #define bus_space_set_multi_stream_4(t, h, o, v, c) \
943         bus_space_set_multi_4((t), (h), (o), (v), (c))
944
945 #define bus_space_read_region_stream_1(t, h, o, a, c) \
946         bus_space_read_region_1((t), (h), (o), (a), (c))
947 #define bus_space_read_region_stream_2(t, h, o, a, c) \
948         bus_space_read_region_2((t), (h), (o), (a), (c))
949 #define bus_space_read_region_stream_4(t, h, o, a, c) \
950         bus_space_read_region_4((t), (h), (o), (a), (c))
951
952 #define bus_space_write_region_stream_1(t, h, o, a, c) \
953         bus_space_write_region_1((t), (h), (o), (a), (c))
954 #define bus_space_write_region_stream_2(t, h, o, a, c) \
955         bus_space_write_region_2((t), (h), (o), (a), (c))
956 #define bus_space_write_region_stream_4(t, h, o, a, c) \
957         bus_space_write_region_4((t), (h), (o), (a), (c))
958
959 #define bus_space_set_region_stream_1(t, h, o, v, c) \
960         bus_space_set_region_1((t), (h), (o), (v), (c))
961 #define bus_space_set_region_stream_2(t, h, o, v, c) \
962         bus_space_set_region_2((t), (h), (o), (v), (c))
963 #define bus_space_set_region_stream_4(t, h, o, v, c) \
964         bus_space_set_region_4((t), (h), (o), (v), (c))
965
966 #define bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \
967         bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
968 #define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \
969         bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c))
970 #define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \
971         bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c))
972
973 #endif /* _CPU_BUS_DMA_H_ */