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