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