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