rename amd64 architecture to x86_64
[dragonfly.git] / sys / cpu / x86_64 / include / bus_dma.h
CommitLineData
d7f50089
YY
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.
d7f50089
YY
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
36typedef uint64_t bus_addr_t;
37typedef uint64_t bus_size_t;
38
39typedef uint64_t bus_space_tag_t;
40typedef 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 */
c1543a89
SS
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 */
d7f50089
YY
56
57/*
58 * Map a region of device bus space into CPU virtual address space.
59 */
60
61static __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
65static __inline int
66bus_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
79static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
80 bus_size_t size);
81
82static __inline void
83bus_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
92static __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
97static __inline int
98bus_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
6a518ee6
MD
107static __inline void *
108bus_space_kva(bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t offset)
109{
c1543a89 110 if (tag == X86_64_BUS_SPACE_IO)
03c663bc 111 return ((void *)0);
6a518ee6
MD
112 return ((void *)(handle + offset));
113}
114
d7f50089
YY
115/*
116 * Allocate a region of memory that is accessible to devices in bus space.
117 */
118
119int 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
128static __inline void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
129 bus_size_t size);
130
131static __inline void
132bus_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 */
142static __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
146static __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
150static __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
154static __inline u_int8_t
155bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
156 bus_size_t offset)
157{
158
c1543a89 159 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
160 return (inb(handle + offset));
161 return (*(volatile u_int8_t *)(handle + offset));
162}
163
164static __inline u_int16_t
165bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
166 bus_size_t offset)
167{
168
c1543a89 169 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
170 return (inw(handle + offset));
171 return (*(volatile u_int16_t *)(handle + offset));
172}
173
174static __inline u_int32_t
175bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
176 bus_size_t offset)
177{
178
c1543a89 179 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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 */
192static __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
197static __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
202static __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
207static __inline void
208bus_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
c1543a89 212 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
226static __inline void
227bus_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
c1543a89 231 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
245static __inline void
246bus_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
c1543a89 250 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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 */
273static __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
278static __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
283static __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
289static __inline void
290bus_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
c1543a89 294 if (tag == X86_64_BUS_SPACE_IO) {
d7f50089
YY
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
317static __inline void
318bus_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
c1543a89 322 if (tag == X86_64_BUS_SPACE_IO) {
d7f50089
YY
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
345static __inline void
346bus_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
c1543a89 350 if (tag == X86_64_BUS_SPACE_IO) {
d7f50089
YY
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
382static __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
386static __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
390static __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
394static __inline void
395bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
396 bus_size_t offset, u_int8_t value)
397{
398
c1543a89 399 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
400 outb(bsh + offset, value);
401 else
402 *(volatile u_int8_t *)(bsh + offset) = value;
403}
404
405static __inline void
406bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
407 bus_size_t offset, u_int16_t value)
408{
409
c1543a89 410 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
411 outw(bsh + offset, value);
412 else
413 *(volatile u_int16_t *)(bsh + offset) = value;
414}
415
416static __inline void
417bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
418 bus_size_t offset, u_int32_t value)
419{
420
c1543a89 421 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
436static __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);
441static __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
447static __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
453static __inline void
454bus_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
c1543a89 458 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
472static __inline void
473bus_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
c1543a89 477 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
491static __inline void
492bus_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
c1543a89 496 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
520static __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);
525static __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);
530static __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
536static __inline void
537bus_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
c1543a89 541 if (tag == X86_64_BUS_SPACE_IO) {
d7f50089
YY
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
564static __inline void
565bus_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
c1543a89 569 if (tag == X86_64_BUS_SPACE_IO) {
d7f50089
YY
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
592static __inline void
593bus_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
c1543a89 597 if (tag == X86_64_BUS_SPACE_IO) {
d7f50089
YY
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
630static __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);
634static __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);
638static __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
643static __inline void
644bus_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
c1543a89 649 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
650 while (count--)
651 outb(addr, value);
652 else
653 while (count--)
654 *(volatile u_int8_t *)(addr) = value;
655}
656
657static __inline void
658bus_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
c1543a89 663 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
664 while (count--)
665 outw(addr, value);
666 else
667 while (count--)
668 *(volatile u_int16_t *)(addr) = value;
669}
670
671static __inline void
672bus_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
c1543a89 677 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
694static __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);
698static __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);
702static __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
707static __inline void
708bus_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
c1543a89 713 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
721static __inline void
722bus_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
c1543a89 727 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
735static __inline void
736bus_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
c1543a89 741 if (tag == X86_64_BUS_SPACE_IO)
d7f50089
YY
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
758static __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
764static __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
770static __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
776static __inline void
777bus_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
c1543a89 784 if (tag == X86_64_BUS_SPACE_IO) {
d7f50089
YY
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
811static __inline void
812bus_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
c1543a89 819 if (tag == X86_64_BUS_SPACE_IO) {
d7f50089
YY
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
846static __inline void
847bus_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
c1543a89 854 if (tag == X86_64_BUS_SPACE_IO) {
d7f50089
YY
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
899static __inline void
900bus_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_ */