xref: /dragonfly/sys/cpu/x86_64/include/bus_dma.h (revision 277350a0)
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 0xFFFFFFUL
43 #define BUS_SPACE_MAXSIZE_32BIT	0xFFFFFFFFUL
44 #define BUS_SPACE_MAXSIZE	(64 * 1024) /* Maximum supported size */
45 #define BUS_SPACE_MAXADDR_24BIT	0xFFFFFFUL
46 #define BUS_SPACE_MAXADDR_32BIT	0xFFFFFFFFUL
47 #define BUS_SPACE_MAXADDR	0xFFFFFFFFFFFFFFFFUL
48 
49 #define BUS_SPACE_UNRESTRICTED	(~0)	/* nsegments */
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 #ifdef _KERNEL
185 static __inline u_int64_t
186 bus_space_read_8(bus_space_tag_t tag, bus_space_handle_t handle,
187 		 bus_size_t offset)
188 {
189 	if (tag == X86_64_BUS_SPACE_IO)
190 		panic("bus_space_read_8: illegal on I/O space");
191 	return (*(volatile u_int64_t *)(handle + offset));
192 }
193 #endif
194 
195 /*
196  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
197  * described by tag/handle/offset and copy into buffer provided.
198  */
199 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
200 					    bus_space_handle_t bsh,
201 					    bus_size_t offset, u_int8_t *addr,
202 					    size_t count);
203 
204 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
205 					    bus_space_handle_t bsh,
206 					    bus_size_t offset, u_int16_t *addr,
207 					    size_t count);
208 
209 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
210 					    bus_space_handle_t bsh,
211 					    bus_size_t offset, u_int32_t *addr,
212 					    size_t count);
213 
214 static __inline void
215 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
216 		       bus_size_t offset, u_int8_t *addr, size_t count)
217 {
218 
219 	if (tag == X86_64_BUS_SPACE_IO)
220 		insb(bsh + offset, addr, count);
221 	else {
222 		__asm __volatile("				\n\
223 			cld					\n\
224 		1:	movb (%2),%%al				\n\
225 			stosb					\n\
226 			loop 1b"				:
227 		    "=D" (addr), "=c" (count)			:
228 		    "r" (bsh + offset), "0" (addr), "1" (count)	:
229 		    "%eax", "memory");
230 	}
231 }
232 
233 static __inline void
234 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
235 		       bus_size_t offset, u_int16_t *addr, size_t count)
236 {
237 
238 	if (tag == X86_64_BUS_SPACE_IO)
239 		insw(bsh + offset, addr, count);
240 	else {
241 		__asm __volatile("				\n\
242 			cld					\n\
243 		1:	movw (%2),%%ax				\n\
244 			stosw					\n\
245 			loop 1b"				:
246 		    "=D" (addr), "=c" (count)			:
247 		    "r" (bsh + offset), "0" (addr), "1" (count)	:
248 		    "%eax", "memory");
249 	}
250 }
251 
252 static __inline void
253 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
254 		       bus_size_t offset, u_int32_t *addr, size_t count)
255 {
256 
257 	if (tag == X86_64_BUS_SPACE_IO)
258 		insl(bsh + offset, addr, count);
259 	else {
260 		__asm __volatile("				\n\
261 			cld					\n\
262 		1:	movl (%2),%%eax				\n\
263 			stosl					\n\
264 			loop 1b"				:
265 		    "=D" (addr), "=c" (count)			:
266 		    "r" (bsh + offset), "0" (addr), "1" (count)	:
267 		    "%eax", "memory");
268 	}
269 }
270 
271 #if 0	/* Cause a link error for bus_space_read_multi_8 */
272 #define	bus_space_read_multi_8	!!! bus_space_read_multi_8 unimplemented !!!
273 #endif
274 
275 /*
276  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
277  * described by tag/handle and starting at `offset' and copy into
278  * buffer provided.
279  */
280 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
281 					     bus_space_handle_t bsh,
282 					     bus_size_t offset, u_int8_t *addr,
283 					     size_t count);
284 
285 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
286 					     bus_space_handle_t bsh,
287 					     bus_size_t offset, u_int16_t *addr,
288 					     size_t count);
289 
290 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
291 					     bus_space_handle_t bsh,
292 					     bus_size_t offset, u_int32_t *addr,
293 					     size_t count);
294 
295 
296 static __inline void
297 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
298 			bus_size_t offset, u_int8_t *addr, size_t count)
299 {
300 
301 	if (tag == X86_64_BUS_SPACE_IO) {
302 		int _port_ = bsh + offset;
303 		__asm __volatile("				\n\
304 			cld					\n\
305 		1:	inb %w2,%%al				\n\
306 			stosb					\n\
307 			incl %2					\n\
308 			loop 1b"				:
309 		    "=D" (addr), "=c" (count), "=d" (_port_)	:
310 		    "0" (addr), "1" (count), "2" (_port_)	:
311 		    "%eax", "memory", "cc");
312 	} else {
313 		bus_space_handle_t _port_ = bsh + offset;
314 		__asm __volatile("				\n\
315 			cld					\n\
316 			repne					\n\
317 			movsb"					:
318 		    "=D" (addr), "=c" (count), "=S" (_port_)	:
319 		    "0" (addr), "1" (count), "2" (_port_)	:
320 		    "memory", "cc");
321 	}
322 }
323 
324 static __inline void
325 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
326 			bus_size_t offset, u_int16_t *addr, size_t count)
327 {
328 
329 	if (tag == X86_64_BUS_SPACE_IO) {
330 		int _port_ = bsh + offset;
331 		__asm __volatile("				\n\
332 			cld					\n\
333 		1:	inw %w2,%%ax				\n\
334 			stosw					\n\
335 			addl $2,%2				\n\
336 			loop 1b"				:
337 		    "=D" (addr), "=c" (count), "=d" (_port_)	:
338 		    "0" (addr), "1" (count), "2" (_port_)	:
339 		    "%eax", "memory", "cc");
340 	} else {
341 		bus_space_handle_t _port_ = bsh + offset;
342 		__asm __volatile("				\n\
343 			cld					\n\
344 			repne					\n\
345 			movsw"					:
346 		    "=D" (addr), "=c" (count), "=S" (_port_)	:
347 		    "0" (addr), "1" (count), "2" (_port_)	:
348 		    "memory", "cc");
349 	}
350 }
351 
352 static __inline void
353 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
354 			bus_size_t offset, u_int32_t *addr, size_t count)
355 {
356 
357 	if (tag == X86_64_BUS_SPACE_IO) {
358 		int _port_ = bsh + offset;
359 		__asm __volatile("				\n\
360 			cld					\n\
361 		1:	inl %w2,%%eax				\n\
362 			stosl					\n\
363 			addl $4,%2				\n\
364 			loop 1b"				:
365 		    "=D" (addr), "=c" (count), "=d" (_port_)	:
366 		    "0" (addr), "1" (count), "2" (_port_)	:
367 		    "%eax", "memory", "cc");
368 	} else {
369 		bus_space_handle_t _port_ = bsh + offset;
370 		__asm __volatile("				\n\
371 			cld					\n\
372 			repne					\n\
373 			movsl"					:
374 		    "=D" (addr), "=c" (count), "=S" (_port_)	:
375 		    "0" (addr), "1" (count), "2" (_port_)	:
376 		    "memory", "cc");
377 	}
378 }
379 
380 #if 0	/* Cause a link error for bus_space_read_region_8 */
381 #define	bus_space_read_region_8	!!! bus_space_read_region_8 unimplemented !!!
382 #endif
383 
384 /*
385  * Write the 1, 2, 4, or 8 byte value `value' to bus space
386  * described by tag/handle/offset.
387  */
388 
389 static __inline void bus_space_write_1(bus_space_tag_t tag,
390 				       bus_space_handle_t bsh,
391 				       bus_size_t offset, u_int8_t value);
392 
393 static __inline void bus_space_write_2(bus_space_tag_t tag,
394 				       bus_space_handle_t bsh,
395 				       bus_size_t offset, u_int16_t value);
396 
397 static __inline void bus_space_write_4(bus_space_tag_t tag,
398 				       bus_space_handle_t bsh,
399 				       bus_size_t offset, u_int32_t value);
400 
401 static __inline void
402 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
403 		       bus_size_t offset, u_int8_t value)
404 {
405 
406 	if (tag == X86_64_BUS_SPACE_IO)
407 		outb(bsh + offset, value);
408 	else
409 		*(volatile u_int8_t *)(bsh + offset) = value;
410 }
411 
412 static __inline void
413 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
414 		       bus_size_t offset, u_int16_t value)
415 {
416 
417 	if (tag == X86_64_BUS_SPACE_IO)
418 		outw(bsh + offset, value);
419 	else
420 		*(volatile u_int16_t *)(bsh + offset) = value;
421 }
422 
423 static __inline void
424 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
425 		       bus_size_t offset, u_int32_t value)
426 {
427 
428 	if (tag == X86_64_BUS_SPACE_IO)
429 		outl(bsh + offset, value);
430 	else
431 		*(volatile u_int32_t *)(bsh + offset) = value;
432 }
433 
434 #ifdef _KERNEL
435 static __inline void
436 bus_space_write_8(bus_space_tag_t tag, bus_space_handle_t bsh,
437 		       bus_size_t offset, u_int64_t value)
438 {
439 	if (tag == X86_64_BUS_SPACE_IO)
440 		panic("bus_space_write_8: illegal on I/O space");
441 	*(volatile u_int64_t *)(bsh + offset) = value;
442 }
443 #endif
444 
445 /*
446  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
447  * provided to bus space described by tag/handle/offset.
448  */
449 
450 static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
451 					     bus_space_handle_t bsh,
452 					     bus_size_t offset,
453 					     const u_int8_t *addr,
454 					     size_t count);
455 static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
456 					     bus_space_handle_t bsh,
457 					     bus_size_t offset,
458 					     const u_int16_t *addr,
459 					     size_t count);
460 
461 static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
462 					     bus_space_handle_t bsh,
463 					     bus_size_t offset,
464 					     const u_int32_t *addr,
465 					     size_t count);
466 
467 static __inline void
468 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
469 			bus_size_t offset, const u_int8_t *addr, size_t count)
470 {
471 
472 	if (tag == X86_64_BUS_SPACE_IO)
473 		outsb(bsh + offset, addr, count);
474 	else {
475 		__asm __volatile("				\n\
476 			cld					\n\
477 		1:	lodsb					\n\
478 			movb %%al,(%2)				\n\
479 			loop 1b"				:
480 		    "=S" (addr), "=c" (count)			:
481 		    "r" (bsh + offset), "0" (addr), "1" (count)	:
482 		    "%eax", "memory", "cc");
483 	}
484 }
485 
486 static __inline void
487 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
488 			bus_size_t offset, const u_int16_t *addr, size_t count)
489 {
490 
491 	if (tag == X86_64_BUS_SPACE_IO)
492 		outsw(bsh + offset, addr, count);
493 	else {
494 		__asm __volatile("				\n\
495 			cld					\n\
496 		1:	lodsw					\n\
497 			movw %%ax,(%2)				\n\
498 			loop 1b"				:
499 		    "=S" (addr), "=c" (count)			:
500 		    "r" (bsh + offset), "0" (addr), "1" (count)	:
501 		    "%eax", "memory", "cc");
502 	}
503 }
504 
505 static __inline void
506 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
507 			bus_size_t offset, const u_int32_t *addr, size_t count)
508 {
509 
510 	if (tag == X86_64_BUS_SPACE_IO)
511 		outsl(bsh + offset, addr, count);
512 	else {
513 		__asm __volatile("				\n\
514 			cld					\n\
515 		1:	lodsl					\n\
516 			movl %%eax,(%2)				\n\
517 			loop 1b"				:
518 		    "=S" (addr), "=c" (count)			:
519 		    "r" (bsh + offset), "0" (addr), "1" (count)	:
520 		    "%eax", "memory", "cc");
521 	}
522 }
523 
524 #if 0	/* Cause a link error for bus_space_write_multi_8 */
525 #define	bus_space_write_multi_8(t, h, o, a, c)				\
526 			!!! bus_space_write_multi_8 unimplemented !!!
527 #endif
528 
529 /*
530  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
531  * to bus space described by tag/handle starting at `offset'.
532  */
533 
534 static __inline void bus_space_write_region_1(bus_space_tag_t tag,
535 					      bus_space_handle_t bsh,
536 					      bus_size_t offset,
537 					      const u_int8_t *addr,
538 					      size_t count);
539 static __inline void bus_space_write_region_2(bus_space_tag_t tag,
540 					      bus_space_handle_t bsh,
541 					      bus_size_t offset,
542 					      const u_int16_t *addr,
543 					      size_t count);
544 static __inline void bus_space_write_region_4(bus_space_tag_t tag,
545 					      bus_space_handle_t bsh,
546 					      bus_size_t offset,
547 					      const u_int32_t *addr,
548 					      size_t count);
549 
550 static __inline void
551 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
552 			 bus_size_t offset, const u_int8_t *addr, size_t count)
553 {
554 
555 	if (tag == X86_64_BUS_SPACE_IO) {
556 		int _port_ = bsh + offset;
557 		__asm __volatile("				\n\
558 			cld					\n\
559 		1:	lodsb					\n\
560 			outb %%al,%w0				\n\
561 			incl %0					\n\
562 			loop 1b"				:
563 		    "=d" (_port_), "=S" (addr), "=c" (count)	:
564 		    "0" (_port_), "1" (addr), "2" (count)	:
565 		    "%eax", "memory", "cc");
566 	} else {
567 		bus_space_handle_t _port_ = bsh + offset;
568 		__asm __volatile("				\n\
569 			cld					\n\
570 			repne					\n\
571 			movsb"					:
572 		    "=D" (_port_), "=S" (addr), "=c" (count)	:
573 		    "0" (_port_), "1" (addr), "2" (count)	:
574 		    "memory", "cc");
575 	}
576 }
577 
578 static __inline void
579 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
580 			 bus_size_t offset, const u_int16_t *addr, size_t count)
581 {
582 
583 	if (tag == X86_64_BUS_SPACE_IO) {
584 		int _port_ = bsh + offset;
585 		__asm __volatile("				\n\
586 			cld					\n\
587 		1:	lodsw					\n\
588 			outw %%ax,%w0				\n\
589 			addl $2,%0				\n\
590 			loop 1b"				:
591 		    "=d" (_port_), "=S" (addr), "=c" (count)	:
592 		    "0" (_port_), "1" (addr), "2" (count)	:
593 		    "%eax", "memory", "cc");
594 	} else {
595 		bus_space_handle_t _port_ = bsh + offset;
596 		__asm __volatile("				\n\
597 			cld					\n\
598 			repne					\n\
599 			movsw"					:
600 		    "=D" (_port_), "=S" (addr), "=c" (count)	:
601 		    "0" (_port_), "1" (addr), "2" (count)	:
602 		    "memory", "cc");
603 	}
604 }
605 
606 static __inline void
607 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
608 			 bus_size_t offset, const u_int32_t *addr, size_t count)
609 {
610 
611 	if (tag == X86_64_BUS_SPACE_IO) {
612 		int _port_ = bsh + offset;
613 		__asm __volatile("				\n\
614 			cld					\n\
615 		1:	lodsl					\n\
616 			outl %%eax,%w0				\n\
617 			addl $4,%0				\n\
618 			loop 1b"				:
619 		    "=d" (_port_), "=S" (addr), "=c" (count)	:
620 		    "0" (_port_), "1" (addr), "2" (count)	:
621 		    "%eax", "memory", "cc");
622 	} else {
623 		bus_space_handle_t _port_ = bsh + offset;
624 		__asm __volatile("				\n\
625 			cld					\n\
626 			repne					\n\
627 			movsl"					:
628 		    "=D" (_port_), "=S" (addr), "=c" (count)	:
629 		    "0" (_port_), "1" (addr), "2" (count)	:
630 		    "memory", "cc");
631 	}
632 }
633 
634 #if 0	/* Cause a link error for bus_space_write_region_8 */
635 #define	bus_space_write_region_8					\
636 			!!! bus_space_write_region_8 unimplemented !!!
637 #endif
638 
639 /*
640  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
641  * by tag/handle/offset `count' times.
642  */
643 
644 static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
645 					   bus_space_handle_t bsh,
646 					   bus_size_t offset,
647 					   u_int8_t value, size_t count);
648 static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
649 					   bus_space_handle_t bsh,
650 					   bus_size_t offset,
651 					   u_int16_t value, size_t count);
652 static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
653 					   bus_space_handle_t bsh,
654 					   bus_size_t offset,
655 					   u_int32_t value, size_t count);
656 
657 static __inline void
658 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
659 		      bus_size_t offset, u_int8_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 			outb(addr, value);
666 	else
667 		while (count--)
668 			*(volatile u_int8_t *)(addr) = value;
669 }
670 
671 static __inline void
672 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
673 		     bus_size_t offset, u_int16_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 			outw(addr, value);
680 	else
681 		while (count--)
682 			*(volatile u_int16_t *)(addr) = value;
683 }
684 
685 static __inline void
686 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
687 		      bus_size_t offset, u_int32_t value, size_t count)
688 {
689 	bus_space_handle_t addr = bsh + offset;
690 
691 	if (tag == X86_64_BUS_SPACE_IO)
692 		while (count--)
693 			outl(addr, value);
694 	else
695 		while (count--)
696 			*(volatile u_int32_t *)(addr) = value;
697 }
698 
699 #if 0	/* Cause a link error for bus_space_set_multi_8 */
700 #define	bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
701 #endif
702 
703 /*
704  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
705  * by tag/handle starting at `offset'.
706  */
707 
708 static __inline void bus_space_set_region_1(bus_space_tag_t tag,
709 					    bus_space_handle_t bsh,
710 					    bus_size_t offset, u_int8_t value,
711 					    size_t count);
712 static __inline void bus_space_set_region_2(bus_space_tag_t tag,
713 					    bus_space_handle_t bsh,
714 					    bus_size_t offset, u_int16_t value,
715 					    size_t count);
716 static __inline void bus_space_set_region_4(bus_space_tag_t tag,
717 					    bus_space_handle_t bsh,
718 					    bus_size_t offset, u_int32_t value,
719 					    size_t count);
720 
721 static __inline void
722 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
723 		       bus_size_t offset, u_int8_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++)
729 			outb(addr, value);
730 	else
731 		for (; count != 0; count--, addr++)
732 			*(volatile u_int8_t *)(addr) = value;
733 }
734 
735 static __inline void
736 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
737 		       bus_size_t offset, u_int16_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 += 2)
743 			outw(addr, value);
744 	else
745 		for (; count != 0; count--, addr += 2)
746 			*(volatile u_int16_t *)(addr) = value;
747 }
748 
749 static __inline void
750 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
751 		       bus_size_t offset, u_int32_t value, size_t count)
752 {
753 	bus_space_handle_t addr = bsh + offset;
754 
755 	if (tag == X86_64_BUS_SPACE_IO)
756 		for (; count != 0; count--, addr += 4)
757 			outl(addr, value);
758 	else
759 		for (; count != 0; count--, addr += 4)
760 			*(volatile u_int32_t *)(addr) = value;
761 }
762 
763 #if 0	/* Cause a link error for bus_space_set_region_8 */
764 #define	bus_space_set_region_8	!!! bus_space_set_region_8 unimplemented !!!
765 #endif
766 
767 /*
768  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
769  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
770  */
771 
772 static __inline void bus_space_copy_region_1(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 bus_space_copy_region_2(bus_space_tag_t tag,
779 					     bus_space_handle_t bsh1,
780 					     bus_size_t off1,
781 					     bus_space_handle_t bsh2,
782 					     bus_size_t off2, size_t count);
783 
784 static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
785 					     bus_space_handle_t bsh1,
786 					     bus_size_t off1,
787 					     bus_space_handle_t bsh2,
788 					     bus_size_t off2, size_t count);
789 
790 static __inline void
791 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
792 			bus_size_t off1, bus_space_handle_t bsh2,
793 			bus_size_t off2, size_t count)
794 {
795 	bus_space_handle_t addr1 = bsh1 + off1;
796 	bus_space_handle_t addr2 = bsh2 + off2;
797 
798 	if (tag == X86_64_BUS_SPACE_IO) {
799 		if (addr1 >= addr2) {
800 			/* src after dest: copy forward */
801 			for (; count != 0; count--, addr1++, addr2++)
802 				outb(addr2, inb(addr1));
803 		} else {
804 			/* dest after src: copy backwards */
805 			for (addr1 += (count - 1), addr2 += (count - 1);
806 			    count != 0; count--, addr1--, addr2--)
807 				outb(addr2, inb(addr1));
808 		}
809 	} else {
810 		if (addr1 >= addr2) {
811 			/* src after dest: copy forward */
812 			for (; count != 0; count--, addr1++, addr2++)
813 				*(volatile u_int8_t *)(addr2) =
814 				    *(volatile u_int8_t *)(addr1);
815 		} else {
816 			/* dest after src: copy backwards */
817 			for (addr1 += (count - 1), addr2 += (count - 1);
818 			    count != 0; count--, addr1--, addr2--)
819 				*(volatile u_int8_t *)(addr2) =
820 				    *(volatile u_int8_t *)(addr1);
821 		}
822 	}
823 }
824 
825 static __inline void
826 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
827 			bus_size_t off1, bus_space_handle_t bsh2,
828 			bus_size_t off2, size_t count)
829 {
830 	bus_space_handle_t addr1 = bsh1 + off1;
831 	bus_space_handle_t addr2 = bsh2 + off2;
832 
833 	if (tag == X86_64_BUS_SPACE_IO) {
834 		if (addr1 >= addr2) {
835 			/* src after dest: copy forward */
836 			for (; count != 0; count--, addr1 += 2, addr2 += 2)
837 				outw(addr2, inw(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 				outw(addr2, inw(addr1));
843 		}
844 	} else {
845 		if (addr1 >= addr2) {
846 			/* src after dest: copy forward */
847 			for (; count != 0; count--, addr1 += 2, addr2 += 2)
848 				*(volatile u_int16_t *)(addr2) =
849 				    *(volatile u_int16_t *)(addr1);
850 		} else {
851 			/* dest after src: copy backwards */
852 			for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
853 			    count != 0; count--, addr1 -= 2, addr2 -= 2)
854 				*(volatile u_int16_t *)(addr2) =
855 				    *(volatile u_int16_t *)(addr1);
856 		}
857 	}
858 }
859 
860 static __inline void
861 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
862 			bus_size_t off1, bus_space_handle_t bsh2,
863 			bus_size_t off2, size_t count)
864 {
865 	bus_space_handle_t addr1 = bsh1 + off1;
866 	bus_space_handle_t addr2 = bsh2 + off2;
867 
868 	if (tag == X86_64_BUS_SPACE_IO) {
869 		if (addr1 >= addr2) {
870 			/* src after dest: copy forward */
871 			for (; count != 0; count--, addr1 += 4, addr2 += 4)
872 				outl(addr2, inl(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 				outl(addr2, inl(addr1));
878 		}
879 	} else {
880 		if (addr1 >= addr2) {
881 			/* src after dest: copy forward */
882 			for (; count != 0; count--, addr1 += 4, addr2 += 4)
883 				*(volatile u_int32_t *)(addr2) =
884 				    *(volatile u_int32_t *)(addr1);
885 		} else {
886 			/* dest after src: copy backwards */
887 			for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
888 			    count != 0; count--, addr1 -= 4, addr2 -= 4)
889 				*(volatile u_int32_t *)(addr2) =
890 				    *(volatile u_int32_t *)(addr1);
891 		}
892 	}
893 }
894 
895 #if 0	/* Cause a link error for bus_space_copy_8 */
896 #define	bus_space_copy_region_8	!!! bus_space_copy_region_8 unimplemented !!!
897 #endif
898 
899 /*
900  * Bus read/write barrier methods.
901  *
902  *	void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
903  *			       bus_size_t offset, bus_size_t len, int flags);
904  *
905  *
906  * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
907  * prevent reordering by the compiler; all Intel x86 processors currently
908  * retire operations outside the CPU in program order.
909  */
910 #define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
911 #define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
912 
913 static __inline void
914 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
915 		  bus_size_t offset __unused, bus_size_t len __unused, int flags)
916 {
917 	if (flags & BUS_SPACE_BARRIER_READ)
918 		__asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory");
919 	else
920 		__asm __volatile("" : : : "memory");
921 }
922 
923 /*
924  * Stream accesses are the same as normal accesses on amd64; there are no
925  * supported bus systems with an endianess different from the host one.
926  */
927 #define	bus_space_read_stream_1(t, h, o)	bus_space_read_1((t), (h), (o))
928 #define	bus_space_read_stream_2(t, h, o)	bus_space_read_2((t), (h), (o))
929 #define	bus_space_read_stream_4(t, h, o)	bus_space_read_4((t), (h), (o))
930 
931 #define	bus_space_read_multi_stream_1(t, h, o, a, c) \
932 	bus_space_read_multi_1((t), (h), (o), (a), (c))
933 #define	bus_space_read_multi_stream_2(t, h, o, a, c) \
934 	bus_space_read_multi_2((t), (h), (o), (a), (c))
935 #define	bus_space_read_multi_stream_4(t, h, o, a, c) \
936 	bus_space_read_multi_4((t), (h), (o), (a), (c))
937 
938 #define	bus_space_write_stream_1(t, h, o, v) \
939 	bus_space_write_1((t), (h), (o), (v))
940 #define	bus_space_write_stream_2(t, h, o, v) \
941 	bus_space_write_2((t), (h), (o), (v))
942 #define	bus_space_write_stream_4(t, h, o, v) \
943 	bus_space_write_4((t), (h), (o), (v))
944 
945 #define	bus_space_write_multi_stream_1(t, h, o, a, c) \
946 	bus_space_write_multi_1((t), (h), (o), (a), (c))
947 #define	bus_space_write_multi_stream_2(t, h, o, a, c) \
948 	bus_space_write_multi_2((t), (h), (o), (a), (c))
949 #define	bus_space_write_multi_stream_4(t, h, o, a, c) \
950 	bus_space_write_multi_4((t), (h), (o), (a), (c))
951 
952 #define	bus_space_set_multi_stream_1(t, h, o, v, c) \
953 	bus_space_set_multi_1((t), (h), (o), (v), (c))
954 #define	bus_space_set_multi_stream_2(t, h, o, v, c) \
955 	bus_space_set_multi_2((t), (h), (o), (v), (c))
956 #define	bus_space_set_multi_stream_4(t, h, o, v, c) \
957 	bus_space_set_multi_4((t), (h), (o), (v), (c))
958 
959 #define	bus_space_read_region_stream_1(t, h, o, a, c) \
960 	bus_space_read_region_1((t), (h), (o), (a), (c))
961 #define	bus_space_read_region_stream_2(t, h, o, a, c) \
962 	bus_space_read_region_2((t), (h), (o), (a), (c))
963 #define	bus_space_read_region_stream_4(t, h, o, a, c) \
964 	bus_space_read_region_4((t), (h), (o), (a), (c))
965 
966 #define	bus_space_write_region_stream_1(t, h, o, a, c) \
967 	bus_space_write_region_1((t), (h), (o), (a), (c))
968 #define	bus_space_write_region_stream_2(t, h, o, a, c) \
969 	bus_space_write_region_2((t), (h), (o), (a), (c))
970 #define	bus_space_write_region_stream_4(t, h, o, a, c) \
971 	bus_space_write_region_4((t), (h), (o), (a), (c))
972 
973 #define	bus_space_set_region_stream_1(t, h, o, v, c) \
974 	bus_space_set_region_1((t), (h), (o), (v), (c))
975 #define	bus_space_set_region_stream_2(t, h, o, v, c) \
976 	bus_space_set_region_2((t), (h), (o), (v), (c))
977 #define	bus_space_set_region_stream_4(t, h, o, v, c) \
978 	bus_space_set_region_4((t), (h), (o), (v), (c))
979 
980 #define	bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \
981 	bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
982 #define	bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \
983 	bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c))
984 #define	bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \
985 	bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c))
986 
987 #endif /* _CPU_BUS_DMA_H_ */
988