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