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