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