bus.h revision 203883
1/*-
2 * Copyright (c) 2009 Marcel Moolenaar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27/*	$NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $	*/
28
29/*-
30 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
31 * All rights reserved.
32 *
33 * This code is derived from software contributed to The NetBSD Foundation
34 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
35 * NASA Ames Research Center.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 *    notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 *    notice, this list of conditions and the following disclaimer in the
44 *    documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 *    must display the following acknowledgement:
47 *	This product includes software developed by the NetBSD
48 *	Foundation, Inc. and its contributors.
49 * 4. Neither the name of The NetBSD Foundation nor the names of its
50 *    contributors may be used to endorse or promote products derived
51 *    from this software without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
54 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
64 */
65
66/*-
67 * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
68 * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
69 *
70 * Redistribution and use in source and binary forms, with or without
71 * modification, are permitted provided that the following conditions
72 * are met:
73 * 1. Redistributions of source code must retain the above copyright
74 *    notice, this list of conditions and the following disclaimer.
75 * 2. Redistributions in binary form must reproduce the above copyright
76 *    notice, this list of conditions and the following disclaimer in the
77 *    documentation and/or other materials provided with the distribution.
78 * 3. All advertising materials mentioning features or use of this software
79 *    must display the following acknowledgement:
80 *      This product includes software developed by Christopher G. Demetriou
81 *	for the NetBSD Project.
82 * 4. The name of the author may not be used to endorse or promote products
83 *    derived from this software without specific prior written permission
84 *
85 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
86 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
87 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
88 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
89 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
90 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
91 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
92 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
93 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
94 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
95 */
96/* $FreeBSD: head/sys/ia64/include/bus.h 203883 2010-02-14 16:56:24Z marcel $ */
97
98#ifndef _MACHINE_BUS_H_
99#define _MACHINE_BUS_H_
100
101#include <machine/_bus.h>
102#include <machine/cpufunc.h>
103
104/*
105 * I/O port reads with ia32 semantics.
106 */
107#define inb     bus_space_read_io_1
108#define inw     bus_space_read_io_2
109#define inl     bus_space_read_io_4
110
111#define outb    bus_space_write_io_1
112#define outw    bus_space_write_io_2
113#define outl    bus_space_write_io_4
114
115/*
116 * Values for the ia64 bus space tag, not to be used directly by MI code.
117 */
118#define	IA64_BUS_SPACE_IO	0	/* space is i/o space */
119#define IA64_BUS_SPACE_MEM	1	/* space is mem space */
120
121#define	BUS_SPACE_BARRIER_READ	0x01	/* force read barrier */
122#define	BUS_SPACE_BARRIER_WRITE	0x02	/* force write barrier */
123
124#define BUS_SPACE_MAXSIZE_24BIT	0xFFFFFF
125#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
126#define BUS_SPACE_MAXSIZE	0xFFFFFFFFFFFFFFFF
127#define BUS_SPACE_MAXADDR_24BIT	0xFFFFFF
128#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
129#define BUS_SPACE_MAXADDR	0xFFFFFFFFFFFFFFFF
130
131#define BUS_SPACE_UNRESTRICTED	(~0)
132
133
134/*
135 * Map and unmap a region of device bus space into CPU virtual address space.
136 */
137int
138bus_space_map(bus_space_tag_t, bus_addr_t, bus_size_t, int,
139    bus_space_handle_t *);
140
141void
142bus_space_unmap(bus_space_tag_t, bus_space_handle_t, bus_size_t size);
143
144/*
145 * Get a new handle for a subregion of an already-mapped area of bus space.
146 */
147static __inline int
148bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh,
149    bus_size_t ofs, bus_size_t size __unused, bus_space_handle_t *nbshp)
150{
151	*nbshp = bsh + ofs;
152	return (0);
153}
154
155
156/*
157 * Allocate a region of memory that is accessible to devices in bus space.
158 */
159int
160bus_space_alloc(bus_space_tag_t bst, bus_addr_t rstart, bus_addr_t rend,
161    bus_size_t size, bus_size_t align, bus_size_t boundary, int flags,
162    bus_addr_t *addrp, bus_space_handle_t *bshp);
163
164
165/*
166 * Free a region of bus space accessible memory.
167 */
168void
169bus_space_free(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t size);
170
171
172/*
173 * Bus read/write barrier method.
174 */
175static __inline void
176bus_space_barrier(bus_space_tag_t bst __unused, bus_space_handle_t bsh __unused,
177    bus_size_t ofs __unused, bus_size_t size __unused, int flags __unused)
178{
179	ia64_mf_a();
180	ia64_mf();
181}
182
183
184/*
185 * Read 1 unit of data from bus space described by the tag, handle and ofs
186 * tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
187 * data is returned.
188 */
189uint8_t  bus_space_read_io_1(u_long);
190uint16_t bus_space_read_io_2(u_long);
191uint32_t bus_space_read_io_4(u_long);
192uint64_t bus_space_read_io_8(u_long);
193
194static __inline uint8_t
195bus_space_read_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
196{
197	uint8_t val;
198
199	val = (__predict_false(bst == IA64_BUS_SPACE_IO))
200	    ? bus_space_read_io_1(bsh + ofs)
201	    : ia64_ld1((void *)(bsh + ofs));
202	return (val);
203}
204
205static __inline uint16_t
206bus_space_read_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
207{
208	uint16_t val;
209
210	val = (__predict_false(bst == IA64_BUS_SPACE_IO))
211	    ? bus_space_read_io_2(bsh + ofs)
212	    : ia64_ld2((void *)(bsh + ofs));
213	return (val);
214}
215
216static __inline uint32_t
217bus_space_read_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
218{
219	uint32_t val;
220
221	val = (__predict_false(bst == IA64_BUS_SPACE_IO))
222	    ? bus_space_read_io_4(bsh + ofs)
223	    : ia64_ld4((void *)(bsh + ofs));
224	return (val);
225}
226
227static __inline uint64_t
228bus_space_read_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
229{
230	uint64_t val;
231
232	val = (__predict_false(bst == IA64_BUS_SPACE_IO))
233	    ? bus_space_read_io_8(bsh + ofs)
234	    : ia64_ld8((void *)(bsh + ofs));
235	return (val);
236}
237
238
239/*
240 * Write 1 unit of data to bus space described by the tag, handle and ofs
241 * tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
242 * data is passed by value.
243 */
244void bus_space_write_io_1(u_long, uint8_t);
245void bus_space_write_io_2(u_long, uint16_t);
246void bus_space_write_io_4(u_long, uint32_t);
247void bus_space_write_io_8(u_long, uint64_t);
248
249static __inline void
250bus_space_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
251    uint8_t val)
252{
253
254	if (__predict_false(bst == IA64_BUS_SPACE_IO))
255		bus_space_write_io_1(bsh + ofs, val);
256	else
257		ia64_st1((void *)(bsh + ofs), val);
258}
259
260static __inline void
261bus_space_write_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
262    uint16_t val)
263{
264
265	if (__predict_false(bst == IA64_BUS_SPACE_IO))
266		bus_space_write_io_2(bsh + ofs, val);
267	else
268		ia64_st2((void *)(bsh + ofs), val);
269}
270
271static __inline void
272bus_space_write_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
273    uint32_t val)
274{
275
276	if (__predict_false(bst == IA64_BUS_SPACE_IO))
277		bus_space_write_io_4(bsh + ofs, val);
278	else
279		ia64_st4((void *)(bsh + ofs), val);
280}
281
282static __inline void
283bus_space_write_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
284    uint64_t val)
285{
286
287	if (__predict_false(bst == IA64_BUS_SPACE_IO))
288		bus_space_write_io_8(bsh + ofs, val);
289	else
290		ia64_st8((void *)(bsh + ofs), val);
291}
292
293
294/*
295 * Read count units of data from bus space described by the tag, handle and
296 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
297 * data is returned in the buffer passed by reference.
298 */
299void bus_space_read_multi_io_1(u_long, uint8_t *, size_t);
300void bus_space_read_multi_io_2(u_long, uint16_t *, size_t);
301void bus_space_read_multi_io_4(u_long, uint32_t *, size_t);
302void bus_space_read_multi_io_8(u_long, uint64_t *, size_t);
303
304static __inline void
305bus_space_read_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
306    bus_size_t ofs, uint8_t *bufp, size_t count)
307{
308
309	if (__predict_false(bst == IA64_BUS_SPACE_IO))
310		bus_space_read_multi_io_1(bsh + ofs, bufp, count);
311	else {
312		while (count-- > 0)
313			*bufp++ = ia64_ld1((void *)(bsh + ofs));
314	}
315}
316
317static __inline void
318bus_space_read_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
319    bus_size_t ofs, uint16_t *bufp, size_t count)
320{
321
322	if (__predict_false(bst == IA64_BUS_SPACE_IO))
323		bus_space_read_multi_io_2(bsh + ofs, bufp, count);
324	else {
325		while (count-- > 0)
326			*bufp++ = ia64_ld2((void *)(bsh + ofs));
327	}
328}
329
330static __inline void
331bus_space_read_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
332    bus_size_t ofs, uint32_t *bufp, size_t count)
333{
334
335	if (__predict_false(bst == IA64_BUS_SPACE_IO))
336		bus_space_read_multi_io_4(bsh + ofs, bufp, count);
337	else {
338		while (count-- > 0)
339			*bufp++ = ia64_ld4((void *)(bsh + ofs));
340	}
341}
342
343static __inline void
344bus_space_read_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh,
345    bus_size_t ofs, uint64_t *bufp, size_t count)
346{
347
348	if (__predict_false(bst == IA64_BUS_SPACE_IO))
349		bus_space_read_multi_io_8(bsh + ofs, bufp, count);
350	else {
351		while (count-- > 0)
352			*bufp++ = ia64_ld8((void *)(bsh + ofs));
353	}
354}
355
356
357/*
358 * Write count units of data to bus space described by the tag, handle and
359 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
360 * data is read from the buffer passed by reference.
361 */
362void bus_space_write_multi_io_1(u_long, const uint8_t *, size_t);
363void bus_space_write_multi_io_2(u_long, const uint16_t *, size_t);
364void bus_space_write_multi_io_4(u_long, const uint32_t *, size_t);
365void bus_space_write_multi_io_8(u_long, const uint64_t *, size_t);
366
367static __inline void
368bus_space_write_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
369    bus_size_t ofs, const uint8_t *bufp, size_t count)
370{
371
372	if (__predict_false(bst == IA64_BUS_SPACE_IO))
373		bus_space_write_multi_io_1(bsh + ofs, bufp, count);
374	else {
375		while (count-- > 0)
376			ia64_st1((void *)(bsh + ofs), *bufp++);
377	}
378}
379
380static __inline void
381bus_space_write_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
382    bus_size_t ofs, const uint16_t *bufp, size_t count)
383{
384
385	if (__predict_false(bst == IA64_BUS_SPACE_IO))
386		bus_space_write_multi_io_2(bsh + ofs, bufp, count);
387	else {
388		while (count-- > 0)
389			ia64_st2((void *)(bsh + ofs), *bufp++);
390	}
391}
392
393static __inline void
394bus_space_write_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
395    bus_size_t ofs, const uint32_t *bufp, size_t count)
396{
397
398	if (__predict_false(bst == IA64_BUS_SPACE_IO))
399		bus_space_write_multi_io_4(bsh + ofs, bufp, count);
400	else {
401		while (count-- > 0)
402			ia64_st4((void *)(bsh + ofs), *bufp++);
403	}
404}
405
406static __inline void
407bus_space_write_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh,
408    bus_size_t ofs, const uint64_t *bufp, size_t count)
409{
410
411	if (__predict_false(bst == IA64_BUS_SPACE_IO))
412		bus_space_write_multi_io_8(bsh + ofs, bufp, count);
413	else {
414		while (count-- > 0)
415			ia64_st8((void *)(bsh + ofs), *bufp++);
416	}
417}
418
419
420/*
421 * Read count units of data from bus space described by the tag, handle and
422 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
423 * data is written to the buffer passed by reference and read from successive
424 * bus space addresses. Access is unordered.
425 */
426void bus_space_read_region_io_1(u_long, uint8_t *, size_t);
427void bus_space_read_region_io_2(u_long, uint16_t *, size_t);
428void bus_space_read_region_io_4(u_long, uint32_t *, size_t);
429void bus_space_read_region_io_8(u_long, uint64_t *, size_t);
430
431static __inline void
432bus_space_read_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
433    bus_size_t ofs, uint8_t *bufp, size_t count)
434{
435
436	if (__predict_false(bst == IA64_BUS_SPACE_IO))
437		bus_space_read_region_io_1(bsh + ofs, bufp, count);
438	else {
439		uint8_t *bsp = (void *)(bsh + ofs);
440		while (count-- > 0)
441			*bufp++ = ia64_ld1(bsp++);
442	}
443}
444
445static __inline void
446bus_space_read_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
447    bus_size_t ofs, uint16_t *bufp, size_t count)
448{
449
450	if (__predict_false(bst == IA64_BUS_SPACE_IO))
451		bus_space_read_region_io_2(bsh + ofs, bufp, count);
452	else {
453		uint16_t *bsp = (void *)(bsh + ofs);
454		while (count-- > 0)
455			*bufp++ = ia64_ld2(bsp++);
456	}
457}
458
459static __inline void
460bus_space_read_region_4(bus_space_tag_t bst, bus_space_handle_t bsh,
461    bus_size_t ofs, uint32_t *bufp, size_t count)
462{
463
464	if (__predict_false(bst == IA64_BUS_SPACE_IO))
465		bus_space_read_region_io_4(bsh + ofs, bufp, count);
466	else {
467		uint32_t *bsp = (void *)(bsh + ofs);
468		while (count-- > 0)
469			*bufp++ = ia64_ld4(bsp++);
470	}
471}
472
473static __inline void
474bus_space_read_region_8(bus_space_tag_t bst, bus_space_handle_t bsh,
475    bus_size_t ofs, uint64_t *bufp, size_t count)
476{
477
478	if (__predict_false(bst == IA64_BUS_SPACE_IO))
479		bus_space_read_region_io_8(bsh + ofs, bufp, count);
480	else {
481		uint64_t *bsp = (void *)(bsh + ofs);
482		while (count-- > 0)
483			*bufp++ = ia64_ld8(bsp++);
484	}
485}
486
487
488/*
489 * Write count units of data from bus space described by the tag, handle and
490 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
491 * data is read from the buffer passed by reference and written to successive
492 * bus space addresses. Access is unordered.
493 */
494void bus_space_write_region_io_1(u_long, const uint8_t *, size_t);
495void bus_space_write_region_io_2(u_long, const uint16_t *, size_t);
496void bus_space_write_region_io_4(u_long, const uint32_t *, size_t);
497void bus_space_write_region_io_8(u_long, const uint64_t *, size_t);
498
499static __inline void
500bus_space_write_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
501    bus_size_t ofs, const uint8_t *bufp, size_t count)
502{
503
504	if (__predict_false(bst == IA64_BUS_SPACE_IO))
505		bus_space_write_region_io_1(bsh + ofs, bufp, count);
506	else {
507		uint8_t *bsp = (void *)(bsh + ofs);
508		while (count-- > 0)
509			ia64_st1(bsp++, *bufp++);
510	}
511}
512
513static __inline void
514bus_space_write_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
515    bus_size_t ofs, const uint16_t *bufp, size_t count)
516{
517
518	if (__predict_false(bst == IA64_BUS_SPACE_IO))
519		bus_space_write_region_io_2(bsh + ofs, bufp, count);
520	else {
521		uint16_t *bsp = (void *)(bsh + ofs);
522		while (count-- > 0)
523			ia64_st2(bsp++, *bufp++);
524	}
525}
526
527static __inline void
528bus_space_write_region_4(bus_space_tag_t bst, bus_space_handle_t bsh,
529    bus_size_t ofs, const uint32_t *bufp, size_t count)
530{
531
532	if (__predict_false(bst == IA64_BUS_SPACE_IO))
533		bus_space_write_region_io_4(bsh + ofs, bufp, count);
534	else {
535		uint32_t *bsp = (void *)(bsh + ofs);
536		while (count-- > 0)
537			ia64_st4(bsp++, *bufp++);
538	}
539}
540
541static __inline void
542bus_space_write_region_8(bus_space_tag_t bst, bus_space_handle_t bsh,
543    bus_size_t ofs, const uint64_t *bufp, size_t count)
544{
545
546	if (__predict_false(bst == IA64_BUS_SPACE_IO))
547		bus_space_write_region_io_8(bsh + ofs, bufp, count);
548	else {
549		uint64_t *bsp = (void *)(bsh + ofs);
550		while (count-- > 0)
551			ia64_st8(bsp++, *bufp++);
552	}
553}
554
555
556/*
557 * Write count units of data from bus space described by the tag, handle and
558 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
559 * data is passed by value. Writes are unordered.
560 */
561static __inline void
562bus_space_set_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
563    bus_size_t ofs, uint8_t val, size_t count)
564{
565
566	while (count-- > 0)
567		bus_space_write_1(bst, bsh, ofs, val);
568}
569
570static __inline void
571bus_space_set_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
572    bus_size_t ofs, uint16_t val, size_t count)
573{
574
575	while (count-- > 0)
576		bus_space_write_2(bst, bsh, ofs, val);
577}
578
579static __inline void
580bus_space_set_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
581    bus_size_t ofs, uint32_t val, size_t count)
582{
583
584	while (count-- > 0)
585		bus_space_write_4(bst, bsh, ofs, val);
586}
587
588static __inline void
589bus_space_set_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh,
590    bus_size_t ofs, uint64_t val, size_t count)
591{
592
593	while (count-- > 0)
594		bus_space_write_8(bst, bsh, ofs, val);
595}
596
597
598/*
599 * Write count units of data from bus space described by the tag, handle and
600 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
601 * data is passed by value and written to successive bus space addresses.
602 * Writes are unordered.
603 */
604void bus_space_set_region_io_1(u_long, uint8_t, size_t);
605void bus_space_set_region_io_2(u_long, uint16_t, size_t);
606void bus_space_set_region_io_4(u_long, uint32_t, size_t);
607void bus_space_set_region_io_8(u_long, uint64_t, size_t);
608
609static __inline void
610bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
611    bus_size_t ofs, uint8_t val, size_t count)
612{
613
614	if (__predict_false(bst == IA64_BUS_SPACE_IO))
615		bus_space_set_region_io_1(bsh + ofs, val, count);
616	else {
617		uint8_t *bsp = (void *)(bsh + ofs);
618		while (count-- > 0)
619			ia64_st1(bsp++, val);
620	}
621}
622
623static __inline void
624bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
625    bus_size_t ofs, uint16_t val, size_t count)
626{
627
628	if (__predict_false(bst == IA64_BUS_SPACE_IO))
629		bus_space_set_region_io_2(bsh + ofs, val, count);
630	else {
631		uint16_t *bsp = (void *)(bsh + ofs);
632		while (count-- > 0)
633			ia64_st2(bsp++, val);
634	}
635}
636
637static __inline void
638bus_space_set_region_4(bus_space_tag_t bst, bus_space_handle_t bsh,
639    bus_size_t ofs, uint32_t val, size_t count)
640{
641
642	if (__predict_false(bst == IA64_BUS_SPACE_IO))
643		bus_space_set_region_io_4(bsh + ofs, val, count);
644	else {
645		uint32_t *bsp = (void *)(bsh + ofs);
646		while (count-- > 0)
647			ia64_st4(bsp++, val);
648	}
649}
650
651static __inline void
652bus_space_set_region_8(bus_space_tag_t bst, bus_space_handle_t bsh,
653    bus_size_t ofs, uint64_t val, size_t count)
654{
655
656	if (__predict_false(bst == IA64_BUS_SPACE_IO))
657		bus_space_set_region_io_4(bsh + ofs, val, count);
658	else {
659		uint64_t *bsp = (void *)(bsh + ofs);
660		while (count-- > 0)
661			ia64_st8(bsp++, val);
662	}
663}
664
665
666/*
667 * Copy count units of data from bus space described by the tag and the first
668 * handle and ofs pair to bus space described by the tag and the second handle
669 * and ofs pair. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes.
670 * The data is read from successive bus space addresses and also written to
671 * successive bus space addresses. Both reads and writes are unordered.
672 */
673void bus_space_copy_region_io_1(u_long, u_long, size_t);
674void bus_space_copy_region_io_2(u_long, u_long, size_t);
675void bus_space_copy_region_io_4(u_long, u_long, size_t);
676void bus_space_copy_region_io_8(u_long, u_long, size_t);
677
678static __inline void
679bus_space_copy_region_1(bus_space_tag_t bst, bus_space_handle_t sbsh,
680    bus_size_t sofs, bus_space_handle_t dbsh, bus_size_t dofs, size_t count)
681{
682	uint8_t *dst, *src;
683
684	if (__predict_false(bst == IA64_BUS_SPACE_IO)) {
685		bus_space_copy_region_io_1(sbsh + sofs, dbsh + dofs, count);
686		return;
687	}
688
689	src = (void *)(sbsh + sofs);
690	dst = (void *)(dbsh + dofs);
691	if (src < dst) {
692		src += count - 1;
693		dst += count - 1;
694		while (count-- > 0)
695			ia64_st1(dst--, ia64_ld1(src--));
696	} else {
697		while (count-- > 0)
698			ia64_st1(dst++, ia64_ld1(src++));
699	}
700}
701
702static __inline void
703bus_space_copy_region_2(bus_space_tag_t bst, bus_space_handle_t sbsh,
704    bus_size_t sofs, bus_space_handle_t dbsh, bus_size_t dofs, size_t count)
705{
706	uint16_t *dst, *src;
707
708	if (__predict_false(bst == IA64_BUS_SPACE_IO)) {
709		bus_space_copy_region_io_2(sbsh + sofs, dbsh + dofs, count);
710		return;
711	}
712
713	src = (void *)(sbsh + sofs);
714	dst = (void *)(dbsh + dofs);
715	if (src < dst) {
716		src += count - 1;
717		dst += count - 1;
718		while (count-- > 0)
719			ia64_st2(dst--, ia64_ld2(src--));
720	} else {
721		while (count-- > 0)
722			ia64_st2(dst++, ia64_ld2(src++));
723	}
724}
725
726static __inline void
727bus_space_copy_region_4(bus_space_tag_t bst, bus_space_handle_t sbsh,
728    bus_size_t sofs, bus_space_handle_t dbsh, bus_size_t dofs, size_t count)
729{
730	uint32_t *dst, *src;
731
732	if (__predict_false(bst == IA64_BUS_SPACE_IO)) {
733		bus_space_copy_region_io_4(sbsh + sofs, dbsh + dofs, count);
734		return;
735	}
736
737	src = (void *)(sbsh + sofs);
738	dst = (void *)(dbsh + dofs);
739	if (src < dst) {
740		src += count - 1;
741		dst += count - 1;
742		while (count-- > 0)
743			ia64_st4(dst--, ia64_ld4(src--));
744	} else {
745		while (count-- > 0)
746			ia64_st4(dst++, ia64_ld4(src++));
747	}
748}
749
750static __inline void
751bus_space_copy_region_8(bus_space_tag_t bst, bus_space_handle_t sbsh,
752    bus_size_t sofs, bus_space_handle_t dbsh, bus_size_t dofs, size_t count)
753{
754	uint64_t *dst, *src;
755
756	if (__predict_false(bst == IA64_BUS_SPACE_IO)) {
757		bus_space_copy_region_io_8(sbsh + sofs, dbsh + dofs, count);
758		return;
759	}
760
761	src = (void *)(sbsh + sofs);
762	dst = (void *)(dbsh + dofs);
763	if (src < dst) {
764		src += count - 1;
765		dst += count - 1;
766		while (count-- > 0)
767			ia64_st8(dst--, ia64_ld8(src--));
768	} else {
769		while (count-- > 0)
770			ia64_st8(dst++, ia64_ld8(src++));
771	}
772}
773
774
775/*
776 * Stream accesses are the same as normal accesses on ia64; there are no
777 * supported bus systems with an endianess different from the host one.
778 */
779
780#define	bus_space_read_stream_1		bus_space_read_1
781#define	bus_space_read_stream_2		bus_space_read_2
782#define	bus_space_read_stream_4		bus_space_read_4
783#define	bus_space_read_stream_8		bus_space_read_8
784
785#define	bus_space_write_stream_1	bus_space_write_1
786#define	bus_space_write_stream_2	bus_space_write_2
787#define	bus_space_write_stream_4	bus_space_write_4
788#define	bus_space_write_stream_8	bus_space_write_8
789
790#define	bus_space_read_multi_stream_1	bus_space_read_multi_1
791#define	bus_space_read_multi_stream_2	bus_space_read_multi_2
792#define	bus_space_read_multi_stream_4	bus_space_read_multi_4
793#define	bus_space_read_multi_stream_8	bus_space_read_multi_8
794
795#define	bus_space_write_multi_stream_1	bus_space_write_multi_1
796#define	bus_space_write_multi_stream_2	bus_space_write_multi_2
797#define	bus_space_write_multi_stream_4	bus_space_write_multi_4
798#define	bus_space_write_multi_stream_8	bus_space_write_multi_8
799
800#define	bus_space_read_region_stream_1	bus_space_read_region_1
801#define	bus_space_read_region_stream_2	bus_space_read_region_2
802#define	bus_space_read_region_stream_4	bus_space_read_region_4
803#define	bus_space_read_region_stream_8	bus_space_read_region_8
804
805#define	bus_space_write_region_stream_1	bus_space_write_region_1
806#define	bus_space_write_region_stream_2	bus_space_write_region_2
807#define	bus_space_write_region_stream_4	bus_space_write_region_4
808#define	bus_space_write_region_stream_8	bus_space_write_region_8
809
810#define	bus_space_set_multi_stream_1	bus_space_set_multi_1
811#define	bus_space_set_multi_stream_2	bus_space_set_multi_2
812#define	bus_space_set_multi_stream_4	bus_space_set_multi_4
813#define	bus_space_set_multi_stream_8	bus_space_set_multi_8
814
815#define	bus_space_set_region_stream_1	bus_space_set_region_1
816#define	bus_space_set_region_stream_2	bus_space_set_region_2
817#define	bus_space_set_region_stream_4	bus_space_set_region_4
818#define	bus_space_set_region_stream_8	bus_space_set_region_8
819
820#define	bus_space_copy_region_stream_1	bus_space_copy_region_1
821#define	bus_space_copy_region_stream_2	bus_space_copy_region_2
822#define	bus_space_copy_region_stream_4	bus_space_copy_region_4
823#define	bus_space_copy_region_stream_8	bus_space_copy_region_8
824
825#include <machine/bus_dma.h>
826
827#endif /* _MACHINE_BUS_H_ */
828