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/10.1/sys/x86/include/bus.h 263687 2014-03-24 13:48:04Z emaste $
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 static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
134 bus_size_t size, int flags,
135 bus_space_handle_t *bshp);
136
137 static __inline int
138 bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
139 bus_size_t size __unused, int flags __unused,
140 bus_space_handle_t *bshp)
141 {
142
143 *bshp = addr;
144 return (0);
145 }
146
147 /*
148 * Unmap a region of device bus space.
149 */
150
151 static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
152 bus_size_t size);
153
154 static __inline void
155 bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
156 bus_size_t size __unused)
157 {
158 }
159
160 /*
161 * Get a new handle for a subregion of an already-mapped area of bus space.
162 */
163
164 static __inline int bus_space_subregion(bus_space_tag_t t,
165 bus_space_handle_t bsh,
166 bus_size_t offset, bus_size_t size,
167 bus_space_handle_t *nbshp);
168
169 static __inline int
170 bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh,
171 bus_size_t offset, bus_size_t size __unused,
172 bus_space_handle_t *nbshp)
173 {
174
175 *nbshp = bsh + offset;
176 return (0);
177 }
178
179 /*
180 * Allocate a region of memory that is accessible to devices in bus space.
181 */
182
183 int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
184 bus_addr_t rend, bus_size_t size, bus_size_t align,
185 bus_size_t boundary, int flags, bus_addr_t *addrp,
186 bus_space_handle_t *bshp);
187
188 /*
189 * Free a region of bus space accessible memory.
190 */
191
192 static __inline void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
193 bus_size_t size);
194
195 static __inline void
196 bus_space_free(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
197 bus_size_t size __unused)
198 {
199 }
200
201
202 /*
203 * Read a 1, 2, 4, or 8 byte quantity from bus space
204 * described by tag/handle/offset.
205 */
206 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
207 bus_space_handle_t handle,
208 bus_size_t offset);
209
210 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
211 bus_space_handle_t handle,
212 bus_size_t offset);
213
214 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
215 bus_space_handle_t handle,
216 bus_size_t offset);
217
218 #ifdef __amd64__
219 static __inline uint64_t bus_space_read_8(bus_space_tag_t tag,
220 bus_space_handle_t handle,
221 bus_size_t offset);
222 #endif
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 #ifdef __amd64__
255 static __inline uint64_t
256 bus_space_read_8(bus_space_tag_t tag, bus_space_handle_t handle,
257 bus_size_t offset)
258 {
259
260 if (tag == X86_BUS_SPACE_IO) /* No 8 byte IO space access on x86 */
261 return (BUS_SPACE_INVALID_DATA);
262 return (*(volatile uint64_t *)(handle + offset));
263 }
264 #endif
265
266 /*
267 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
268 * described by tag/handle/offset and copy into buffer provided.
269 */
270 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
271 bus_space_handle_t bsh,
272 bus_size_t offset, u_int8_t *addr,
273 size_t count);
274
275 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
276 bus_space_handle_t bsh,
277 bus_size_t offset, u_int16_t *addr,
278 size_t count);
279
280 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
281 bus_space_handle_t bsh,
282 bus_size_t offset, u_int32_t *addr,
283 size_t count);
284
285 static __inline void
286 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
287 bus_size_t offset, u_int8_t *addr, size_t count)
288 {
289
290 if (tag == X86_BUS_SPACE_IO)
291 insb(bsh + offset, addr, count);
292 else {
293 #ifdef __GNUCLIKE_ASM
294 __asm __volatile(" \n\
295 cld \n\
296 1: movb (%2),%%al \n\
297 stosb \n\
298 loop 1b" :
299 "=D" (addr), "=c" (count) :
300 "r" (bsh + offset), "" (addr), "1" (count) :
301 "%eax", "memory");
302 #endif
303 }
304 }
305
306 static __inline void
307 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
308 bus_size_t offset, u_int16_t *addr, size_t count)
309 {
310
311 if (tag == X86_BUS_SPACE_IO)
312 insw(bsh + offset, addr, count);
313 else {
314 #ifdef __GNUCLIKE_ASM
315 __asm __volatile(" \n\
316 cld \n\
317 1: movw (%2),%%ax \n\
318 stosw \n\
319 loop 1b" :
320 "=D" (addr), "=c" (count) :
321 "r" (bsh + offset), "" (addr), "1" (count) :
322 "%eax", "memory");
323 #endif
324 }
325 }
326
327 static __inline void
328 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
329 bus_size_t offset, u_int32_t *addr, size_t count)
330 {
331
332 if (tag == X86_BUS_SPACE_IO)
333 insl(bsh + offset, addr, count);
334 else {
335 #ifdef __GNUCLIKE_ASM
336 __asm __volatile(" \n\
337 cld \n\
338 1: movl (%2),%%eax \n\
339 stosl \n\
340 loop 1b" :
341 "=D" (addr), "=c" (count) :
342 "r" (bsh + offset), "" (addr), "1" (count) :
343 "%eax", "memory");
344 #endif
345 }
346 }
347
348 #if 0 /* Cause a link error for bus_space_read_multi_8 */
349 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!!
350 #endif
351
352 /*
353 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
354 * described by tag/handle and starting at `offset' and copy into
355 * buffer provided.
356 */
357 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
358 bus_space_handle_t bsh,
359 bus_size_t offset, u_int8_t *addr,
360 size_t count);
361
362 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
363 bus_space_handle_t bsh,
364 bus_size_t offset, u_int16_t *addr,
365 size_t count);
366
367 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
368 bus_space_handle_t bsh,
369 bus_size_t offset, u_int32_t *addr,
370 size_t count);
371
372
373 static __inline void
374 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
375 bus_size_t offset, u_int8_t *addr, size_t count)
376 {
377
378 if (tag == X86_BUS_SPACE_IO) {
379 int _port_ = bsh + offset;
380 #ifdef __GNUCLIKE_ASM
381 __asm __volatile(" \n\
382 cld \n\
383 1: inb %w2,%%al \n\
384 stosb \n\
385 incl %2 \n\
386 loop 1b" :
387 "=D" (addr), "=c" (count), "=d" (_port_) :
388 "" (addr), "1" (count), "2" (_port_) :
389 "%eax", "memory", "cc");
390 #endif
391 } else {
392 bus_space_handle_t _port_ = bsh + offset;
393 #ifdef __GNUCLIKE_ASM
394 __asm __volatile(" \n\
395 cld \n\
396 repne \n\
397 movsb" :
398 "=D" (addr), "=c" (count), "=S" (_port_) :
399 "" (addr), "1" (count), "2" (_port_) :
400 "memory", "cc");
401 #endif
402 }
403 }
404
405 static __inline void
406 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
407 bus_size_t offset, u_int16_t *addr, size_t count)
408 {
409
410 if (tag == X86_BUS_SPACE_IO) {
411 int _port_ = bsh + offset;
412 #ifdef __GNUCLIKE_ASM
413 __asm __volatile(" \n\
414 cld \n\
415 1: inw %w2,%%ax \n\
416 stosw \n\
417 addl $2,%2 \n\
418 loop 1b" :
419 "=D" (addr), "=c" (count), "=d" (_port_) :
420 "" (addr), "1" (count), "2" (_port_) :
421 "%eax", "memory", "cc");
422 #endif
423 } else {
424 bus_space_handle_t _port_ = bsh + offset;
425 #ifdef __GNUCLIKE_ASM
426 __asm __volatile(" \n\
427 cld \n\
428 repne \n\
429 movsw" :
430 "=D" (addr), "=c" (count), "=S" (_port_) :
431 "" (addr), "1" (count), "2" (_port_) :
432 "memory", "cc");
433 #endif
434 }
435 }
436
437 static __inline void
438 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
439 bus_size_t offset, u_int32_t *addr, size_t count)
440 {
441
442 if (tag == X86_BUS_SPACE_IO) {
443 int _port_ = bsh + offset;
444 #ifdef __GNUCLIKE_ASM
445 __asm __volatile(" \n\
446 cld \n\
447 1: inl %w2,%%eax \n\
448 stosl \n\
449 addl $4,%2 \n\
450 loop 1b" :
451 "=D" (addr), "=c" (count), "=d" (_port_) :
452 "" (addr), "1" (count), "2" (_port_) :
453 "%eax", "memory", "cc");
454 #endif
455 } else {
456 bus_space_handle_t _port_ = bsh + offset;
457 #ifdef __GNUCLIKE_ASM
458 __asm __volatile(" \n\
459 cld \n\
460 repne \n\
461 movsl" :
462 "=D" (addr), "=c" (count), "=S" (_port_) :
463 "" (addr), "1" (count), "2" (_port_) :
464 "memory", "cc");
465 #endif
466 }
467 }
468
469 #if 0 /* Cause a link error for bus_space_read_region_8 */
470 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
471 #endif
472
473 /*
474 * Write the 1, 2, 4, or 8 byte value `value' to bus space
475 * described by tag/handle/offset.
476 */
477
478 static __inline void bus_space_write_1(bus_space_tag_t tag,
479 bus_space_handle_t bsh,
480 bus_size_t offset, u_int8_t value);
481
482 static __inline void bus_space_write_2(bus_space_tag_t tag,
483 bus_space_handle_t bsh,
484 bus_size_t offset, u_int16_t value);
485
486 static __inline void bus_space_write_4(bus_space_tag_t tag,
487 bus_space_handle_t bsh,
488 bus_size_t offset, u_int32_t value);
489
490 #ifdef __amd64__
491 static __inline void bus_space_write_8(bus_space_tag_t tag,
492 bus_space_handle_t bsh,
493 bus_size_t offset, uint64_t value);
494 #endif
495
496 static __inline void
497 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
498 bus_size_t offset, u_int8_t value)
499 {
500
501 if (tag == X86_BUS_SPACE_IO)
502 outb(bsh + offset, value);
503 else
504 *(volatile u_int8_t *)(bsh + offset) = value;
505 }
506
507 static __inline void
508 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
509 bus_size_t offset, u_int16_t value)
510 {
511
512 if (tag == X86_BUS_SPACE_IO)
513 outw(bsh + offset, value);
514 else
515 *(volatile u_int16_t *)(bsh + offset) = value;
516 }
517
518 static __inline void
519 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
520 bus_size_t offset, u_int32_t value)
521 {
522
523 if (tag == X86_BUS_SPACE_IO)
524 outl(bsh + offset, value);
525 else
526 *(volatile u_int32_t *)(bsh + offset) = value;
527 }
528
529 #ifdef __amd64__
530 static __inline void
531 bus_space_write_8(bus_space_tag_t tag, bus_space_handle_t bsh,
532 bus_size_t offset, uint64_t value)
533 {
534
535 if (tag == X86_BUS_SPACE_IO) /* No 8 byte IO space access on x86 */
536 return;
537 else
538 *(volatile uint64_t *)(bsh + offset) = value;
539 }
540 #endif
541
542 /*
543 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
544 * provided to bus space described by tag/handle/offset.
545 */
546
547 static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
548 bus_space_handle_t bsh,
549 bus_size_t offset,
550 const u_int8_t *addr,
551 size_t count);
552 static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
553 bus_space_handle_t bsh,
554 bus_size_t offset,
555 const u_int16_t *addr,
556 size_t count);
557
558 static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
559 bus_space_handle_t bsh,
560 bus_size_t offset,
561 const u_int32_t *addr,
562 size_t count);
563
564 static __inline void
565 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
566 bus_size_t offset, const u_int8_t *addr, size_t count)
567 {
568
569 if (tag == X86_BUS_SPACE_IO)
570 outsb(bsh + offset, addr, count);
571 else {
572 #ifdef __GNUCLIKE_ASM
573 __asm __volatile(" \n\
574 cld \n\
575 1: lodsb \n\
576 movb %%al,(%2) \n\
577 loop 1b" :
578 "=S" (addr), "=c" (count) :
579 "r" (bsh + offset), "" (addr), "1" (count) :
580 "%eax", "memory", "cc");
581 #endif
582 }
583 }
584
585 static __inline void
586 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
587 bus_size_t offset, const u_int16_t *addr, size_t count)
588 {
589
590 if (tag == X86_BUS_SPACE_IO)
591 outsw(bsh + offset, addr, count);
592 else {
593 #ifdef __GNUCLIKE_ASM
594 __asm __volatile(" \n\
595 cld \n\
596 1: lodsw \n\
597 movw %%ax,(%2) \n\
598 loop 1b" :
599 "=S" (addr), "=c" (count) :
600 "r" (bsh + offset), "" (addr), "1" (count) :
601 "%eax", "memory", "cc");
602 #endif
603 }
604 }
605
606 static __inline void
607 bus_space_write_multi_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_BUS_SPACE_IO)
612 outsl(bsh + offset, addr, count);
613 else {
614 #ifdef __GNUCLIKE_ASM
615 __asm __volatile(" \n\
616 cld \n\
617 1: lodsl \n\
618 movl %%eax,(%2) \n\
619 loop 1b" :
620 "=S" (addr), "=c" (count) :
621 "r" (bsh + offset), "" (addr), "1" (count) :
622 "%eax", "memory", "cc");
623 #endif
624 }
625 }
626
627 #if 0 /* Cause a link error for bus_space_write_multi_8 */
628 #define bus_space_write_multi_8(t, h, o, a, c) \
629 !!! bus_space_write_multi_8 unimplemented !!!
630 #endif
631
632 /*
633 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
634 * to bus space described by tag/handle starting at `offset'.
635 */
636
637 static __inline void bus_space_write_region_1(bus_space_tag_t tag,
638 bus_space_handle_t bsh,
639 bus_size_t offset,
640 const u_int8_t *addr,
641 size_t count);
642 static __inline void bus_space_write_region_2(bus_space_tag_t tag,
643 bus_space_handle_t bsh,
644 bus_size_t offset,
645 const u_int16_t *addr,
646 size_t count);
647 static __inline void bus_space_write_region_4(bus_space_tag_t tag,
648 bus_space_handle_t bsh,
649 bus_size_t offset,
650 const u_int32_t *addr,
651 size_t count);
652
653 static __inline void
654 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
655 bus_size_t offset, const u_int8_t *addr, size_t count)
656 {
657
658 if (tag == X86_BUS_SPACE_IO) {
659 int _port_ = bsh + offset;
660 #ifdef __GNUCLIKE_ASM
661 __asm __volatile(" \n\
662 cld \n\
663 1: lodsb \n\
664 outb %%al,%w0 \n\
665 incl %0 \n\
666 loop 1b" :
667 "=d" (_port_), "=S" (addr), "=c" (count) :
668 "" (_port_), "1" (addr), "2" (count) :
669 "%eax", "memory", "cc");
670 #endif
671 } else {
672 bus_space_handle_t _port_ = bsh + offset;
673 #ifdef __GNUCLIKE_ASM
674 __asm __volatile(" \n\
675 cld \n\
676 repne \n\
677 movsb" :
678 "=D" (_port_), "=S" (addr), "=c" (count) :
679 "" (_port_), "1" (addr), "2" (count) :
680 "memory", "cc");
681 #endif
682 }
683 }
684
685 static __inline void
686 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
687 bus_size_t offset, const u_int16_t *addr, size_t count)
688 {
689
690 if (tag == X86_BUS_SPACE_IO) {
691 int _port_ = bsh + offset;
692 #ifdef __GNUCLIKE_ASM
693 __asm __volatile(" \n\
694 cld \n\
695 1: lodsw \n\
696 outw %%ax,%w0 \n\
697 addl $2,%0 \n\
698 loop 1b" :
699 "=d" (_port_), "=S" (addr), "=c" (count) :
700 "" (_port_), "1" (addr), "2" (count) :
701 "%eax", "memory", "cc");
702 #endif
703 } else {
704 bus_space_handle_t _port_ = bsh + offset;
705 #ifdef __GNUCLIKE_ASM
706 __asm __volatile(" \n\
707 cld \n\
708 repne \n\
709 movsw" :
710 "=D" (_port_), "=S" (addr), "=c" (count) :
711 "" (_port_), "1" (addr), "2" (count) :
712 "memory", "cc");
713 #endif
714 }
715 }
716
717 static __inline void
718 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
719 bus_size_t offset, const u_int32_t *addr, size_t count)
720 {
721
722 if (tag == X86_BUS_SPACE_IO) {
723 int _port_ = bsh + offset;
724 #ifdef __GNUCLIKE_ASM
725 __asm __volatile(" \n\
726 cld \n\
727 1: lodsl \n\
728 outl %%eax,%w0 \n\
729 addl $4,%0 \n\
730 loop 1b" :
731 "=d" (_port_), "=S" (addr), "=c" (count) :
732 "" (_port_), "1" (addr), "2" (count) :
733 "%eax", "memory", "cc");
734 #endif
735 } else {
736 bus_space_handle_t _port_ = bsh + offset;
737 #ifdef __GNUCLIKE_ASM
738 __asm __volatile(" \n\
739 cld \n\
740 repne \n\
741 movsl" :
742 "=D" (_port_), "=S" (addr), "=c" (count) :
743 "" (_port_), "1" (addr), "2" (count) :
744 "memory", "cc");
745 #endif
746 }
747 }
748
749 #if 0 /* Cause a link error for bus_space_write_region_8 */
750 #define bus_space_write_region_8 \
751 !!! bus_space_write_region_8 unimplemented !!!
752 #endif
753
754 /*
755 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
756 * by tag/handle/offset `count' times.
757 */
758
759 static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
760 bus_space_handle_t bsh,
761 bus_size_t offset,
762 u_int8_t value, size_t count);
763 static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
764 bus_space_handle_t bsh,
765 bus_size_t offset,
766 u_int16_t value, size_t count);
767 static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
768 bus_space_handle_t bsh,
769 bus_size_t offset,
770 u_int32_t value, size_t count);
771
772 static __inline void
773 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
774 bus_size_t offset, u_int8_t value, size_t count)
775 {
776 bus_space_handle_t addr = bsh + offset;
777
778 if (tag == X86_BUS_SPACE_IO)
779 while (count--)
780 outb(addr, value);
781 else
782 while (count--)
783 *(volatile u_int8_t *)(addr) = value;
784 }
785
786 static __inline void
787 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
788 bus_size_t offset, u_int16_t value, size_t count)
789 {
790 bus_space_handle_t addr = bsh + offset;
791
792 if (tag == X86_BUS_SPACE_IO)
793 while (count--)
794 outw(addr, value);
795 else
796 while (count--)
797 *(volatile u_int16_t *)(addr) = value;
798 }
799
800 static __inline void
801 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
802 bus_size_t offset, u_int32_t value, size_t count)
803 {
804 bus_space_handle_t addr = bsh + offset;
805
806 if (tag == X86_BUS_SPACE_IO)
807 while (count--)
808 outl(addr, value);
809 else
810 while (count--)
811 *(volatile u_int32_t *)(addr) = value;
812 }
813
814 #if 0 /* Cause a link error for bus_space_set_multi_8 */
815 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
816 #endif
817
818 /*
819 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
820 * by tag/handle starting at `offset'.
821 */
822
823 static __inline void bus_space_set_region_1(bus_space_tag_t tag,
824 bus_space_handle_t bsh,
825 bus_size_t offset, u_int8_t value,
826 size_t count);
827 static __inline void bus_space_set_region_2(bus_space_tag_t tag,
828 bus_space_handle_t bsh,
829 bus_size_t offset, u_int16_t value,
830 size_t count);
831 static __inline void bus_space_set_region_4(bus_space_tag_t tag,
832 bus_space_handle_t bsh,
833 bus_size_t offset, u_int32_t value,
834 size_t count);
835
836 static __inline void
837 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
838 bus_size_t offset, u_int8_t value, size_t count)
839 {
840 bus_space_handle_t addr = bsh + offset;
841
842 if (tag == X86_BUS_SPACE_IO)
843 for (; count != 0; count--, addr++)
844 outb(addr, value);
845 else
846 for (; count != 0; count--, addr++)
847 *(volatile u_int8_t *)(addr) = value;
848 }
849
850 static __inline void
851 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
852 bus_size_t offset, u_int16_t value, size_t count)
853 {
854 bus_space_handle_t addr = bsh + offset;
855
856 if (tag == X86_BUS_SPACE_IO)
857 for (; count != 0; count--, addr += 2)
858 outw(addr, value);
859 else
860 for (; count != 0; count--, addr += 2)
861 *(volatile u_int16_t *)(addr) = value;
862 }
863
864 static __inline void
865 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
866 bus_size_t offset, u_int32_t value, size_t count)
867 {
868 bus_space_handle_t addr = bsh + offset;
869
870 if (tag == X86_BUS_SPACE_IO)
871 for (; count != 0; count--, addr += 4)
872 outl(addr, value);
873 else
874 for (; count != 0; count--, addr += 4)
875 *(volatile u_int32_t *)(addr) = value;
876 }
877
878 #if 0 /* Cause a link error for bus_space_set_region_8 */
879 #define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!!
880 #endif
881
882 /*
883 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
884 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
885 */
886
887 static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
888 bus_space_handle_t bsh1,
889 bus_size_t off1,
890 bus_space_handle_t bsh2,
891 bus_size_t off2, size_t count);
892
893 static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
894 bus_space_handle_t bsh1,
895 bus_size_t off1,
896 bus_space_handle_t bsh2,
897 bus_size_t off2, size_t count);
898
899 static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
900 bus_space_handle_t bsh1,
901 bus_size_t off1,
902 bus_space_handle_t bsh2,
903 bus_size_t off2, size_t count);
904
905 static __inline void
906 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
907 bus_size_t off1, bus_space_handle_t bsh2,
908 bus_size_t off2, size_t count)
909 {
910 bus_space_handle_t addr1 = bsh1 + off1;
911 bus_space_handle_t addr2 = bsh2 + off2;
912
913 if (tag == X86_BUS_SPACE_IO) {
914 if (addr1 >= addr2) {
915 /* src after dest: copy forward */
916 for (; count != 0; count--, addr1++, addr2++)
917 outb(addr2, inb(addr1));
918 } else {
919 /* dest after src: copy backwards */
920 for (addr1 += (count - 1), addr2 += (count - 1);
921 count != 0; count--, addr1--, addr2--)
922 outb(addr2, inb(addr1));
923 }
924 } else {
925 if (addr1 >= addr2) {
926 /* src after dest: copy forward */
927 for (; count != 0; count--, addr1++, addr2++)
928 *(volatile u_int8_t *)(addr2) =
929 *(volatile u_int8_t *)(addr1);
930 } else {
931 /* dest after src: copy backwards */
932 for (addr1 += (count - 1), addr2 += (count - 1);
933 count != 0; count--, addr1--, addr2--)
934 *(volatile u_int8_t *)(addr2) =
935 *(volatile u_int8_t *)(addr1);
936 }
937 }
938 }
939
940 static __inline void
941 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
942 bus_size_t off1, bus_space_handle_t bsh2,
943 bus_size_t off2, size_t count)
944 {
945 bus_space_handle_t addr1 = bsh1 + off1;
946 bus_space_handle_t addr2 = bsh2 + off2;
947
948 if (tag == X86_BUS_SPACE_IO) {
949 if (addr1 >= addr2) {
950 /* src after dest: copy forward */
951 for (; count != 0; count--, addr1 += 2, addr2 += 2)
952 outw(addr2, inw(addr1));
953 } else {
954 /* dest after src: copy backwards */
955 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
956 count != 0; count--, addr1 -= 2, addr2 -= 2)
957 outw(addr2, inw(addr1));
958 }
959 } else {
960 if (addr1 >= addr2) {
961 /* src after dest: copy forward */
962 for (; count != 0; count--, addr1 += 2, addr2 += 2)
963 *(volatile u_int16_t *)(addr2) =
964 *(volatile u_int16_t *)(addr1);
965 } else {
966 /* dest after src: copy backwards */
967 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
968 count != 0; count--, addr1 -= 2, addr2 -= 2)
969 *(volatile u_int16_t *)(addr2) =
970 *(volatile u_int16_t *)(addr1);
971 }
972 }
973 }
974
975 static __inline void
976 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
977 bus_size_t off1, bus_space_handle_t bsh2,
978 bus_size_t off2, size_t count)
979 {
980 bus_space_handle_t addr1 = bsh1 + off1;
981 bus_space_handle_t addr2 = bsh2 + off2;
982
983 if (tag == X86_BUS_SPACE_IO) {
984 if (addr1 >= addr2) {
985 /* src after dest: copy forward */
986 for (; count != 0; count--, addr1 += 4, addr2 += 4)
987 outl(addr2, inl(addr1));
988 } else {
989 /* dest after src: copy backwards */
990 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
991 count != 0; count--, addr1 -= 4, addr2 -= 4)
992 outl(addr2, inl(addr1));
993 }
994 } else {
995 if (addr1 >= addr2) {
996 /* src after dest: copy forward */
997 for (; count != 0; count--, addr1 += 4, addr2 += 4)
998 *(volatile u_int32_t *)(addr2) =
999 *(volatile u_int32_t *)(addr1);
1000 } else {
1001 /* dest after src: copy backwards */
1002 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
1003 count != 0; count--, addr1 -= 4, addr2 -= 4)
1004 *(volatile u_int32_t *)(addr2) =
1005 *(volatile u_int32_t *)(addr1);
1006 }
1007 }
1008 }
1009
1010 #if 0 /* Cause a link error for bus_space_copy_8 */
1011 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!!
1012 #endif
1013
1014 /*
1015 * Bus read/write barrier methods.
1016 *
1017 * void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
1018 * bus_size_t offset, bus_size_t len, int flags);
1019 *
1020 *
1021 * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
1022 * prevent reordering by the compiler; all Intel x86 processors currently
1023 * retire operations outside the CPU in program order.
1024 */
1025 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
1026 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
1027
1028 static __inline void
1029 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
1030 bus_size_t offset __unused, bus_size_t len __unused, int flags)
1031 {
1032 #ifdef __GNUCLIKE_ASM
1033 if (flags & BUS_SPACE_BARRIER_READ)
1034 #ifdef __amd64__
1035 __asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory");
1036 #else
1037 __asm __volatile("lock; addl $0,0(%%esp)" : : : "memory");
1038 #endif
1039 else
1040 __compiler_membar();
1041 #endif
1042 }
1043
1044 #ifdef BUS_SPACE_NO_LEGACY
1045 #undef inb
1046 #undef outb
1047 #define inb(a) compiler_error
1048 #define inw(a) compiler_error
1049 #define inl(a) compiler_error
1050 #define outb(a, b) compiler_error
1051 #define outw(a, b) compiler_error
1052 #define outl(a, b) compiler_error
1053 #endif
1054
1055 #include <machine/bus_dma.h>
1056
1057 /*
1058 * Stream accesses are the same as normal accesses on x86; there are no
1059 * supported bus systems with an endianess different from the host one.
1060 */
1061 #define bus_space_read_stream_1(t, h, o) bus_space_read_1((t), (h), (o))
1062 #define bus_space_read_stream_2(t, h, o) bus_space_read_2((t), (h), (o))
1063 #define bus_space_read_stream_4(t, h, o) bus_space_read_4((t), (h), (o))
1064
1065 #define bus_space_read_multi_stream_1(t, h, o, a, c) \
1066 bus_space_read_multi_1((t), (h), (o), (a), (c))
1067 #define bus_space_read_multi_stream_2(t, h, o, a, c) \
1068 bus_space_read_multi_2((t), (h), (o), (a), (c))
1069 #define bus_space_read_multi_stream_4(t, h, o, a, c) \
1070 bus_space_read_multi_4((t), (h), (o), (a), (c))
1071
1072 #define bus_space_write_stream_1(t, h, o, v) \
1073 bus_space_write_1((t), (h), (o), (v))
1074 #define bus_space_write_stream_2(t, h, o, v) \
1075 bus_space_write_2((t), (h), (o), (v))
1076 #define bus_space_write_stream_4(t, h, o, v) \
1077 bus_space_write_4((t), (h), (o), (v))
1078
1079 #define bus_space_write_multi_stream_1(t, h, o, a, c) \
1080 bus_space_write_multi_1((t), (h), (o), (a), (c))
1081 #define bus_space_write_multi_stream_2(t, h, o, a, c) \
1082 bus_space_write_multi_2((t), (h), (o), (a), (c))
1083 #define bus_space_write_multi_stream_4(t, h, o, a, c) \
1084 bus_space_write_multi_4((t), (h), (o), (a), (c))
1085
1086 #define bus_space_set_multi_stream_1(t, h, o, v, c) \
1087 bus_space_set_multi_1((t), (h), (o), (v), (c))
1088 #define bus_space_set_multi_stream_2(t, h, o, v, c) \
1089 bus_space_set_multi_2((t), (h), (o), (v), (c))
1090 #define bus_space_set_multi_stream_4(t, h, o, v, c) \
1091 bus_space_set_multi_4((t), (h), (o), (v), (c))
1092
1093 #define bus_space_read_region_stream_1(t, h, o, a, c) \
1094 bus_space_read_region_1((t), (h), (o), (a), (c))
1095 #define bus_space_read_region_stream_2(t, h, o, a, c) \
1096 bus_space_read_region_2((t), (h), (o), (a), (c))
1097 #define bus_space_read_region_stream_4(t, h, o, a, c) \
1098 bus_space_read_region_4((t), (h), (o), (a), (c))
1099
1100 #define bus_space_write_region_stream_1(t, h, o, a, c) \
1101 bus_space_write_region_1((t), (h), (o), (a), (c))
1102 #define bus_space_write_region_stream_2(t, h, o, a, c) \
1103 bus_space_write_region_2((t), (h), (o), (a), (c))
1104 #define bus_space_write_region_stream_4(t, h, o, a, c) \
1105 bus_space_write_region_4((t), (h), (o), (a), (c))
1106
1107 #define bus_space_set_region_stream_1(t, h, o, v, c) \
1108 bus_space_set_region_1((t), (h), (o), (v), (c))
1109 #define bus_space_set_region_stream_2(t, h, o, v, c) \
1110 bus_space_set_region_2((t), (h), (o), (v), (c))
1111 #define bus_space_set_region_stream_4(t, h, o, v, c) \
1112 bus_space_set_region_4((t), (h), (o), (v), (c))
1113
1114 #define bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \
1115 bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
1116 #define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \
1117 bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c))
1118 #define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \
1119 bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c))
1120
1121 #endif /* _X86_BUS_H_ */
Cache object: 0a016b5e41f7309bdd5ef9048f8013a1
|