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