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