bus.h revision 1.13 1 /* $NetBSD: bus.h,v 1.13 2000/06/04 18:27:39 ragge Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1997, 1998 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
71 #ifndef _VAX_BUS_H_
72 #define _VAX_BUS_H_
73
74 #ifdef BUS_SPACE_DEBUG
75 #include <sys/systm.h> /* for printf() prototype */
76 /*
77 * Macros for sanity-checking the aligned-ness of pointers passed to
78 * bus space ops. These are not strictly necessary on the VAX, but
79 * could lead to performance improvements, and help catch problems
80 * with drivers that would creep up on other architectures.
81 */
82 #define __BUS_SPACE_ALIGNED_ADDRESS(p, t) \
83 ((((u_long)(p)) & (sizeof(t)-1)) == 0)
84
85 #define __BUS_SPACE_ADDRESS_SANITY(p, t, d) \
86 ({ \
87 if (__BUS_SPACE_ALIGNED_ADDRESS((p), t) == 0) { \
88 printf("%s 0x%lx not aligned to %d bytes %s:%d\n", \
89 d, (u_long)(p), sizeof(t), __FILE__, __LINE__); \
90 } \
91 (void) 0; \
92 })
93
94 #define BUS_SPACE_ALIGNED_POINTER(p, t) __BUS_SPACE_ALIGNED_ADDRESS(p, t)
95 #else
96 #define __BUS_SPACE_ADDRESS_SANITY(p,t,d) (void) 0
97 #define BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
98 #endif /* BUS_SPACE_DEBUG */
99
100 /*
101 * Bus address and size types
102 */
103 typedef u_long bus_addr_t;
104 typedef u_long bus_size_t;
105
106 /*
107 * Access methods for bus resources and address space.
108 */
109 typedef struct vax_bus_space *bus_space_tag_t;
110 typedef u_long bus_space_handle_t;
111
112 struct vax_bus_space {
113 /* cookie */
114 void *vbs_cookie;
115
116 /* mapping/unmapping */
117 int (*vbs_map) __P((void *, bus_addr_t, bus_size_t,
118 int, bus_space_handle_t *, int));
119 void (*vbs_unmap) __P((void *, bus_space_handle_t,
120 bus_size_t, int));
121 int (*vbs_subregion) __P((void *, bus_space_handle_t,
122 bus_size_t, bus_size_t, bus_space_handle_t *));
123
124 /* allocation/deallocation */
125 int (*vbs_alloc) __P((void *, bus_addr_t, bus_addr_t,
126 bus_size_t, bus_size_t, bus_size_t, int,
127 bus_addr_t *, bus_space_handle_t *));
128 void (*vbs_free) __P((void *, bus_space_handle_t,
129 bus_size_t));
130 };
131
132 /*
133 * int bus_space_map __P((bus_space_tag_t t, bus_addr_t addr,
134 * bus_size_t size, int flags, bus_space_handle_t *bshp));
135 *
136 * Map a region of bus space.
137 */
138
139 #define BUS_SPACE_MAP_CACHEABLE 0x01
140 #define BUS_SPACE_MAP_LINEAR 0x02
141 #define BUS_SPACE_MAP_PREFETCHABLE 0x04
142
143 #define bus_space_map(t, a, s, f, hp) \
144 (*(t)->vbs_map)((t)->vbs_cookie, (a), (s), (f), (hp), 1)
145 #define vax_bus_space_map_noacct(t, a, s, f, hp) \
146 (*(t)->vbs_map)((t)->vbs_cookie, (a), (s), (f), (hp), 0)
147
148 /*
149 * int bus_space_unmap __P((bus_space_tag_t t,
150 * bus_space_handle_t bsh, bus_size_t size));
151 *
152 * Unmap a region of bus space.
153 */
154
155 #define bus_space_unmap(t, h, s) \
156 (*(t)->vbs_unmap)((t)->vbs_cookie, (h), (s), 1)
157 #define vax_bus_space_unmap_noacct(t, h, s) \
158 (*(t)->vbs_unmap)((t)->vbs_cookie, (h), (s), 0)
159
160 /*
161 * int bus_space_subregion __P((bus_space_tag_t t,
162 * bus_space_handle_t bsh, bus_size_t offset, bus_size_t size,
163 * bus_space_handle_t *nbshp));
164 *
165 * Get a new handle for a subregion of an already-mapped area of bus space.
166 */
167
168 #define bus_space_subregion(t, h, o, s, nhp) \
169 (*(t)->vbs_subregion)((t)->vbs_cookie, (h), (o), (s), (nhp))
170
171 /*
172 * int bus_space_alloc __P((bus_space_tag_t t, bus_addr_t rstart,
173 * bus_addr_t rend, bus_size_t size, bus_size_t align,
174 * bus_size_t boundary, int flags, bus_addr_t *addrp,
175 * bus_space_handle_t *bshp));
176 *
177 * Allocate a region of bus space.
178 */
179
180 #define bus_space_alloc(t, rs, re, s, a, b, f, ap, hp) \
181 (*(t)->vbs_alloc)((t)->vbs_cookie, (rs), (re), (s), (a), (b), \
182 (f), (ap), (hp))
183
184 /*
185 * int bus_space_free __P((bus_space_tag_t t,
186 * bus_space_handle_t bsh, bus_size_t size));
187 *
188 * Free a region of bus space.
189 */
190
191 #define bus_space_free(t, h, s) \
192 (*(t)->vbs_free)((t)->vbs_cookie, (h), (s))
193
194 /*
195 * u_intN_t bus_space_read_N __P((bus_space_tag_t tag,
196 * bus_space_handle_t bsh, bus_size_t offset));
197 *
198 * Read a 1, 2, 4, or 8 byte quantity from bus space
199 * described by tag/handle/offset.
200 */
201
202 #define bus_space_read_1(t, h, o) \
203 (*(volatile u_int8_t *)((h) + (o)))
204
205 #define bus_space_read_2(t, h, o) \
206 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int16_t, "bus addr"), \
207 (*(volatile u_int16_t *)((h) + (o))))
208
209 #define bus_space_read_4(t, h, o) \
210 (__BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int32_t, "bus addr"), \
211 (*(volatile u_int32_t *)((h) + (o))))
212
213 #if 0 /* Cause a link error for bus_space_read_8 */
214 #define bus_space_read_8(t, h, o) !!! bus_space_read_8 unimplemented !!!
215 #endif
216
217 /*
218 * void bus_space_read_multi_N __P((bus_space_tag_t tag,
219 * bus_space_handle_t bsh, bus_size_t offset,
220 * u_intN_t *addr, size_t count));
221 *
222 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
223 * described by tag/handle/offset and copy into buffer provided.
224 */
225 static __inline void vax_mem_read_multi_1 __P((bus_space_tag_t,
226 bus_space_handle_t, bus_size_t, u_int8_t *, size_t));
227 static __inline void vax_mem_read_multi_2 __P((bus_space_tag_t,
228 bus_space_handle_t, bus_size_t, u_int16_t *, size_t));
229 static __inline void vax_mem_read_multi_4 __P((bus_space_tag_t,
230 bus_space_handle_t, bus_size_t, u_int32_t *, size_t));
231
232 #define bus_space_read_multi_1(t, h, o, a, c) \
233 vax_mem_read_multi_1((t), (h), (o), (a), (c))
234
235 #define bus_space_read_multi_2(t, h, o, a, c) \
236 do { \
237 __BUS_SPACE_ADDRESS_SANITY((a), u_int16_t, "buffer"); \
238 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int16_t, "bus addr"); \
239 vax_mem_read_multi_2((t), (h), (o), (a), (c)); \
240 } while (0)
241
242 #define bus_space_read_multi_4(t, h, o, a, c) \
243 do { \
244 __BUS_SPACE_ADDRESS_SANITY((a), u_int32_t, "buffer"); \
245 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int32_t, "bus addr"); \
246 vax_mem_read_multi_4((t), (h), (o), (a), (c)); \
247 } while (0)
248
249 #if 0 /* Cause a link error for bus_space_read_multi_8 */
250 #define bus_space_read_multi_8 !!! bus_space_read_multi_8 unimplemented !!!
251 #endif
252
253 static __inline void
254 vax_mem_read_multi_1(t, h, o, a, c)
255 bus_space_tag_t t;
256 bus_space_handle_t h;
257 bus_size_t o;
258 u_int8_t *a;
259 size_t c;
260 {
261 const bus_addr_t addr = h + o;
262
263 for (; c != 0; c--, a++)
264 *a = *(volatile u_int8_t *)(addr);
265 }
266
267 static __inline void
268 vax_mem_read_multi_2(t, h, o, a, c)
269 bus_space_tag_t t;
270 bus_space_handle_t h;
271 bus_size_t o;
272 u_int16_t *a;
273 size_t c;
274 {
275 const bus_addr_t addr = h + o;
276
277 for (; c != 0; c--, a++)
278 *a = *(volatile u_int16_t *)(addr);
279 }
280
281 static __inline void
282 vax_mem_read_multi_4(t, h, o, a, c)
283 bus_space_tag_t t;
284 bus_space_handle_t h;
285 bus_size_t o;
286 u_int32_t *a;
287 size_t c;
288 {
289 const bus_addr_t addr = h + o;
290
291 for (; c != 0; c--, a++)
292 *a = *(volatile u_int32_t *)(addr);
293 }
294
295 /*
296 * void bus_space_read_region_N __P((bus_space_tag_t tag,
297 * bus_space_handle_t bsh, bus_size_t offset,
298 * u_intN_t *addr, size_t count));
299 *
300 * Read `count' 1, 2, 4, or 8 byte quantities from bus space
301 * described by tag/handle and starting at `offset' and copy into
302 * buffer provided.
303 */
304
305 static __inline void vax_mem_read_region_1 __P((bus_space_tag_t,
306 bus_space_handle_t, bus_size_t, u_int8_t *, size_t));
307 static __inline void vax_mem_read_region_2 __P((bus_space_tag_t,
308 bus_space_handle_t, bus_size_t, u_int16_t *, size_t));
309 static __inline void vax_mem_read_region_4 __P((bus_space_tag_t,
310 bus_space_handle_t, bus_size_t, u_int32_t *, size_t));
311
312 #define bus_space_read_region_1(t, h, o, a, c) \
313 do { \
314 vax_mem_read_region_1((t), (h), (o), (a), (c)); \
315 } while (0)
316
317 #define bus_space_read_region_2(t, h, o, a, c) \
318 do { \
319 __BUS_SPACE_ADDRESS_SANITY((a), u_int16_t, "buffer"); \
320 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int16_t, "bus addr"); \
321 vax_mem_read_region_2((t), (h), (o), (a), (c)); \
322 } while (0)
323
324 #define bus_space_read_region_4(t, h, o, a, c) \
325 do { \
326 __BUS_SPACE_ADDRESS_SANITY((a), u_int32_t, "buffer"); \
327 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int32_t, "bus addr"); \
328 vax_mem_read_region_4((t), (h), (o), (a), (c)); \
329 } while (0)
330
331 #if 0 /* Cause a link error for bus_space_read_region_8 */
332 #define bus_space_read_region_8 \
333 !!! bus_space_read_region_8 unimplemented !!!
334 #endif
335
336 static __inline void
337 vax_mem_read_region_1(t, h, o, a, c)
338 bus_space_tag_t t;
339 bus_space_handle_t h;
340 bus_size_t o;
341 u_int8_t *a;
342 size_t c;
343 {
344 bus_addr_t addr = h + o;
345
346 for (; c != 0; c--, addr++, a++)
347 *a = *(volatile u_int8_t *)(addr);
348 }
349
350 static __inline void
351 vax_mem_read_region_2(t, h, o, a, c)
352 bus_space_tag_t t;
353 bus_space_handle_t h;
354 bus_size_t o;
355 u_int16_t *a;
356 size_t c;
357 {
358 bus_addr_t addr = h + o;
359
360 for (; c != 0; c--, addr++, a++)
361 *a = *(volatile u_int16_t *)(addr);
362 }
363
364 static __inline void
365 vax_mem_read_region_4(t, h, o, a, c)
366 bus_space_tag_t t;
367 bus_space_handle_t h;
368 bus_size_t o;
369 u_int32_t *a;
370 size_t c;
371 {
372 bus_addr_t addr = h + o;
373
374 for (; c != 0; c--, addr++, a++)
375 *a = *(volatile u_int32_t *)(addr);
376 }
377
378 /*
379 * void bus_space_write_N __P((bus_space_tag_t tag,
380 * bus_space_handle_t bsh, bus_size_t offset,
381 * u_intN_t value));
382 *
383 * Write the 1, 2, 4, or 8 byte value `value' to bus space
384 * described by tag/handle/offset.
385 */
386
387 #define bus_space_write_1(t, h, o, v) \
388 do { \
389 ((void)(*(volatile u_int8_t *)((h) + (o)) = (v))); \
390 } while (0)
391
392 #define bus_space_write_2(t, h, o, v) \
393 do { \
394 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int16_t, "bus addr"); \
395 ((void)(*(volatile u_int16_t *)((h) + (o)) = (v))); \
396 } while (0)
397
398 #define bus_space_write_4(t, h, o, v) \
399 do { \
400 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int32_t, "bus addr"); \
401 ((void)(*(volatile u_int32_t *)((h) + (o)) = (v))); \
402 } while (0)
403
404 #if 0 /* Cause a link error for bus_space_write_8 */
405 #define bus_space_write_8 !!! bus_space_write_8 not implemented !!!
406 #endif
407
408 /*
409 * void bus_space_write_multi_N __P((bus_space_tag_t tag,
410 * bus_space_handle_t bsh, bus_size_t offset,
411 * const u_intN_t *addr, size_t count));
412 *
413 * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
414 * provided to bus space described by tag/handle/offset.
415 */
416 static __inline void vax_mem_write_multi_1 __P((bus_space_tag_t,
417 bus_space_handle_t, bus_size_t, const u_int8_t *, size_t));
418 static __inline void vax_mem_write_multi_2 __P((bus_space_tag_t,
419 bus_space_handle_t, bus_size_t, const u_int16_t *, size_t));
420 static __inline void vax_mem_write_multi_4 __P((bus_space_tag_t,
421 bus_space_handle_t, bus_size_t, const u_int32_t *, size_t));
422
423 #define bus_space_write_multi_1(t, h, o, a, c) \
424 do { \
425 vax_mem_write_multi_1((t), (h), (o), (a), (c)); \
426 } while (0)
427
428 #define bus_space_write_multi_2(t, h, o, a, c) \
429 do { \
430 __BUS_SPACE_ADDRESS_SANITY((a), u_int16_t, "buffer"); \
431 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int16_t, "bus addr"); \
432 vax_mem_write_multi_2((t), (h), (o), (a), (c)); \
433 } while (0)
434
435 #define bus_space_write_multi_4(t, h, o, a, c) \
436 do { \
437 __BUS_SPACE_ADDRESS_SANITY((a), u_int32_t, "buffer"); \
438 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int32_t, "bus addr"); \
439 vax_mem_write_multi_4((t), (h), (o), (a), (c)); \
440 } while (0)
441
442 #if 0 /* Cause a link error for bus_space_write_multi_8 */
443 #define bus_space_write_multi_8(t, h, o, a, c) \
444 !!! bus_space_write_multi_8 unimplemented !!!
445 #endif
446
447 static __inline void
448 vax_mem_write_multi_1(t, h, o, a, c)
449 bus_space_tag_t t;
450 bus_space_handle_t h;
451 bus_size_t o;
452 const u_int8_t *a;
453 size_t c;
454 {
455 const bus_addr_t addr = h + o;
456
457 for (; c != 0; c--, a++)
458 *(volatile u_int8_t *)(addr) = *a;
459 }
460
461 static __inline void
462 vax_mem_write_multi_2(t, h, o, a, c)
463 bus_space_tag_t t;
464 bus_space_handle_t h;
465 bus_size_t o;
466 const u_int16_t *a;
467 size_t c;
468 {
469 const bus_addr_t addr = h + o;
470
471 for (; c != 0; c--, a++)
472 *(volatile u_int16_t *)(addr) = *a;
473 }
474
475 static __inline void
476 vax_mem_write_multi_4(t, h, o, a, c)
477 bus_space_tag_t t;
478 bus_space_handle_t h;
479 bus_size_t o;
480 const u_int32_t *a;
481 size_t c;
482 {
483 const bus_addr_t addr = h + o;
484
485 for (; c != 0; c--, a++)
486 *(volatile u_int32_t *)(addr) = *a;
487 }
488
489 /*
490 * void bus_space_write_region_N __P((bus_space_tag_t tag,
491 * bus_space_handle_t bsh, bus_size_t offset,
492 * const u_intN_t *addr, size_t count));
493 *
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'.
496 */
497 static __inline void vax_mem_write_region_1 __P((bus_space_tag_t,
498 bus_space_handle_t, bus_size_t, const u_int8_t *, size_t));
499 static __inline void vax_mem_write_region_2 __P((bus_space_tag_t,
500 bus_space_handle_t, bus_size_t, const u_int16_t *, size_t));
501 static __inline void vax_mem_write_region_4 __P((bus_space_tag_t,
502 bus_space_handle_t, bus_size_t, const u_int32_t *, size_t));
503
504 #define bus_space_write_region_1(t, h, o, a, c) \
505 vax_mem_write_region_1((t), (h), (o), (a), (c))
506
507 #define bus_space_write_region_2(t, h, o, a, c) \
508 do { \
509 __BUS_SPACE_ADDRESS_SANITY((a), u_int16_t, "buffer"); \
510 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int16_t, "bus addr"); \
511 vax_mem_write_region_2((t), (h), (o), (a), (c)); \
512 } while (0)
513
514 #define bus_space_write_region_4(t, h, o, a, c) \
515 do { \
516 __BUS_SPACE_ADDRESS_SANITY((a), u_int32_t, "buffer"); \
517 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int32_t, "bus addr"); \
518 vax_mem_write_region_4((t), (h), (o), (a), (c)); \
519 } while (0)
520
521 #if 0 /* Cause a link error for bus_space_write_region_8 */
522 #define bus_space_write_region_8 \
523 !!! bus_space_write_region_8 unimplemented !!!
524 #endif
525
526 static __inline void
527 vax_mem_write_region_1(t, h, o, a, c)
528 bus_space_tag_t t;
529 bus_space_handle_t h;
530 bus_size_t o;
531 const u_int8_t *a;
532 size_t c;
533 {
534 bus_addr_t addr = h + o;
535
536 for (; c != 0; c--, addr++, a++)
537 *(volatile u_int8_t *)(addr) = *a;
538 }
539
540 static __inline void
541 vax_mem_write_region_2(t, h, o, a, c)
542 bus_space_tag_t t;
543 bus_space_handle_t h;
544 bus_size_t o;
545 const u_int16_t *a;
546 size_t c;
547 {
548 bus_addr_t addr = h + o;
549
550 for (; c != 0; c--, addr++, a++)
551 *(volatile u_int16_t *)(addr) = *a;
552 }
553
554 static __inline void
555 vax_mem_write_region_4(t, h, o, a, c)
556 bus_space_tag_t t;
557 bus_space_handle_t h;
558 bus_size_t o;
559 const u_int32_t *a;
560 size_t c;
561 {
562 bus_addr_t addr = h + o;
563
564 for (; c != 0; c--, addr++, a++)
565 *(volatile u_int32_t *)(addr) = *a;
566 }
567
568 /*
569 * void bus_space_set_multi_N __P((bus_space_tag_t tag,
570 * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
571 * size_t count));
572 *
573 * Write the 1, 2, 4, or 8 byte value `val' to bus space described
574 * by tag/handle/offset `count' times.
575 */
576
577 static __inline void vax_mem_set_multi_1 __P((bus_space_tag_t,
578 bus_space_handle_t, bus_size_t, u_int8_t, size_t));
579 static __inline void vax_mem_set_multi_2 __P((bus_space_tag_t,
580 bus_space_handle_t, bus_size_t, u_int16_t, size_t));
581 static __inline void vax_mem_set_multi_4 __P((bus_space_tag_t,
582 bus_space_handle_t, bus_size_t, u_int32_t, size_t));
583
584 #define bus_space_set_multi_1(t, h, o, v, c) \
585 vax_mem_set_multi_1((t), (h), (o), (v), (c))
586
587 #define bus_space_set_multi_2(t, h, o, v, c) \
588 do { \
589 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int16_t, "bus addr"); \
590 vax_mem_set_multi_2((t), (h), (o), (v), (c)); \
591 } while (0)
592
593 #define bus_space_set_multi_4(t, h, o, v, c) \
594 do { \
595 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int32_t, "bus addr"); \
596 vax_mem_set_multi_4((t), (h), (o), (v), (c)); \
597 } while (0)
598
599 static __inline void
600 vax_mem_set_multi_1(t, h, o, v, c)
601 bus_space_tag_t t;
602 bus_space_handle_t h;
603 bus_size_t o;
604 u_int8_t v;
605 size_t c;
606 {
607 bus_addr_t addr = h + o;
608
609 while (c--)
610 *(volatile u_int8_t *)(addr) = v;
611 }
612
613 static __inline void
614 vax_mem_set_multi_2(t, h, o, v, c)
615 bus_space_tag_t t;
616 bus_space_handle_t h;
617 bus_size_t o;
618 u_int16_t v;
619 size_t c;
620 {
621 bus_addr_t addr = h + o;
622
623 while (c--)
624 *(volatile u_int16_t *)(addr) = v;
625 }
626
627 static __inline void
628 vax_mem_set_multi_4(t, h, o, v, c)
629 bus_space_tag_t t;
630 bus_space_handle_t h;
631 bus_size_t o;
632 u_int32_t v;
633 size_t c;
634 {
635 bus_addr_t addr = h + o;
636
637 while (c--)
638 *(volatile u_int32_t *)(addr) = v;
639 }
640
641 #if 0 /* Cause a link error for bus_space_set_multi_8 */
642 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
643 #endif
644
645 /*
646 * void bus_space_set_region_N __P((bus_space_tag_t tag,
647 * bus_space_handle_t bsh, bus_size_t offset, u_intN_t val,
648 * size_t count));
649 *
650 * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
651 * by tag/handle starting at `offset'.
652 */
653
654 static __inline void vax_mem_set_region_1 __P((bus_space_tag_t,
655 bus_space_handle_t, bus_size_t, u_int8_t, size_t));
656 static __inline void vax_mem_set_region_2 __P((bus_space_tag_t,
657 bus_space_handle_t, bus_size_t, u_int16_t, size_t));
658 static __inline void vax_mem_set_region_4 __P((bus_space_tag_t,
659 bus_space_handle_t, bus_size_t, u_int32_t, size_t));
660
661 #define bus_space_set_region_1(t, h, o, v, c) \
662 vax_mem_set_region_1((t), (h), (o), (v), (c))
663
664 #define bus_space_set_region_2(t, h, o, v, c) \
665 do { \
666 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int16_t, "bus addr"); \
667 vax_mem_set_region_2((t), (h), (o), (v), (c)); \
668 } while (0)
669
670 #define bus_space_set_region_4(t, h, o, v, c) \
671 do { \
672 __BUS_SPACE_ADDRESS_SANITY((h) + (o), u_int32_t, "bus addr"); \
673 vax_mem_set_region_4((t), (h), (o), (v), (c)); \
674 } while (0)
675
676 static __inline void
677 vax_mem_set_region_1(t, h, o, v, c)
678 bus_space_tag_t t;
679 bus_space_handle_t h;
680 bus_size_t o;
681 u_int8_t v;
682 size_t c;
683 {
684 bus_addr_t addr = h + o;
685
686 for (; c != 0; c--, addr++)
687 *(volatile u_int8_t *)(addr) = v;
688 }
689
690 static __inline void
691 vax_mem_set_region_2(t, h, o, v, c)
692 bus_space_tag_t t;
693 bus_space_handle_t h;
694 bus_size_t o;
695 u_int16_t v;
696 size_t c;
697 {
698 bus_addr_t addr = h + o;
699
700 for (; c != 0; c--, addr += 2)
701 *(volatile u_int16_t *)(addr) = v;
702 }
703
704 static __inline void
705 vax_mem_set_region_4(t, h, o, v, c)
706 bus_space_tag_t t;
707 bus_space_handle_t h;
708 bus_size_t o;
709 u_int32_t v;
710 size_t c;
711 {
712 bus_addr_t addr = h + o;
713
714 for (; c != 0; c--, addr += 4)
715 *(volatile u_int32_t *)(addr) = v;
716 }
717
718 #if 0 /* Cause a link error for bus_space_set_region_8 */
719 #define bus_space_set_region_8 !!! bus_space_set_region_8 unimplemented !!!
720 #endif
721
722 /*
723 * void bus_space_copy_region_N __P((bus_space_tag_t tag,
724 * bus_space_handle_t bsh1, bus_size_t off1,
725 * bus_space_handle_t bsh2, bus_size_t off2,
726 * size_t count));
727 *
728 * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
729 * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
730 */
731
732 static __inline void vax_mem_copy_region_1 __P((bus_space_tag_t,
733 bus_space_handle_t, bus_size_t, bus_space_handle_t,
734 bus_size_t, size_t));
735 static __inline void vax_mem_copy_region_2 __P((bus_space_tag_t,
736 bus_space_handle_t, bus_size_t, bus_space_handle_t,
737 bus_size_t, size_t));
738 static __inline void vax_mem_copy_region_4 __P((bus_space_tag_t,
739 bus_space_handle_t, bus_size_t, bus_space_handle_t,
740 bus_size_t, size_t));
741
742 #define bus_space_copy_region_1(t, h1, o1, h2, o2, c) \
743 vax_mem_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
744
745 #define bus_space_copy_region_2(t, h1, o1, h2, o2, c) \
746 do { \
747 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), u_int16_t, "bus addr 1"); \
748 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), u_int16_t, "bus addr 2"); \
749 vax_mem_copy_region_2((t), (h1), (o1), (h2), (o2), (c)); \
750 } while (0)
751
752 #define bus_space_copy_region_4(t, h1, o1, h2, o2, c) \
753 do { \
754 __BUS_SPACE_ADDRESS_SANITY((h1) + (o1), u_int32_t, "bus addr 1"); \
755 __BUS_SPACE_ADDRESS_SANITY((h2) + (o2), u_int32_t, "bus addr 2"); \
756 vax_mem_copy_region_4((t), (h1), (o1), (h2), (o2), (c)); \
757 } while (0)
758
759 static __inline void
760 vax_mem_copy_region_1(t, h1, o1, h2, o2, c)
761 bus_space_tag_t t;
762 bus_space_handle_t h1;
763 bus_size_t o1;
764 bus_space_handle_t h2;
765 bus_size_t o2;
766 size_t c;
767 {
768 bus_addr_t addr1 = h1 + o1;
769 bus_addr_t addr2 = h2 + o2;
770
771 if (addr1 >= addr2) {
772 /* src after dest: copy forward */
773 for (; c != 0; c--, addr1++, addr2++)
774 *(volatile u_int8_t *)(addr2) =
775 *(volatile u_int8_t *)(addr1);
776 } else {
777 /* dest after src: copy backwards */
778 for (addr1 += (c - 1), addr2 += (c - 1);
779 c != 0; c--, addr1--, addr2--)
780 *(volatile u_int8_t *)(addr2) =
781 *(volatile u_int8_t *)(addr1);
782 }
783 }
784
785 static __inline void
786 vax_mem_copy_region_2(t, h1, o1, h2, o2, c)
787 bus_space_tag_t t;
788 bus_space_handle_t h1;
789 bus_size_t o1;
790 bus_space_handle_t h2;
791 bus_size_t o2;
792 size_t c;
793 {
794 bus_addr_t addr1 = h1 + o1;
795 bus_addr_t addr2 = h2 + o2;
796
797 if (addr1 >= addr2) {
798 /* src after dest: copy forward */
799 for (; c != 0; c--, addr1 += 2, addr2 += 2)
800 *(volatile u_int16_t *)(addr2) =
801 *(volatile u_int16_t *)(addr1);
802 } else {
803 /* dest after src: copy backwards */
804 for (addr1 += 2 * (c - 1), addr2 += 2 * (c - 1);
805 c != 0; c--, addr1 -= 2, addr2 -= 2)
806 *(volatile u_int16_t *)(addr2) =
807 *(volatile u_int16_t *)(addr1);
808 }
809 }
810
811 static __inline void
812 vax_mem_copy_region_4(t, h1, o1, h2, o2, c)
813 bus_space_tag_t t;
814 bus_space_handle_t h1;
815 bus_size_t o1;
816 bus_space_handle_t h2;
817 bus_size_t o2;
818 size_t c;
819 {
820 bus_addr_t addr1 = h1 + o1;
821 bus_addr_t addr2 = h2 + o2;
822
823 if (addr1 >= addr2) {
824 /* src after dest: copy forward */
825 for (; c != 0; c--, addr1 += 4, addr2 += 4)
826 *(volatile u_int32_t *)(addr2) =
827 *(volatile u_int32_t *)(addr1);
828 } else {
829 /* dest after src: copy backwards */
830 for (addr1 += 4 * (c - 1), addr2 += 4 * (c - 1);
831 c != 0; c--, addr1 -= 4, addr2 -= 4)
832 *(volatile u_int32_t *)(addr2) =
833 *(volatile u_int32_t *)(addr1);
834 }
835 }
836
837 #if 0 /* Cause a link error for bus_space_copy_8 */
838 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!!
839 #endif
840
841
842 /*
843 * Bus read/write barrier methods.
844 *
845 * void bus_space_barrier __P((bus_space_tag_t tag,
846 * bus_space_handle_t bsh, bus_size_t offset,
847 * bus_size_t len, int flags));
848 *
849 * Note: the vax does not currently require barriers, but we must
850 * provide the flags to MI code.
851 */
852 #define bus_space_barrier(t, h, o, l, f) \
853 ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
854 #define BUS_SPACE_BARRIER_READ 0x01 /* force read barrier */
855 #define BUS_SPACE_BARRIER_WRITE 0x02 /* force write barrier */
856
857
858 /*
859 * Flags used in various bus DMA methods.
860 */
861 #define BUS_DMA_WAITOK 0x00 /* safe to sleep (pseudo-flag) */
862 #define BUS_DMA_NOWAIT 0x01 /* not safe to sleep */
863 #define BUS_DMA_ALLOCNOW 0x02 /* perform resource allocation now */
864 #define BUS_DMA_COHERENT 0x04 /* hint: map memory DMA coherent */
865 #define BUS_DMA_BUS1 0x10 /* placeholders for bus functions... */
866 #define BUS_DMA_BUS2 0x20
867 #define BUS_DMA_BUS3 0x40
868 #define BUS_DMA_BUS4 0x80
869
870 #define VAX_BUS_DMA_SPILLPAGE BUS_DMA_BUS1 /* VS4000 kludge */
871 /*
872 * Private flags stored in the DMA map.
873 */
874 #define DMAMAP_HAS_SGMAP 0x80000000 /* sgva/len are valid */
875
876 /* Forwards needed by prototypes below. */
877 struct mbuf;
878 struct uio;
879 struct vax_sgmap;
880
881 /*
882 * Operations performed by bus_dmamap_sync().
883 */
884 #define BUS_DMASYNC_PREREAD 0x01 /* pre-read synchronization */
885 #define BUS_DMASYNC_POSTREAD 0x02 /* post-read synchronization */
886 #define BUS_DMASYNC_PREWRITE 0x04 /* pre-write synchronization */
887 #define BUS_DMASYNC_POSTWRITE 0x08 /* post-write synchronization */
888
889 /*
890 * vax_bus_t
891 *
892 * Busses supported by NetBSD/vax, used by internal
893 * utility functions. NOT TO BE USED BY MACHINE-INDEPENDENT
894 * CODE!
895 */
896 typedef enum {
897 VAX_BUS_MAINBUS,
898 VAX_BUS_SBI,
899 VAX_BUS_MASSBUS,
900 VAX_BUS_UNIBUS, /* Also handles QBUS */
901 VAX_BUS_BI,
902 VAX_BUS_XMI,
903 VAX_BUS_TURBOCHANNEL
904 } vax_bus_t;
905
906 typedef struct vax_bus_dma_tag *bus_dma_tag_t;
907 typedef struct vax_bus_dmamap *bus_dmamap_t;
908
909 /*
910 * bus_dma_segment_t
911 *
912 * Describes a single contiguous DMA transaction. Values
913 * are suitable for programming into DMA registers.
914 */
915 struct vax_bus_dma_segment {
916 bus_addr_t ds_addr; /* DMA address */
917 bus_size_t ds_len; /* length of transfer */
918 };
919 typedef struct vax_bus_dma_segment bus_dma_segment_t;
920
921 struct proc;
922
923 /*
924 * bus_dma_tag_t
925 *
926 * A machine-dependent opaque type describing the implementation of
927 * DMA for a given bus.
928 */
929 struct vax_bus_dma_tag {
930 void *_cookie; /* cookie used in the guts */
931 bus_addr_t _wbase; /* DMA window base */
932 bus_size_t _wsize; /* DMA window size */
933
934 /*
935 * Some chipsets have a built-in boundary constraint, independent
936 * of what the device requests. This allows that boundary to
937 * be specified. If the device has a more restrictive contraint,
938 * the map will use that, otherwise this boundary will be used.
939 * This value is ignored if 0.
940 */
941 bus_size_t _boundary;
942
943 /*
944 * A bus may have more than one SGMAP window, so SGMAP
945 * windows also get a pointer to their SGMAP state.
946 */
947 struct vax_sgmap *_sgmap;
948
949 /*
950 * Internal-use only utility methods. NOT TO BE USED BY
951 * MACHINE-INDEPENDENT CODE!
952 */
953 bus_dma_tag_t (*_get_tag) __P((bus_dma_tag_t, vax_bus_t));
954
955 /*
956 * DMA mapping methods.
957 */
958 int (*_dmamap_create) __P((bus_dma_tag_t, bus_size_t, int,
959 bus_size_t, bus_size_t, int, bus_dmamap_t *));
960 void (*_dmamap_destroy) __P((bus_dma_tag_t, bus_dmamap_t));
961 int (*_dmamap_load) __P((bus_dma_tag_t, bus_dmamap_t, void *,
962 bus_size_t, struct proc *, int));
963 int (*_dmamap_load_mbuf) __P((bus_dma_tag_t, bus_dmamap_t,
964 struct mbuf *, int));
965 int (*_dmamap_load_uio) __P((bus_dma_tag_t, bus_dmamap_t,
966 struct uio *, int));
967 int (*_dmamap_load_raw) __P((bus_dma_tag_t, bus_dmamap_t,
968 bus_dma_segment_t *, int, bus_size_t, int));
969 void (*_dmamap_unload) __P((bus_dma_tag_t, bus_dmamap_t));
970 void (*_dmamap_sync) __P((bus_dma_tag_t, bus_dmamap_t,
971 bus_addr_t, bus_size_t, int));
972
973 /*
974 * DMA memory utility functions.
975 */
976 int (*_dmamem_alloc) __P((bus_dma_tag_t, bus_size_t, bus_size_t,
977 bus_size_t, bus_dma_segment_t *, int, int *, int));
978 void (*_dmamem_free) __P((bus_dma_tag_t,
979 bus_dma_segment_t *, int));
980 int (*_dmamem_map) __P((bus_dma_tag_t, bus_dma_segment_t *,
981 int, size_t, caddr_t *, int));
982 void (*_dmamem_unmap) __P((bus_dma_tag_t, caddr_t, size_t));
983 int (*_dmamem_mmap) __P((bus_dma_tag_t, bus_dma_segment_t *,
984 int, int, int, int));
985 };
986
987 #define vaxbus_dma_get_tag(t, b) \
988 (*(t)->_get_tag)(t, b)
989
990 #define bus_dmamap_create(t, s, n, m, b, f, p) \
991 (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
992 #define bus_dmamap_destroy(t, p) \
993 (*(t)->_dmamap_destroy)((t), (p))
994 #define bus_dmamap_load(t, m, b, s, p, f) \
995 (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
996 #define bus_dmamap_load_mbuf(t, m, b, f) \
997 (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
998 #define bus_dmamap_load_uio(t, m, u, f) \
999 (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
1000 #define bus_dmamap_load_raw(t, m, sg, n, s, f) \
1001 (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
1002 #define bus_dmamap_unload(t, p) \
1003 (*(t)->_dmamap_unload)((t), (p))
1004 #define bus_dmamap_sync(t, p, o, l, ops) \
1005 (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops))
1006 #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f) \
1007 (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
1008 #define bus_dmamem_free(t, sg, n) \
1009 (*(t)->_dmamem_free)((t), (sg), (n))
1010 #define bus_dmamem_map(t, sg, n, s, k, f) \
1011 (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
1012 #define bus_dmamem_unmap(t, k, s) \
1013 (*(t)->_dmamem_unmap)((t), (k), (s))
1014 #define bus_dmamem_mmap(t, sg, n, o, p, f) \
1015 (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
1016
1017 /*
1018 * bus_dmamap_t
1019 *
1020 * Describes a DMA mapping.
1021 */
1022 struct vax_bus_dmamap {
1023 /*
1024 * PRIVATE MEMBERS: not for use my machine-independent code.
1025 */
1026 bus_size_t _dm_size; /* largest DMA transfer mappable */
1027 int _dm_segcnt; /* number of segs this map can map */
1028 bus_size_t _dm_maxsegsz; /* largest possible segment */
1029 bus_size_t _dm_boundary; /* don't cross this */
1030 int _dm_flags; /* misc. flags */
1031
1032 /*
1033 * This is used only for SGMAP-mapped DMA, but we keep it
1034 * here to avoid pointless indirection.
1035 */
1036 int _dm_pteidx; /* PTE index */
1037 int _dm_ptecnt; /* PTE count */
1038 u_long _dm_sgva; /* allocated sgva */
1039 bus_size_t _dm_sgvalen; /* svga length */
1040
1041 /*
1042 * PUBLIC MEMBERS: these are used by machine-independent code.
1043 */
1044 bus_size_t dm_mapsize; /* size of the mapping */
1045 int dm_nsegs; /* # valid segments in mapping */
1046 bus_dma_segment_t dm_segs[1]; /* segments; variable length */
1047 };
1048
1049 #ifdef _VAX_BUS_DMA_PRIVATE
1050 int _bus_dmamap_create __P((bus_dma_tag_t, bus_size_t, int, bus_size_t,
1051 bus_size_t, int, bus_dmamap_t *));
1052 void _bus_dmamap_destroy __P((bus_dma_tag_t, bus_dmamap_t));
1053
1054 int _bus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t,
1055 void *, bus_size_t, struct proc *, int));
1056 int _bus_dmamap_load_mbuf __P((bus_dma_tag_t,
1057 bus_dmamap_t, struct mbuf *, int));
1058 int _bus_dmamap_load_uio __P((bus_dma_tag_t,
1059 bus_dmamap_t, struct uio *, int));
1060 int _bus_dmamap_load_raw __P((bus_dma_tag_t,
1061 bus_dmamap_t, bus_dma_segment_t *, int, bus_size_t, int));
1062
1063 void _bus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t));
1064 void _bus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
1065 bus_size_t, int));
1066
1067 int _bus_dmamem_alloc __P((bus_dma_tag_t tag, bus_size_t size,
1068 bus_size_t alignment, bus_size_t boundary,
1069 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags));
1070 void _bus_dmamem_free __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
1071 int nsegs));
1072 int _bus_dmamem_map __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
1073 int nsegs, size_t size, caddr_t *kvap, int flags));
1074 void _bus_dmamem_unmap __P((bus_dma_tag_t tag, caddr_t kva,
1075 size_t size));
1076 int _bus_dmamem_mmap __P((bus_dma_tag_t tag, bus_dma_segment_t *segs,
1077 int nsegs, int off, int prot, int flags));
1078 #endif /* _VAX_BUS_DMA_PRIVATE */
1079
1080 #endif /* _VAX_BUS_H_ */
1081