4 * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc.
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.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
41 * Copyright (c) 1996 Charles M. Hannum. All rights reserved.
42 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
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
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.
74 #include <sys/systm.h>
76 #include <machine/cpufunc.h>
77 #include <machine/vmparam.h>
79 #ifdef BUS_SPACE_DEBUG
81 * Macros for sanity-checking the aligned-ness of pointers passed to
82 * bus space ops. These are not strictly necessary on the x86, but
83 * could lead to performance improvements, and help catch problems
84 * with drivers that would creep up on other architectures.
86 #define __BUS_SPACE_ALIGNED_ADDRESS(p, t) \
87 ((((u_long)(p)) & (sizeof(t)-1)) == 0)
89 #define __BUS_SPACE_ADDRESS_SANITY(p, t, d) \
91 if (__BUS_SPACE_ALIGNED_ADDRESS((p), t) == 0) { \
92 printf("%s 0x%lx not aligned to %d bytes %s:%d\n", \
93 d, (u_long)(p), sizeof(t), __FILE__, __LINE__); \
98 #define BUS_SPACE_ALIGNED_POINTER(p, t) __BUS_SPACE_ALIGNED_ADDRESS(p, t)
100 #define __BUS_SPACE_ADDRESS_SANITY(p,t,d) (void) 0
101 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
102 #endif /* BUS_SPACE_DEBUG */
105 * bus_space_map flags
108 #define BUS_SPACE_MAP_CACHEABLE 0x01
109 #define BUS_SPACE_MAP_LINEAR 0x02
110 #define BUS_SPACE_MAP_PREFETCHABLE 0x04
113 * Derived from x86 implementation, ia64 has both i/o and mem spaces
114 * These values are for bus space tag.
116 #define IA64_BUS_SPACE_IO 0 /* space is i/o space */
117 #define IA64_BUS_SPACE_MEM 1 /* space is mem space */
119 #define __BUS_SPACE_HAS_STREAM_METHODS 1
122 * Bus address and size types
124 typedef u_long bus_addr_t
;
125 typedef u_long bus_size_t
;
128 * Access methods for bus resources and address space.
130 typedef int bus_space_tag_t
;
131 typedef u_long bus_space_handle_t
;
135 int ia64_bus_space_map(bus_space_tag_t
, bus_addr_t
,
136 bus_size_t
, int, bus_space_handle_t
*);
137 void ia64_bus_space_unmap(bus_space_tag_t
, bus_space_handle_t
,
139 int ia64_bus_space_subregion(bus_space_tag_t
, bus_space_handle_t
,
140 bus_size_t
, bus_size_t
, bus_space_handle_t
*);
141 #define bus_space_map(t, a, s, f, hp) \
142 ia64_bus_space_map((t), (a), (s), (f), (hp))
143 #define bus_space_unmap(t, h, s) \
144 ia64_bus_space_unmap((t), (h), (s))
145 #define bus_space_subregion(t, h, o, s, nhp) \
146 ia64_bus_space_subregion((t), (h), (o), (s), (nhp))
150 #define bus_space_vaddr(t, h) \
151 ((t) == IA64_BUS_SPACE_MEM ? (void *)(h) : (void *)0)
153 /* map to user space */
155 paddr_t
ia64_bus_space_mmap(bus_space_tag_t
, bus_addr_t
, off_t
, int, int);
157 #define bus_space_mmap(t, b, o, p, f) \
158 ia64_bus_space_mmap((t), (b), (o), (p), (f))
162 int ia64_bus_space_alloc(bus_space_tag_t
, bus_addr_t
, bus_addr_t
,
163 bus_size_t
, bus_size_t
, bus_size_t
, int, bus_addr_t
*,
164 bus_space_handle_t
*);
165 void ia64_bus_space_free(bus_space_tag_t
, bus_space_handle_t
, bus_size_t
);
167 #define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp) \
168 ia64_bus_space__alloc((t), (rs), (re), (s), (a), (b), (f), (ap), (hp))
169 #define bus_space_free(t, h, s) \
170 ia64_bus_space_free((t), (h), (s))
173 * uintN_t bus_space_read_N(bus_space_tag_t tag,
174 * bus_space_handle_t bsh, bus_size_t offset);
176 * Read a 1, 2, 4, or 8 byte quantity from bus space
177 * described by tag/handle/offset.
180 #define bus_space_read_1(t, h, o) \
181 ((t) == IA64_BUS_SPACE_IO ? (inb((h) + (o))) :\
182 (*(volatile uint8_t *)((h) + (o))))
184 #define bus_space_read_2(t, h, o) \
185 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"), \
186 ((t) == IA64_BUS_SPACE_IO ? (inw((h) + (o))) : \
187 (*(volatile uint16_t *)((h) + (o)))))
189 #define bus_space_read_4(t, h, o) \
190 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"), \
191 ((t) == IA64_BUS_SPACE_IO ? (inl((h) + (o))) : \
192 (*(volatile uint32_t *)((h) + (o)))))
194 #define bus_space_read_8(t, h, o) \
195 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"), \
196 ((t) == IA64_BUS_SPACE_IO ? \
197 ({ printf("%s: can't read 8bytes from I/O space\n", __FUNCTION__); 0;}) : \
198 (*(volatile uint64_t *)((h) + (o)))))
200 #define bus_space_read_stream_1 bus_space_read_1
201 #define bus_space_read_stream_2 bus_space_read_2
202 #define bus_space_read_stream_4 bus_space_read_4
203 #define bus_space_read_stream_8 bus_space_read_8
206 * void bus_space_read_multi_N(bus_space_tag_t tag,
207 * bus_space_handle_t bsh, bus_size_t offset,
208 * uintN_t *addr, size_t count);
210 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
211 * described by tag/handle/offset and copy into buffer provided.
214 #define bus_space_read_multi_1(t, h, o, ptr, cnt) \
216 if ((t) == IA64_BUS_SPACE_IO) { \
217 insb((h) + (o), (ptr), (cnt)); \
220 volatile uint8_t *__p = (uint8_t *)((h) + (o)); \
221 uint8_t *__dst = (ptr); \
222 for (__i = 0; __i < (cnt); __i++) \
225 } while (/* CONSTCOND */ 0)
227 #define bus_space_read_multi_2(t, h, o, ptr, cnt) \
229 __BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer"); \
230 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \
231 if ((t) == IA64_BUS_SPACE_IO) { \
232 insw((h) + (o), (ptr), (cnt)); \
235 volatile uint16_t *__p = (uint16_t *)((h) + (o)); \
236 uint16_t *__dst = (ptr); \
237 for (__i = 0; __i < (cnt); __i++) \
240 } while (/* CONSTCOND */ 0)
242 #define bus_space_read_multi_4(t, h, o, ptr, cnt) \
244 __BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer"); \
245 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \
246 if ((t) == IA64_BUS_SPACE_IO) { \
247 insl((h) + (o), (ptr), (cnt)); \
250 volatile uint32_t *__p = (uint32_t *)((h) + (o)); \
251 uint32_t *__dst = (ptr); \
252 for (__i = 0; __i < (cnt); __i++) \
255 } while (/* CONSTCOND */ 0)
257 #define bus_space_read_multi_8(t, h, o, ptr, cnt) \
259 __BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer"); \
260 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \
261 if ((t) == IA64_BUS_SPACE_IO) { \
262 printf("%s: can't read 8bytes from I/O space\n", \
266 volatile uint64_t *__p = (uint64_t *)((h) + (o)); \
267 uint64_t *__dst = (ptr); \
268 for (__i = 0; __i < (cnt); __i++) \
271 } while (/* CONSTCOND */ 0)
273 #define bus_space_read_multi_stream_1 bus_space_read_multi_1
274 #define bus_space_read_multi_stream_2 bus_space_read_multi_2
275 #define bus_space_read_multi_stream_4 bus_space_read_multi_4
276 #define bus_space_read_multi_stream_8 bus_space_read_multi_8
280 * void bus_space_read_region_N(bus_space_tag_t tag,
281 * bus_space_handle_t bsh, bus_size_t offset,
282 * uintN_t *addr, size_t count);
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
289 #define bus_space_read_region_1(t, h, o, ptr, cnt) \
291 if ((t) == IA64_BUS_SPACE_IO) { \
293 volatile bus_addr_t __port = (h) + (o); \
294 uint8_t *__dst = (ptr); \
295 for (__i = 0; __i < (cnt); __i++) { \
296 *__dst++ = inb(__port); \
301 volatile uint8_t *__p = (uint8_t *)((h) + (o)); \
302 uint8_t *__dst = (ptr); \
303 for (__i = 0; __i < (cnt); __i++) \
306 } while (/* CONSTCOND */ 0)
308 #define bus_space_read_region_2(t, h, o, ptr, cnt) \
310 __BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer"); \
311 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \
312 if ((t) == IA64_BUS_SPACE_IO) { \
314 volatile bus_addr_t __port = (h) + (o); \
315 uint8_t *__dst = (ptr); \
316 for (__i = 0; __i < (cnt); __i++) { \
317 *__dst++ = inb(__port); \
322 volatile uint16_t *__p = (uint16_t *)((h) + (o)); \
323 uint16_t *__dst = (ptr); \
324 for (__i = 0; __i < (cnt); __i++) \
327 } while (/* CONSTCOND */ 0)
329 #define bus_space_read_region_4(t, h, o, ptr, cnt) \
331 __BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer"); \
332 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \
333 if ((t) == IA64_BUS_SPACE_IO) { \
335 volatile bus_addr_t __port = (h) + (o); \
336 uint8_t *__dst = (ptr); \
337 for (__i = 0; __i < (cnt); __i++) { \
338 *__dst++ = inb(__port); \
342 volatile uint32_t *__p = (uint32_t *)((h) + (o)); \
343 uint32_t *__dst = (ptr); \
344 for (__i = 0; __i < (cnt); __i++) \
347 } while (/* CONSTCOND */ 0)
349 #define bus_space_read_region_8(t, h, o, ptr, cnt) \
351 __BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer"); \
352 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \
353 if ((t) == IA64_BUS_SPACE_IO) { \
354 printf("%s: can't read 8bytes from I/O space\n", \
357 volatile uint64_t *__p = (uint64_t *)((h) + (o)); \
358 uint64_t *__dst = (ptr); \
359 for (__i = 0; __i < (cnt); __i++) \
362 } while (/* CONSTCOND */ 0)
364 #define bus_space_read_region_stream_1 bus_space_read_region_1
365 #define bus_space_read_region_stream_2 bus_space_read_region_2
366 #define bus_space_read_region_stream_4 bus_space_read_region_4
367 #define bus_space_read_region_stream_8 bus_space_read_region_8
371 * void bus_space_write_N(bus_space_tag_t tag,
372 * bus_space_handle_t bsh, bus_size_t offset,
375 * Write the 1, 2, 4, or 8 byte value `value' to bus space
376 * described by tag/handle/offset.
379 #define bus_space_write_1(t, h, o, v) \
381 if ((t) == IA64_BUS_SPACE_IO) \
382 outb((h) + (o), (v)); \
384 ((void)(*(volatile uint8_t *)((h) + (o)) = (v))); \
385 } while (/* CONSTCOND */ 0)
387 #define bus_space_write_2(t, h, o, v) \
389 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \
390 if ((t) == IA64_BUS_SPACE_IO) \
391 outw((h) + (o), (v)); \
393 ((void)(*(volatile uint16_t *)((h) + (o)) = (v))); \
394 } while (/* CONSTCOND */ 0)
396 #define bus_space_write_4(t, h, o, v) \
398 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \
399 if ((t) == IA64_BUS_SPACE_IO) \
400 outl((h) + (o), (v)); \
402 ((void)(*(volatile uint32_t *)((h) + (o)) = (v))); \
403 } while (/* CONSTCOND */ 0)
405 #define bus_space_write_8(t, h, o, v) \
406 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \
407 if ((t) == IA64_BUS_SPACE_IO ? \
408 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__); : \
409 (*(volatile uint64_t *)((h) + (o)) = (v)))
411 #define bus_space_write_stream_1 bus_space_write_1
412 #define bus_space_write_stream_2 bus_space_write_2
413 #define bus_space_write_stream_4 bus_space_write_4
414 #define bus_space_write_stream_8 bus_space_write_8
417 * void bus_space_write_multi_N(bus_space_tag_t tag,
418 * bus_space_handle_t bsh, bus_size_t offset,
419 * const uintN_t *addr, size_t count);
421 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
422 * provided to bus space described by tag/handle/offset.
425 #define bus_space_write_multi_1(t, h, o, ptr, cnt) \
427 if ((t) == IA64_BUS_SPACE_IO) { \
428 outsb((h) + (o), (ptr), (cnt)); \
431 volatile uint8_t *__p = (uint8_t *)((h) + (o)); \
432 uint8_t *__src = (ptr); \
433 for (__i = 0; __i < (cnt); __i++) \
436 } while (/* CONSTCOND */ 0)
438 #define bus_space_write_multi_2(t, h, o, ptr, cnt) \
440 __BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer"); \
441 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \
442 if ((t) == IA64_BUS_SPACE_IO) { \
443 outsw((h) + (o), (ptr), (cnt)); \
446 volatile uint16_t *__p = (uint16_t *)((h) + (o)); \
447 uint16_t *__src = (ptr); \
448 for (__i = 0; __i < (cnt); __i++) \
451 } while (/* CONSTCOND */ 0)
453 #define bus_space_write_multi_4(t, h, o, ptr, cnt) \
455 __BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer"); \
456 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \
457 if ((t) == IA64_BUS_SPACE_IO) { \
458 outsl((h) + (o), (ptr), (cnt)); \
461 volatile uint32_t *__p = (uint32_t *)((h) + (o)); \
462 uint32_t *__src = (ptr); \
463 for (__i = 0; __i < (cnt); __i++) \
466 } while (/* CONSTCOND */ 0)
468 #define bus_space_write_multi_8(t, h, o, ptr, cnt) \
470 __BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer"); \
471 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \
472 if ((t) == IA64_BUS_SPACE_IO) { \
473 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__);\
476 volatile uint64_t *__p = (uint64_t *)((h) + (o)); \
477 uint64_t *__src = (ptr); \
478 for (__i = 0; __i < (cnt); __i++) \
481 } while (/* CONSTCOND */ 0)
483 #define bus_space_write_multi_stream_1 bus_space_write_multi_1
484 #define bus_space_write_multi_stream_2 bus_space_write_multi_2
485 #define bus_space_write_multi_stream_4 bus_space_write_multi_4
486 #define bus_space_write_multi_stream_8 bus_space_write_multi_8
490 * void bus_space_write_region_N(bus_space_tag_t tag,
491 * bus_space_handle_t bsh, bus_size_t offset,
492 * const uintN_t *addr, size_t count);
494 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
495 * to bus space described by tag/handle starting at `offset'.
498 #define bus_space_write_region_1(t, h, o, ptr, cnt) \
500 if ((t) == IA64_BUS_SPACE_IO) { \
502 volatile bus_addr_t __port = (h) + (o); \
503 uint8_t *__src = (ptr); \
504 for (__i = 0; __i < (cnt); __i++) { \
505 outb(__port, *__src); \
511 volatile uint8_t *__p = (uint8_t *)((h) + (o)); \
512 uint8_t *__src = (ptr); \
513 for (__i = 0; __i < (cnt); __i++) \
516 } while (/* CONSTCOND */ 0)
518 #define bus_space_write_region_2(t, h, o, ptr, cnt) \
520 __BUS_SPACE_ADDRESS_SANITY((ptr), uint16_t, "buffer"); \
521 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \
522 if ((t) == IA64_BUS_SPACE_IO) { \
524 volatile bus_addr_t __port = (h) + (o); \
525 uint16_t *__src = (ptr); \
526 for (__i = 0; __i < (cnt); __i++) { \
527 outw(__port, *__src); \
533 volatile uint16_t *__p = (uint16_t *)((h) + (o)); \
534 uint16_t *__src = (ptr); \
535 for (__i = 0; __i < (cnt); __i++) \
538 } while (/* CONSTCOND */ 0)
540 #define bus_space_write_region_4(t, h, o, ptr, cnt) \
542 __BUS_SPACE_ADDRESS_SANITY((ptr), uint32_t, "buffer"); \
543 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \
544 if ((t) == IA64_BUS_SPACE_IO) { \
546 volatile bus_addr_t __port = (h) + (o); \
547 uint32_t *__src = (ptr); \
548 for (__i = 0; __i < (cnt); __i++) { \
549 outl(__port, *__src); \
555 volatile uint32_t *__p = (uint32_t *)(h) + (o); \
556 uint32_t *__src = (ptr); \
557 for (__i = 0; __i < (cnt); __i++) \
560 } while (/* CONSTCOND */ 0)
562 #define bus_space_write_region_8(t, h, o, ptr, cnt) \
564 __BUS_SPACE_ADDRESS_SANITY((ptr), uint64_t, "buffer"); \
565 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \
566 if ((t) == IA64_BUS_SPACE_IO) { \
567 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__);\
570 volatile uint64_t *__p = (uint64_t *)((h) + (o)); \
571 uint64_t *__src = (ptr); \
572 for (__i = 0; __i < (cnt); __i++) \
575 } while (/* CONSTCOND */ 0)
577 #define bus_space_write_region_stream_1 bus_space_write_region_1
578 #define bus_space_write_region_stream_2 bus_space_write_region_2
579 #define bus_space_write_region_stream_4 bus_space_write_region_4
580 #define bus_space_write_region_stream_8 bus_space_write_region_8
584 * void bus_space_set_multi_N(bus_space_tag_t tag,
585 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
588 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
589 * by tag/handle/offset `count' times.
592 static __inline
void ia64_bus_space_set_multi_1(bus_space_tag_t
,
593 bus_space_handle_t
, bus_size_t
, uint8_t, size_t);
594 static __inline
void ia64_bus_space_set_multi_2(bus_space_tag_t
,
595 bus_space_handle_t
, bus_size_t
, uint16_t, size_t);
596 static __inline
void ia64_bus_space_set_multi_4(bus_space_tag_t
,
597 bus_space_handle_t
, bus_size_t
, uint32_t, size_t);
598 static __inline
void ia64_bus_space_set_multi_8(bus_space_tag_t
,
599 bus_space_handle_t
, bus_size_t
, uint64_t, size_t);
601 #define bus_space_set_multi_1(t, h, o, v, c) \
602 ia64_bus_space_set_multi_1((t), (h), (o), (v), (c))
604 #define bus_space_set_multi_2(t, h, o, v, c) \
606 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \
607 ia64_bus_space_set_multi_2((t), (h), (o), (v), (c)); \
608 } while (/* CONSTCOND */ 0)
610 #define bus_space_set_multi_4(t, h, o, v, c) \
612 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \
613 ia64_bus_space_set_multi_4((t), (h), (o), (v), (c)); \
614 } while (/* CONSTCOND */ 0)
616 #define bus_space_set_multi_8(t, h, o, v, c) \
618 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \
619 ia64_bus_space_set_multi_8((t), (h), (o), (v), (c)); \
620 } while (/* CONSTCOND */ 0)
623 ia64_bus_space_set_multi_1(bus_space_tag_t t
, bus_space_handle_t h
,
624 bus_size_t o
, uint8_t v
, size_t c
)
626 bus_addr_t addr
= h
+ o
;
628 if (t
== IA64_BUS_SPACE_IO
)
633 *(volatile uint8_t *)(addr
) = v
;
637 ia64_bus_space_set_multi_2(bus_space_tag_t t
, bus_space_handle_t h
,
638 bus_size_t o
, uint16_t v
, size_t c
)
640 bus_addr_t addr
= h
+ o
;
642 if (t
== IA64_BUS_SPACE_IO
)
647 *(volatile uint16_t *)(addr
) = v
;
651 ia64_bus_space_set_multi_4(bus_space_tag_t t
, bus_space_handle_t h
,
652 bus_size_t o
, uint32_t v
, size_t c
)
654 bus_addr_t addr
= h
+ o
;
656 if (t
== IA64_BUS_SPACE_IO
)
661 *(volatile uint32_t *)(addr
) = v
;
665 ia64_bus_space_set_multi_8(bus_space_tag_t t
, bus_space_handle_t h
,
666 bus_size_t o
, uint64_t v
, size_t c
)
668 bus_addr_t addr
= h
+ o
;
670 if (t
== IA64_BUS_SPACE_IO
)
671 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__
);
674 *(volatile uint64_t *)(addr
) = v
;
679 * void bus_space_set_region_N(bus_space_tag_t tag,
680 * bus_space_handle_t bsh, bus_size_t offset, uintN_t val,
683 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
684 * by tag/handle starting at `offset'.
687 static __inline
void ia64_bus_space_set_region_1(bus_space_tag_t
,
688 bus_space_handle_t
, bus_size_t
, uint8_t, size_t);
689 static __inline
void ia64_bus_space_set_region_2(bus_space_tag_t
,
690 bus_space_handle_t
, bus_size_t
, uint16_t, size_t);
691 static __inline
void ia64_bus_space_set_region_4(bus_space_tag_t
,
692 bus_space_handle_t
, bus_size_t
, uint32_t, size_t);
694 #define bus_space_set_region_1(t, h, o, v, c) \
695 ia64_bus_space_set_region_1((t), (h), (o), (v), (c))
697 #define bus_space_set_region_2(t, h, o, v, c) \
699 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint16_t, "bus addr"); \
700 ia64_bus_space_set_region_2((t), (h), (o), (v), (c)); \
701 } while (/* CONSTCOND */ 0)
703 #define bus_space_set_region_4(t, h, o, v, c) \
705 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint32_t, "bus addr"); \
706 ia64_bus_space_set_region_4((t), (h), (o), (v), (c)); \
707 } while (/* CONSTCOND */ 0)
709 #define bus_space_set_region_8(t, h, o, v, c) \
711 __BUS_SPACE_ADDRESS_SANITY((h) + (o), uint64_t, "bus addr"); \
712 ia64_bus_space_set_region_8((t), (h), (o), (v), (c)); \
713 } while (/* CONSTCOND */ 0)
716 ia64_bus_space_set_region_1(bus_space_tag_t t
, bus_space_handle_t h
,
717 bus_size_t o
, uint8_t v
, size_t c
)
719 bus_addr_t addr
= h
+ o
;
721 if (t
== IA64_BUS_SPACE_IO
)
722 for (; c
!= 0; c
--, addr
++)
725 for (; c
!= 0; c
--, addr
++)
726 *(volatile uint8_t *)(addr
) = v
;
730 ia64_bus_space_set_region_2(bus_space_tag_t t
, bus_space_handle_t h
,
731 bus_size_t o
, uint16_t v
, size_t c
)
733 bus_addr_t addr
= h
+ o
;
735 if (t
== IA64_BUS_SPACE_IO
)
736 for (; c
!= 0; c
--, addr
+= 2)
739 for (; c
!= 0; c
--, addr
+= 2)
740 *(volatile uint16_t *)(addr
) = v
;
744 ia64_bus_space_set_region_4(bus_space_tag_t t
, bus_space_handle_t h
,
745 bus_size_t o
, uint32_t v
, size_t c
)
747 bus_addr_t addr
= h
+ o
;
749 if (t
== IA64_BUS_SPACE_IO
)
750 for (; c
!= 0; c
--, addr
+= 4)
753 for (; c
!= 0; c
--, addr
+= 4)
754 *(volatile uint32_t *)(addr
) = v
;
758 ia64_bus_space_set_region_8(bus_space_tag_t t
, bus_space_handle_t h
,
759 bus_size_t o
, uint64_t v
, size_t c
)
761 bus_addr_t addr
= h
+ o
;
763 if (t
== IA64_BUS_SPACE_IO
)
764 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__
);
766 for (; c
!= 0; c
--, addr
+= 8)
767 *(volatile uint32_t *)(addr
) = v
;
772 * void bus_space_copy_region_N(bus_space_tag_t tag,
773 * bus_space_handle_t bsh1, bus_size_t off1,
774 * bus_space_handle_t bsh2, bus_size_t off2,
777 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
778 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
781 static __inline
void ia64_bus_space_copy_region_1(bus_space_tag_t
,
782 bus_space_handle_t
, bus_size_t
, bus_space_handle_t
,
784 static __inline
void ia64_bus_space_copy_region_2(bus_space_tag_t
,
785 bus_space_handle_t
, bus_size_t
, bus_space_handle_t
,
787 static __inline
void ia64_bus_space_copy_region_4(bus_space_tag_t
,
788 bus_space_handle_t
, bus_size_t
, bus_space_handle_t
,
791 #define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \
792 ia64_bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
794 #define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \
796 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint16_t, "bus addr 1"); \
797 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint16_t, "bus addr 2"); \
798 ia64_bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c)); \
799 } while (/* CONSTCOND */ 0)
801 #define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \
803 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint32_t, "bus addr 1"); \
804 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint32_t, "bus addr 2"); \
805 ia64_bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c)); \
806 } while (/* CONSTCOND */ 0)
808 #define bus_space_copy_region_8(t, h1, o1, h2, o2, c) \
810 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), uint64_t, "bus addr 1"); \
811 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), uint64_t, "bus addr 2"); \
812 ia64_bus_space_copy_region_8((t), (h1), (o1), (h2), (o2), (c)); \
813 } while (/* CONSTCOND */ 0)
816 ia64_bus_space_copy_region_1(bus_space_tag_t t
,
817 bus_space_handle_t h1
, bus_size_t o1
,
818 bus_space_handle_t h2
, bus_size_t o2
, size_t c
)
820 bus_addr_t addr1
= h1
+ o1
;
821 bus_addr_t addr2
= h2
+ o2
;
823 if (t
== IA64_BUS_SPACE_IO
) {
824 if (addr1
>= addr2
) {
825 /* src after dest: copy forward */
826 for (; c
!= 0; c
--, addr1
++, addr2
++)
827 outb(addr2
, inb(addr1
));
829 /* dest after src: copy backwards */
830 for (addr1
+= (c
- 1), addr2
+= (c
- 1);
831 c
!= 0; c
--, addr1
--, addr2
--)
832 outb(addr2
, inb(addr1
));
835 if (addr1
>= addr2
) {
836 /* src after dest: copy forward */
837 for (; c
!= 0; c
--, addr1
++, addr2
++)
838 *(volatile uint8_t *)(addr2
) =
839 *(volatile uint8_t *)(addr1
);
841 /* dest after src: copy backwards */
842 for (addr1
+= (c
- 1), addr2
+= (c
- 1);
843 c
!= 0; c
--, addr1
--, addr2
--)
844 *(volatile uint8_t *)(addr2
) =
845 *(volatile uint8_t *)(addr1
);
851 ia64_bus_space_copy_region_2(bus_space_tag_t t
,
852 bus_space_handle_t h1
, bus_size_t o1
,
853 bus_space_handle_t h2
, bus_size_t o2
, size_t c
)
855 bus_addr_t addr1
= h1
+ o1
;
856 bus_addr_t addr2
= h2
+ o2
;
858 if (t
== IA64_BUS_SPACE_IO
) {
859 if (addr1
>= addr2
) {
860 /* src after dest: copy forward */
861 for (; c
!= 0; c
--, addr1
+= 2, addr2
+= 2)
862 outw(addr2
, inw(addr1
));
864 /* dest after src: copy backwards */
865 for (addr1
+= 2 * (c
- 1), addr2
+= 2 * (c
- 1);
866 c
!= 0; c
--, addr1
-= 2, addr2
-= 2)
867 outw(addr2
, inw(addr1
));
870 if (addr1
>= addr2
) {
871 /* src after dest: copy forward */
872 for (; c
!= 0; c
--, addr1
+= 2, addr2
+= 2)
873 *(volatile uint16_t *)(addr2
) =
874 *(volatile uint16_t *)(addr1
);
876 /* dest after src: copy backwards */
877 for (addr1
+= 2 * (c
- 1), addr2
+= 2 * (c
- 1);
878 c
!= 0; c
--, addr1
-= 2, addr2
-= 2)
879 *(volatile uint16_t *)(addr2
) =
880 *(volatile uint16_t *)(addr1
);
886 ia64_bus_space_copy_region_4(bus_space_tag_t t
,
887 bus_space_handle_t h1
, bus_size_t o1
,
888 bus_space_handle_t h2
, bus_size_t o2
, size_t c
)
890 bus_addr_t addr1
= h1
+ o1
;
891 bus_addr_t addr2
= h2
+ o2
;
893 if (t
== IA64_BUS_SPACE_IO
) {
894 if (addr1
>= addr2
) {
895 /* src after dest: copy forward */
896 for (; c
!= 0; c
--, addr1
+= 4, addr2
+= 4)
897 outl(addr2
, inl(addr1
));
899 /* dest after src: copy backwards */
900 for (addr1
+= 4 * (c
- 1), addr2
+= 4 * (c
- 1);
901 c
!= 0; c
--, addr1
-= 4, addr2
-= 4)
902 outl(addr2
, inl(addr1
));
905 if (addr1
>= addr2
) {
906 /* src after dest: copy forward */
907 for (; c
!= 0; c
--, addr1
+= 4, addr2
+= 4)
908 *(volatile uint32_t *)(addr2
) =
909 *(volatile uint32_t *)(addr1
);
911 /* dest after src: copy backwards */
912 for (addr1
+= 4 * (c
- 1), addr2
+= 4 * (c
- 1);
913 c
!= 0; c
--, addr1
-= 4, addr2
-= 4)
914 *(volatile uint32_t *)(addr2
) =
915 *(volatile uint32_t *)(addr1
);
921 ia64_bus_space_copy_region_8(bus_space_tag_t t
,
922 bus_space_handle_t h1
, bus_size_t o1
,
923 bus_space_handle_t h2
, bus_size_t o2
, size_t c
)
925 bus_addr_t addr1
= h1
+ o1
;
926 bus_addr_t addr2
= h2
+ o2
;
928 if (t
== IA64_BUS_SPACE_IO
) {
929 printf("%s: can't write 8bytes to I/O space\n", __FUNCTION__
);
931 if (addr1
>= addr2
) {
932 /* src after dest: copy forward */
933 for (; c
!= 0; c
--, addr1
+= 8, addr2
+= 8)
934 *(volatile uint64_t *)(addr2
) =
935 *(volatile uint64_t *)(addr1
);
937 /* dest after src: copy backwards */
938 for (addr1
+= 8 * (c
- 1), addr2
+= 8 * (c
- 1);
939 c
!= 0; c
--, addr1
-= 8, addr2
-= 8)
940 *(volatile uint64_t *)(addr2
) =
941 *(volatile uint64_t *)(addr1
);
948 * Bus read/write barrier methods.
950 * void bus_space_barrier(bus_space_tag_t tag,
951 * bus_space_handle_t bsh, bus_size_t offset,
952 * bus_size_t len, int flags);
954 * Note: the x86 does not currently require barriers, but we must
955 * provide the flags to MI code.
957 #define bus_space_barrier(t, h, o, l, f) \
958 ia64_bus_space_barrier((t), (h), (o), (l), (f))
961 #define BUS_SPACE_BARRIER_READ 0x01
962 #define BUS_SPACE_BARRIER_WRITE 0x02
964 /* XXX to be investigated: are these used? */
965 #define BUS_SPACE_BARRIER_READ_BEFORE_READ 0x04
966 #define BUS_SPACE_BARRIER_READ_BEFORE_WRITE 0x08
967 #define BUS_SPACE_BARRIER_WRITE_BEFORE_READ 0x10
968 #define BUS_SPACE_BARRIER_WRITE_BEFORE_WRITE 0x20
969 #define BUS_SPACE_BARRIER_SYNC 0x40
972 ia64_bus_space_barrier(bus_space_tag_t t
, bus_space_handle_t handle
,
973 bus_size_t offset
, bus_size_t length
, int flags
)
975 if (t
== IA64_BUS_SPACE_IO
)
979 case BUS_SPACE_BARRIER_READ
:
980 __asm
volatile("mf" ::: "memory");
982 case BUS_SPACE_BARRIER_WRITE
:
983 __asm
volatile("mf" ::: "memory");
985 case BUS_SPACE_BARRIER_READ
| BUS_SPACE_BARRIER_WRITE
:
986 __asm
volatile("mf" ::: "memory");
989 printf("%s: Unknown barrier %d\n", __FUNCTION__
, flags
);
996 * Flags used in various bus DMA methods.
998 #define BUS_DMA_WAITOK 0x000 /* safe to sleep (pseudo-flag) */
999 #define BUS_DMA_NOWAIT 0x001 /* not safe to sleep */
1000 #define BUS_DMA_ALLOCNOW 0x002 /* perform resource allocation now */
1001 #define BUS_DMA_COHERENT 0x004 /* hint: map memory DMA coherent */
1002 #define BUS_DMA_STREAMING 0x008 /* hint: sequential, unidirectional */
1003 #define BUS_DMA_BUS1 0x010 /* placeholders for bus functions... */
1004 #define BUS_DMA_BUS2 0x020
1005 #define BUS_DMA_BUS3 0x040
1006 #define BUS_DMA_BUS4 0x080
1007 #define BUS_DMA_READ 0x100 /* mapping is device -> memory only */
1008 #define BUS_DMA_WRITE 0x200 /* mapping is memory -> device only */
1009 #define BUS_DMA_NOCACHE 0x400 /* hint: map non-cached memory */
1011 /* Forwards needed by prototypes below. */
1016 * Operations performed by bus_dmamap_sync().
1018 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */
1019 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */
1020 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */
1021 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */
1023 typedef struct ia64_bus_dma_tag
*bus_dma_tag_t
;
1024 typedef struct ia64_bus_dmamap
*bus_dmamap_t
;
1026 #define BUS_DMA_TAG_VALID(t) ((t) != (bus_dma_tag_t)0)
1031 * Describes a single contiguous DMA transaction. Values
1032 * are suitable for programming into DMA registers.
1034 struct ia64_bus_dma_segment
{
1035 bus_addr_t ds_addr
; /* DMA address */
1036 bus_size_t ds_len
; /* length of transfer */
1038 typedef struct ia64_bus_dma_segment bus_dma_segment_t
;
1043 * A machine-dependent opaque type describing the implementation of
1044 * DMA for a given bus.
1047 struct ia64_bus_dma_tag
{
1049 * The `bounce threshold' is checked while we are loading
1050 * the DMA map. If the physical address of the segment
1051 * exceeds the threshold, an error will be returned. The
1052 * caller can then take whatever action is necessary to
1053 * bounce the transfer. If this value is 0, it will be
1056 bus_addr_t _bounce_thresh
;
1057 bus_addr_t _bounce_alloc_lo
;
1058 bus_addr_t _bounce_alloc_hi
;
1059 int (*_may_bounce
)(bus_dma_tag_t
, bus_dmamap_t
, int, int *);
1062 * DMA mapping methods.
1064 int (*_dmamap_create
)(bus_dma_tag_t
, bus_size_t
, int,
1065 bus_size_t
, bus_size_t
, int, bus_dmamap_t
*);
1066 void (*_dmamap_destroy
)(bus_dma_tag_t
, bus_dmamap_t
);
1067 int (*_dmamap_load
)(bus_dma_tag_t
, bus_dmamap_t
, void *,
1068 bus_size_t
, struct proc
*, int);
1069 int (*_dmamap_load_mbuf
)(bus_dma_tag_t
, bus_dmamap_t
,
1070 struct mbuf
*, int);
1071 int (*_dmamap_load_uio
)(bus_dma_tag_t
, bus_dmamap_t
,
1073 int (*_dmamap_load_raw
)(bus_dma_tag_t
, bus_dmamap_t
,
1074 bus_dma_segment_t
*, int, bus_size_t
, int);
1075 void (*_dmamap_unload
)(bus_dma_tag_t
, bus_dmamap_t
);
1076 void (*_dmamap_sync
)(bus_dma_tag_t
, bus_dmamap_t
,
1077 bus_addr_t
, bus_size_t
, int);
1080 * DMA memory utility functions.
1082 int (*_dmamem_alloc
)(bus_dma_tag_t
, bus_size_t
, bus_size_t
,
1083 bus_size_t
, bus_dma_segment_t
*, int, int *, int);
1084 void (*_dmamem_free
)(bus_dma_tag_t
, bus_dma_segment_t
*, int);
1085 int (*_dmamem_map
)(bus_dma_tag_t
, bus_dma_segment_t
*,
1086 int, size_t, void **, int);
1087 void (*_dmamem_unmap
)(bus_dma_tag_t
, void *, size_t);
1088 paddr_t (*_dmamem_mmap
)(bus_dma_tag_t
, bus_dma_segment_t
*,
1089 int, off_t
, int, int);
1092 static __inline
void bus_dmamap_sync(bus_dma_tag_t
, bus_dmamap_t
,
1093 bus_addr_t
, bus_size_t
, int) __attribute__((__unused__
));
1095 #define bus_dmamap_create(t, s, n, m, b, f, p) \
1096 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
1097 #define bus_dmamap_destroy(t, p) \
1098 (*(t)->_dmamap_destroy)((t), (p))
1099 #define bus_dmamap_load(t, m, b, s, p, f) \
1100 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
1101 #define bus_dmamap_load_mbuf(t, m, b, f) \
1102 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
1103 #define bus_dmamap_load_uio(t, m, u, f) \
1104 (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
1105 #define bus_dmamap_load_raw(t, m, sg, n, s, f) \
1106 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
1107 #define bus_dmamap_unload(t, p) \
1108 (*(t)->_dmamap_unload)((t), (p))
1109 static __inline
void
1110 bus_dmamap_sync(bus_dma_tag_t t
, bus_dmamap_t p
, bus_addr_t o
, bus_size_t l
,
1113 /* if (ops & BUS_DMASYNC_POSTREAD)
1115 if (t
->_dmamap_sync
)
1116 (*t
->_dmamap_sync
)(t
, p
, o
, l
, ops
);
1119 #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
1120 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
1121 #define bus_dmamem_free(t, sg, n) \
1122 (*(t)->_dmamem_free)((t), (sg), (n))
1123 #define bus_dmamem_map(t, sg, n, s, k, f) \
1124 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
1125 #define bus_dmamem_unmap(t, k, s) \
1126 (*(t)->_dmamem_unmap)((t), (k), (s))
1127 #define bus_dmamem_mmap(t, sg, n, o, p, f) \
1128 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
1133 * Describes a DMA mapping.
1135 struct ia64_bus_dmamap
{
1137 * PRIVATE MEMBERS: not for use by machine-independent code.
1139 bus_size_t _dm_size
; /* largest DMA transfer mappable */
1140 int _dm_segcnt
; /* number of segs this map can map */
1141 bus_size_t _dm_maxmaxsegsz
; /* fixed largest possible segment */
1142 bus_size_t _dm_boundary
; /* don't cross this */
1143 bus_addr_t _dm_bounce_thresh
; /* bounce threshold; see tag */
1144 int _dm_flags
; /* misc. flags */
1146 void *_dm_cookie
; /* cookie for bus-specific functions */
1149 * PUBLIC MEMBERS: these are used by machine-independent code.
1151 bus_size_t dm_maxsegsz
; /* largest possible segment */
1152 bus_size_t dm_mapsize
; /* size of the mapping */
1153 int dm_nsegs
; /* # valid segments in mapping */
1154 bus_dma_segment_t dm_segs
[1]; /* segments; variable length */
1157 #endif /* _IA64_BUS_H_ */