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