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