Do a major clean-up of the BUSDMA architecture. A large number of
[dragonfly.git] / sys / cpu / i386 / include / bus_at386.h
CommitLineData
984263bc
MD
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: src/sys/i386/include/bus_at386.h,v 1.8.2.3 2002/03/03 05:42:50 nyan Exp $ */
1f7ab7c9 71/* $DragonFly: src/sys/cpu/i386/include/bus_at386.h,v 1.9 2006/10/25 20:55:51 dillon Exp $ */
984263bc 72
f8334305
MD
73#ifndef _MACHINE_BUS_AT386_H_
74#define _MACHINE_BUS_AT386_H_
984263bc 75
f8334305 76#include <machine/cpufunc.h>
984263bc 77
984263bc
MD
78/*
79 * Values for the i386 bus space tag, not to be used directly by MI code.
80 */
81#define I386_BUS_SPACE_IO 0 /* space is i/o space */
82#define I386_BUS_SPACE_MEM 1 /* space is mem space */
83
84/*
85 * Bus address and size types
86 */
6ef943a3
MD
87typedef u_int32_t bus_addr_t;
88typedef u_int32_t bus_size_t;
984263bc
MD
89
90#define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
91#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
92#define BUS_SPACE_MAXSIZE (64 * 1024) /* Maximum supported size */
93#define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
94#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
6ef943a3 95#define BUS_SPACE_MAXADDR BUS_SPACE_MAXADDR_32BIT
984263bc
MD
96
97#define BUS_SPACE_UNRESTRICTED (~0)
98
99/*
100 * Access methods for bus resources and address space.
101 */
102typedef int bus_space_tag_t;
103typedef u_int bus_space_handle_t;
104
105/*
106 * Map a region of device bus space into CPU virtual address space.
107 */
108
109#define BUS_SPACE_MAP_CACHEABLE 0x01
110#define BUS_SPACE_MAP_LINEAR 0x02
111
112int bus_space_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size,
113 int flags, bus_space_handle_t *bshp);
114
115/*
116 * Unmap a region of device bus space.
117 */
118
119static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
120 bus_size_t size);
121
122static __inline void
1a5be628 123bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused, bus_size_t size __unused )
984263bc
MD
124{
125}
126
127/*
128 * Get a new handle for a subregion of an already-mapped area of bus space.
129 */
130
131static __inline int bus_space_subregion(bus_space_tag_t t,
132 bus_space_handle_t bsh,
133 bus_size_t offset, bus_size_t size,
134 bus_space_handle_t *nbshp);
135
136static __inline int
1a5be628
MD
137bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh,
138 bus_size_t offset, bus_size_t size __unused,
984263bc
MD
139 bus_space_handle_t *nbshp)
140{
141
142 *nbshp = bsh + offset;
143 return (0);
144}
145
146/*
147 * Allocate a region of memory that is accessible to devices in bus space.
148 */
149
150int bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
151 bus_addr_t rend, bus_size_t size, bus_size_t align,
152 bus_size_t boundary, int flags, bus_addr_t *addrp,
153 bus_space_handle_t *bshp);
154
155/*
156 * Free a region of bus space accessible memory.
157 */
158
159static __inline void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
160 bus_size_t size);
161
162static __inline void
1a5be628 163bus_space_free(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused, bus_size_t size __unused)
984263bc
MD
164{
165}
166
984263bc
MD
167/*
168 * Read a 1, 2, 4, or 8 byte quantity from bus space
169 * described by tag/handle/offset.
170 */
171static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
172 bus_space_handle_t handle,
173 bus_size_t offset);
174
175static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
176 bus_space_handle_t handle,
177 bus_size_t offset);
178
179static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
180 bus_space_handle_t handle,
181 bus_size_t offset);
182
183static __inline u_int8_t
184bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
185 bus_size_t offset)
186{
984263bc 187 if (tag == I386_BUS_SPACE_IO)
984263bc 188 return (inb(handle + offset));
984263bc 189 return (*(volatile u_int8_t *)(handle + offset));
984263bc
MD
190}
191
192static __inline u_int16_t
193bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
194 bus_size_t offset)
195{
984263bc 196 if (tag == I386_BUS_SPACE_IO)
984263bc 197 return (inw(handle + offset));
984263bc 198 return (*(volatile u_int16_t *)(handle + offset));
984263bc
MD
199}
200
201static __inline u_int32_t
202bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
203 bus_size_t offset)
204{
984263bc 205 if (tag == I386_BUS_SPACE_IO)
984263bc 206 return (inl(handle + offset));
984263bc 207 return (*(volatile u_int32_t *)(handle + offset));
984263bc
MD
208}
209
984263bc
MD
210/*
211 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
212 * described by tag/handle/offset and copy into buffer provided.
213 */
214static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
215 bus_space_handle_t bsh,
216 bus_size_t offset, u_int8_t *addr,
217 size_t count);
218
219static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
220 bus_space_handle_t bsh,
221 bus_size_t offset, u_int16_t *addr,
222 size_t count);
223
224static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
225 bus_space_handle_t bsh,
226 bus_size_t offset, u_int32_t *addr,
227 size_t count);
228
229static __inline void
230bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
231 bus_size_t offset, u_int8_t *addr, size_t count)
232{
1f7ab7c9 233 if (tag == I386_BUS_SPACE_IO) {
984263bc 234 insb(bsh + offset, addr, count);
1f7ab7c9 235 } else {
984263bc
MD
236 __asm __volatile(" \n\
237 cld \n\
238 1: movb (%2),%%al \n\
239 stosb \n\
240 loop 1b" :
241 "=D" (addr), "=c" (count) :
242 "r" (bsh + offset), "0" (addr), "1" (count) :
243 "%eax", "memory");
244 }
984263bc
MD
245}
246
247static __inline void
248bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
249 bus_size_t offset, u_int16_t *addr, size_t count)
250{
1f7ab7c9 251 if (tag == I386_BUS_SPACE_IO) {
984263bc 252 insw(bsh + offset, addr, count);
1f7ab7c9 253 } else {
984263bc
MD
254 __asm __volatile(" \n\
255 cld \n\
256 1: movw (%2),%%ax \n\
257 stosw \n\
258 loop 1b" :
259 "=D" (addr), "=c" (count) :
260 "r" (bsh + offset), "0" (addr), "1" (count) :
261 "%eax", "memory");
262 }
984263bc
MD
263}
264
265static __inline void
266bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
267 bus_size_t offset, u_int32_t *addr, size_t count)
268{
1f7ab7c9 269 if (tag == I386_BUS_SPACE_IO) {
984263bc 270 insl(bsh + offset, addr, count);
1f7ab7c9 271 } else {
984263bc
MD
272 __asm __volatile(" \n\
273 cld \n\
274 1: movl (%2),%%eax \n\
275 stosl \n\
276 loop 1b" :
277 "=D" (addr), "=c" (count) :
278 "r" (bsh + offset), "0" (addr), "1" (count) :
279 "%eax", "memory");
280 }
984263bc
MD
281}
282
984263bc
MD
283/*
284 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
285 * described by tag/handle and starting at `offset' and copy into
286 * buffer provided.
287 */
288static __inline void bus_space_read_region_1(bus_space_tag_t tag,
289 bus_space_handle_t bsh,
290 bus_size_t offset, u_int8_t *addr,
291 size_t count);
292
293static __inline void bus_space_read_region_2(bus_space_tag_t tag,
294 bus_space_handle_t bsh,
295 bus_size_t offset, u_int16_t *addr,
296 size_t count);
297
298static __inline void bus_space_read_region_4(bus_space_tag_t tag,
299 bus_space_handle_t bsh,
300 bus_size_t offset, u_int32_t *addr,
301 size_t count);
302
303
304static __inline void
305bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
306 bus_size_t offset, u_int8_t *addr, size_t count)
307{
1f7ab7c9 308 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
309 int _port_ = bsh + offset; \
310 __asm __volatile(" \n\
311 cld \n\
312 1: inb %w2,%%al \n\
313 stosb \n\
314 incl %2 \n\
315 loop 1b" :
316 "=D" (addr), "=c" (count), "=d" (_port_) :
317 "0" (addr), "1" (count), "2" (_port_) :
318 "%eax", "memory", "cc");
1f7ab7c9 319 } else {
984263bc
MD
320 int _port_ = bsh + offset; \
321 __asm __volatile(" \n\
322 cld \n\
323 repne \n\
324 movsb" :
325 "=D" (addr), "=c" (count), "=S" (_port_) :
326 "0" (addr), "1" (count), "2" (_port_) :
327 "memory", "cc");
328 }
984263bc
MD
329}
330
331static __inline void
332bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
333 bus_size_t offset, u_int16_t *addr, size_t count)
334{
1f7ab7c9 335 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
336 int _port_ = bsh + offset; \
337 __asm __volatile(" \n\
338 cld \n\
339 1: inw %w2,%%ax \n\
340 stosw \n\
341 addl $2,%2 \n\
342 loop 1b" :
343 "=D" (addr), "=c" (count), "=d" (_port_) :
344 "0" (addr), "1" (count), "2" (_port_) :
345 "%eax", "memory", "cc");
1f7ab7c9 346 } else {
984263bc
MD
347 int _port_ = bsh + offset; \
348 __asm __volatile(" \n\
349 cld \n\
350 repne \n\
351 movsw" :
352 "=D" (addr), "=c" (count), "=S" (_port_) :
353 "0" (addr), "1" (count), "2" (_port_) :
354 "memory", "cc");
355 }
984263bc
MD
356}
357
358static __inline void
359bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
360 bus_size_t offset, u_int32_t *addr, size_t count)
361{
1f7ab7c9 362 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
363 int _port_ = bsh + offset; \
364 __asm __volatile(" \n\
365 cld \n\
366 1: inl %w2,%%eax \n\
367 stosl \n\
368 addl $4,%2 \n\
369 loop 1b" :
370 "=D" (addr), "=c" (count), "=d" (_port_) :
371 "0" (addr), "1" (count), "2" (_port_) :
372 "%eax", "memory", "cc");
1f7ab7c9 373 } else {
984263bc
MD
374 int _port_ = bsh + offset; \
375 __asm __volatile(" \n\
376 cld \n\
377 repne \n\
378 movsl" :
379 "=D" (addr), "=c" (count), "=S" (_port_) :
380 "0" (addr), "1" (count), "2" (_port_) :
381 "memory", "cc");
382 }
984263bc
MD
383}
384
984263bc
MD
385/*
386 * Write the 1, 2, 4, or 8 byte value `value' to bus space
387 * described by tag/handle/offset.
388 */
389
390static __inline void bus_space_write_1(bus_space_tag_t tag,
391 bus_space_handle_t bsh,
392 bus_size_t offset, u_int8_t value);
393
394static __inline void bus_space_write_2(bus_space_tag_t tag,
395 bus_space_handle_t bsh,
396 bus_size_t offset, u_int16_t value);
397
398static __inline void bus_space_write_4(bus_space_tag_t tag,
399 bus_space_handle_t bsh,
400 bus_size_t offset, u_int32_t value);
401
402static __inline void
403bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
404 bus_size_t offset, u_int8_t value)
405{
984263bc 406 if (tag == I386_BUS_SPACE_IO)
984263bc 407 outb(bsh + offset, value);
984263bc 408 else
984263bc 409 *(volatile u_int8_t *)(bsh + offset) = value;
984263bc
MD
410}
411
412static __inline void
413bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
414 bus_size_t offset, u_int16_t value)
415{
984263bc 416 if (tag == I386_BUS_SPACE_IO)
984263bc 417 outw(bsh + offset, value);
984263bc 418 else
984263bc 419 *(volatile u_int16_t *)(bsh + offset) = value;
984263bc
MD
420}
421
422static __inline void
423bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
424 bus_size_t offset, u_int32_t value)
425{
984263bc 426 if (tag == I386_BUS_SPACE_IO)
984263bc 427 outl(bsh + offset, value);
984263bc 428 else
984263bc 429 *(volatile u_int32_t *)(bsh + offset) = value;
984263bc
MD
430}
431
984263bc
MD
432/*
433 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
434 * provided to bus space described by tag/handle/offset.
435 */
436
437static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
438 bus_space_handle_t bsh,
439 bus_size_t offset,
440 const u_int8_t *addr,
441 size_t count);
442static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
443 bus_space_handle_t bsh,
444 bus_size_t offset,
445 const u_int16_t *addr,
446 size_t count);
447
448static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
449 bus_space_handle_t bsh,
450 bus_size_t offset,
451 const u_int32_t *addr,
452 size_t count);
453
454static __inline void
455bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
456 bus_size_t offset, const u_int8_t *addr, size_t count)
457{
1f7ab7c9 458 if (tag == I386_BUS_SPACE_IO) {
984263bc 459 outsb(bsh + offset, addr, count);
1f7ab7c9 460 } else {
984263bc
MD
461 __asm __volatile(" \n\
462 cld \n\
463 1: lodsb \n\
464 movb %%al,(%2) \n\
465 loop 1b" :
466 "=S" (addr), "=c" (count) :
467 "r" (bsh + offset), "0" (addr), "1" (count) :
468 "%eax", "memory", "cc");
469 }
984263bc
MD
470}
471
472static __inline void
473bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
474 bus_size_t offset, const u_int16_t *addr, size_t count)
475{
1f7ab7c9 476 if (tag == I386_BUS_SPACE_IO) {
984263bc 477 outsw(bsh + offset, addr, count);
1f7ab7c9 478 } else {
984263bc
MD
479 __asm __volatile(" \n\
480 cld \n\
481 1: lodsw \n\
482 movw %%ax,(%2) \n\
483 loop 1b" :
484 "=S" (addr), "=c" (count) :
485 "r" (bsh + offset), "0" (addr), "1" (count) :
486 "%eax", "memory", "cc");
487 }
984263bc
MD
488}
489
490static __inline void
491bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
492 bus_size_t offset, const u_int32_t *addr, size_t count)
493{
1f7ab7c9 494 if (tag == I386_BUS_SPACE_IO) {
984263bc 495 outsl(bsh + offset, addr, count);
1f7ab7c9 496 } else {
984263bc
MD
497 __asm __volatile(" \n\
498 cld \n\
499 1: lodsl \n\
500 movl %%eax,(%2) \n\
501 loop 1b" :
502 "=S" (addr), "=c" (count) :
503 "r" (bsh + offset), "0" (addr), "1" (count) :
504 "%eax", "memory", "cc");
505 }
984263bc
MD
506}
507
984263bc
MD
508/*
509 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
510 * to bus space described by tag/handle starting at `offset'.
511 */
512
513static __inline void bus_space_write_region_1(bus_space_tag_t tag,
514 bus_space_handle_t bsh,
515 bus_size_t offset,
516 const u_int8_t *addr,
517 size_t count);
518static __inline void bus_space_write_region_2(bus_space_tag_t tag,
519 bus_space_handle_t bsh,
520 bus_size_t offset,
521 const u_int16_t *addr,
522 size_t count);
523static __inline void bus_space_write_region_4(bus_space_tag_t tag,
524 bus_space_handle_t bsh,
525 bus_size_t offset,
526 const u_int32_t *addr,
527 size_t count);
528
529static __inline void
530bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
531 bus_size_t offset, const u_int8_t *addr, size_t count)
532{
1f7ab7c9 533 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
534 int _port_ = bsh + offset; \
535 __asm __volatile(" \n\
536 cld \n\
537 1: lodsb \n\
538 outb %%al,%w0 \n\
539 incl %0 \n\
540 loop 1b" :
541 "=d" (_port_), "=S" (addr), "=c" (count) :
542 "0" (_port_), "1" (addr), "2" (count) :
543 "%eax", "memory", "cc");
1f7ab7c9 544 } else {
984263bc
MD
545 int _port_ = bsh + offset; \
546 __asm __volatile(" \n\
547 cld \n\
548 repne \n\
549 movsb" :
550 "=D" (_port_), "=S" (addr), "=c" (count) :
551 "0" (_port_), "1" (addr), "2" (count) :
552 "memory", "cc");
553 }
984263bc
MD
554}
555
556static __inline void
557bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
558 bus_size_t offset, const u_int16_t *addr, size_t count)
559{
1f7ab7c9 560 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
561 int _port_ = bsh + offset; \
562 __asm __volatile(" \n\
563 cld \n\
564 1: lodsw \n\
565 outw %%ax,%w0 \n\
566 addl $2,%0 \n\
567 loop 1b" :
568 "=d" (_port_), "=S" (addr), "=c" (count) :
569 "0" (_port_), "1" (addr), "2" (count) :
570 "%eax", "memory", "cc");
1f7ab7c9 571 } else {
984263bc
MD
572 int _port_ = bsh + offset; \
573 __asm __volatile(" \n\
574 cld \n\
575 repne \n\
576 movsw" :
577 "=D" (_port_), "=S" (addr), "=c" (count) :
578 "0" (_port_), "1" (addr), "2" (count) :
579 "memory", "cc");
580 }
984263bc
MD
581}
582
583static __inline void
584bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
585 bus_size_t offset, const u_int32_t *addr, size_t count)
586{
1f7ab7c9 587 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
588 int _port_ = bsh + offset; \
589 __asm __volatile(" \n\
590 cld \n\
591 1: lodsl \n\
592 outl %%eax,%w0 \n\
593 addl $4,%0 \n\
594 loop 1b" :
595 "=d" (_port_), "=S" (addr), "=c" (count) :
596 "0" (_port_), "1" (addr), "2" (count) :
597 "%eax", "memory", "cc");
1f7ab7c9 598 } else {
984263bc
MD
599 int _port_ = bsh + offset; \
600 __asm __volatile(" \n\
601 cld \n\
602 repne \n\
603 movsl" :
604 "=D" (_port_), "=S" (addr), "=c" (count) :
605 "0" (_port_), "1" (addr), "2" (count) :
606 "memory", "cc");
607 }
984263bc
MD
608}
609
984263bc
MD
610/*
611 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
612 * by tag/handle/offset `count' times.
613 */
614
615static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
616 bus_space_handle_t bsh,
617 bus_size_t offset,
618 u_int8_t value, size_t count);
619static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
620 bus_space_handle_t bsh,
621 bus_size_t offset,
622 u_int16_t value, size_t count);
623static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
624 bus_space_handle_t bsh,
625 bus_size_t offset,
626 u_int32_t value, size_t count);
627
628static __inline void
629bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
630 bus_size_t offset, u_int8_t value, size_t count)
631{
6ef943a3 632 bus_space_handle_t addr = bsh + offset;
984263bc 633
1f7ab7c9 634 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
635 while (count--)
636 outb(addr, value);
1f7ab7c9 637 } else {
984263bc
MD
638 while (count--)
639 *(volatile u_int8_t *)(addr) = value;
1f7ab7c9 640 }
984263bc
MD
641}
642
643static __inline void
644bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
645 bus_size_t offset, u_int16_t value, size_t count)
646{
6ef943a3 647 bus_space_handle_t addr = bsh + offset;
984263bc 648
1f7ab7c9 649 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
650 while (count--)
651 outw(addr, value);
1f7ab7c9 652 } else {
984263bc
MD
653 while (count--)
654 *(volatile u_int16_t *)(addr) = value;
1f7ab7c9 655 }
984263bc
MD
656}
657
658static __inline void
659bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
660 bus_size_t offset, u_int32_t value, size_t count)
661{
6ef943a3 662 bus_space_handle_t addr = bsh + offset;
984263bc 663
1f7ab7c9 664 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
665 while (count--)
666 outl(addr, value);
1f7ab7c9 667 } else {
984263bc
MD
668 while (count--)
669 *(volatile u_int32_t *)(addr) = value;
1f7ab7c9 670 }
984263bc
MD
671}
672
984263bc
MD
673/*
674 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
675 * by tag/handle starting at `offset'.
676 */
677
678static __inline void bus_space_set_region_1(bus_space_tag_t tag,
679 bus_space_handle_t bsh,
680 bus_size_t offset, u_int8_t value,
681 size_t count);
682static __inline void bus_space_set_region_2(bus_space_tag_t tag,
683 bus_space_handle_t bsh,
684 bus_size_t offset, u_int16_t value,
685 size_t count);
686static __inline void bus_space_set_region_4(bus_space_tag_t tag,
687 bus_space_handle_t bsh,
688 bus_size_t offset, u_int32_t value,
689 size_t count);
690
691static __inline void
692bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
693 bus_size_t offset, u_int8_t value, size_t count)
694{
6ef943a3 695 bus_space_handle_t addr = bsh + offset;
984263bc 696
1f7ab7c9 697 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
698 for (; count != 0; count--, addr++)
699 outb(addr, value);
1f7ab7c9 700 } else {
984263bc
MD
701 for (; count != 0; count--, addr++)
702 *(volatile u_int8_t *)(addr) = value;
1f7ab7c9 703 }
984263bc
MD
704}
705
706static __inline void
707bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
708 bus_size_t offset, u_int16_t value, size_t count)
709{
6ef943a3 710 bus_space_handle_t addr = bsh + offset;
984263bc 711
1f7ab7c9 712 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
713 for (; count != 0; count--, addr += 2)
714 outw(addr, value);
1f7ab7c9 715 } else {
984263bc
MD
716 for (; count != 0; count--, addr += 2)
717 *(volatile u_int16_t *)(addr) = value;
1f7ab7c9 718 }
984263bc
MD
719}
720
721static __inline void
722bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
723 bus_size_t offset, u_int32_t value, size_t count)
724{
6ef943a3 725 bus_space_handle_t addr = bsh + offset;
984263bc 726
1f7ab7c9 727 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
728 for (; count != 0; count--, addr += 4)
729 outl(addr, value);
1f7ab7c9 730 } else {
984263bc
MD
731 for (; count != 0; count--, addr += 4)
732 *(volatile u_int32_t *)(addr) = value;
1f7ab7c9 733 }
984263bc
MD
734}
735
984263bc
MD
736/*
737 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
738 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
739 */
740
741static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
742 bus_space_handle_t bsh1,
743 bus_size_t off1,
744 bus_space_handle_t bsh2,
745 bus_size_t off2, size_t count);
746
747static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
748 bus_space_handle_t bsh1,
749 bus_size_t off1,
750 bus_space_handle_t bsh2,
751 bus_size_t off2, size_t count);
752
753static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
754 bus_space_handle_t bsh1,
755 bus_size_t off1,
756 bus_space_handle_t bsh2,
757 bus_size_t off2, size_t count);
758
759static __inline void
760bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
761 bus_size_t off1, bus_space_handle_t bsh2,
762 bus_size_t off2, size_t count)
763{
6ef943a3
MD
764 bus_space_handle_t addr1 = bsh1 + off1;
765 bus_space_handle_t addr2 = bsh2 + off2;
984263bc 766
1f7ab7c9 767 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
768 if (addr1 >= addr2) {
769 /* src after dest: copy forward */
770 for (; count != 0; count--, addr1++, addr2++)
771 outb(addr2, inb(addr1));
772 } else {
773 /* dest after src: copy backwards */
774 for (addr1 += (count - 1), addr2 += (count - 1);
775 count != 0; count--, addr1--, addr2--)
776 outb(addr2, inb(addr1));
777 }
1f7ab7c9 778 } else {
984263bc
MD
779 if (addr1 >= addr2) {
780 /* src after dest: copy forward */
781 for (; count != 0; count--, addr1++, addr2++)
782 *(volatile u_int8_t *)(addr2) =
783 *(volatile u_int8_t *)(addr1);
784 } else {
785 /* dest after src: copy backwards */
786 for (addr1 += (count - 1), addr2 += (count - 1);
787 count != 0; count--, addr1--, addr2--)
788 *(volatile u_int8_t *)(addr2) =
789 *(volatile u_int8_t *)(addr1);
790 }
791 }
984263bc
MD
792}
793
794static __inline void
795bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
796 bus_size_t off1, bus_space_handle_t bsh2,
797 bus_size_t off2, size_t count)
798{
6ef943a3
MD
799 bus_space_handle_t addr1 = bsh1 + off1;
800 bus_space_handle_t addr2 = bsh2 + off2;
984263bc 801
1f7ab7c9 802 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
803 if (addr1 >= addr2) {
804 /* src after dest: copy forward */
805 for (; count != 0; count--, addr1 += 2, addr2 += 2)
806 outw(addr2, inw(addr1));
807 } else {
808 /* dest after src: copy backwards */
809 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
810 count != 0; count--, addr1 -= 2, addr2 -= 2)
811 outw(addr2, inw(addr1));
812 }
1f7ab7c9 813 } else {
984263bc
MD
814 if (addr1 >= addr2) {
815 /* src after dest: copy forward */
816 for (; count != 0; count--, addr1 += 2, addr2 += 2)
817 *(volatile u_int16_t *)(addr2) =
818 *(volatile u_int16_t *)(addr1);
819 } else {
820 /* dest after src: copy backwards */
821 for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
822 count != 0; count--, addr1 -= 2, addr2 -= 2)
823 *(volatile u_int16_t *)(addr2) =
824 *(volatile u_int16_t *)(addr1);
825 }
826 }
984263bc
MD
827}
828
829static __inline void
830bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
831 bus_size_t off1, bus_space_handle_t bsh2,
832 bus_size_t off2, size_t count)
833{
6ef943a3
MD
834 bus_space_handle_t addr1 = bsh1 + off1;
835 bus_space_handle_t addr2 = bsh2 + off2;
984263bc 836
1f7ab7c9 837 if (tag == I386_BUS_SPACE_IO) {
984263bc
MD
838 if (addr1 >= addr2) {
839 /* src after dest: copy forward */
840 for (; count != 0; count--, addr1 += 4, addr2 += 4)
841 outl(addr2, inl(addr1));
842 } else {
843 /* dest after src: copy backwards */
844 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
845 count != 0; count--, addr1 -= 4, addr2 -= 4)
846 outl(addr2, inl(addr1));
847 }
1f7ab7c9 848 } else {
984263bc
MD
849 if (addr1 >= addr2) {
850 /* src after dest: copy forward */
851 for (; count != 0; count--, addr1 += 4, addr2 += 4)
852 *(volatile u_int32_t *)(addr2) =
853 *(volatile u_int32_t *)(addr1);
854 } else {
855 /* dest after src: copy backwards */
856 for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
857 count != 0; count--, addr1 -= 4, addr2 -= 4)
858 *(volatile u_int32_t *)(addr2) =
859 *(volatile u_int32_t *)(addr1);
860 }
861 }
984263bc
MD
862}
863
984263bc
MD
864/*
865 * Bus read/write barrier methods.
866 *
867 * void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
868 * bus_size_t offset, bus_size_t len, int flags);
869 *
fef0fdf2
MD
870 * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
871 * prevent reordering by the compiler; all Intel x86 processors currently
872 * retire operations outside the CPU in program order.
984263bc 873 */
984263bc
MD
874#define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
875#define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
876
fef0fdf2 877static __inline void
1a5be628
MD
878bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
879 bus_size_t offset __unused, bus_size_t len __unused, int flags)
fef0fdf2
MD
880{
881 if (flags & BUS_SPACE_BARRIER_READ)
59894250 882 __asm __volatile("lock; addl $0,0(%%esp)" : : : "memory");
fef0fdf2
MD
883 else
884 __asm __volatile("" : : : "memory");
885}
886
f8334305 887#endif /* _MACHINE_BUS_AT386_H_ */