bus.h revision 115416
1/*	$NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $	*/
2
3/*-
4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *	This product includes software developed by the NetBSD
22 *	Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 *    contributors may be used to endorse or promote products derived
25 *    from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40/*
41 * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
42 * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
43 *
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
46 * are met:
47 * 1. Redistributions of source code must retain the above copyright
48 *    notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 *    notice, this list of conditions and the following disclaimer in the
51 *    documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 *    must display the following acknowledgement:
54 *      This product includes software developed by Christopher G. Demetriou
55 *	for the NetBSD Project.
56 * 4. The name of the author may not be used to endorse or promote products
57 *    derived from this software without specific prior written permission
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
60 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
61 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
62 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
63 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
64 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
65 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
66 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
67 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
68 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
69 */
70/* $FreeBSD: head/sys/ia64/include/bus.h 115416 2003-05-30 20:40:33Z hmp $ */
71
72#ifndef _MACHINE_BUS_H_
73#define _MACHINE_BUS_H_
74
75/*
76 * Platform notes:
77 * o	We don't use the _MACHINE_BUS_PIO_H_ and _MACHINE_BUS_MEMIO_H_
78 *	macros to conditionally compile for I/O port, memory mapped I/O
79 *	or both. It's a micro-optimization that is not worth the pain
80 *	because there is no I/O port space. I/O ports are emulated by
81 *	doing memory mapped I/O in a special memory range. The address
82 *	translation is slightly magic for I/O port accesses, but it does
83 *	not warrant the overhead.
84 *
85 */
86#define	_MACHINE_BUS_MEMIO_H_
87#define	_MACHINE_BUS_PIO_H_
88
89#include <machine/cpufunc.h>
90
91/*
92 * Values for the ia64 bus space tag, not to be used directly by MI code.
93 */
94#define	IA64_BUS_SPACE_IO	0	/* space is i/o space */
95#define IA64_BUS_SPACE_MEM	1	/* space is mem space */
96
97/*
98 * Bus address and size types
99 */
100typedef u_long bus_addr_t;
101typedef u_long bus_size_t;
102
103#define BUS_SPACE_MAXSIZE_24BIT	0xFFFFFF
104#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
105#define BUS_SPACE_MAXSIZE	0xFFFFFFFFFFFFFFFF
106#define BUS_SPACE_MAXADDR_24BIT	0xFFFFFF
107#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
108#define BUS_SPACE_MAXADDR	0xFFFFFFFF
109
110#define BUS_SPACE_UNRESTRICTED	(~0)
111
112/*
113 * Access methods for bus resources and address space.
114 */
115typedef	int bus_space_tag_t;
116typedef	u_long bus_space_handle_t;
117
118
119/*
120 * Map a region of device bus space into CPU virtual address space.
121 */
122#define	BUS_SPACE_MAP_CACHEABLE		0x01
123#define	BUS_SPACE_MAP_LINEAR		0x02
124
125int
126bus_space_map(bus_space_tag_t bst, bus_addr_t addr, bus_size_t size, int flags,
127    bus_space_handle_t *bshp);
128
129
130/*
131 * Unmap a region of device bus space.
132 */
133static __inline void
134bus_space_unmap(bus_space_tag_t bst __unused, bus_space_handle_t bsh __unused,
135    bus_size_t size __unused)
136{
137}
138
139
140/*
141 * Get a new handle for a subregion of an already-mapped area of bus space.
142 */
143static __inline int
144bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh,
145    bus_size_t ofs, bus_size_t size, bus_space_handle_t *nbshp)
146{
147	*nbshp = bsh + ofs;
148	return (0);
149}
150
151
152/*
153 * Allocate a region of memory that is accessible to devices in bus space.
154 */
155int
156bus_space_alloc(bus_space_tag_t bst, bus_addr_t rstart, bus_addr_t rend,
157    bus_size_t size, bus_size_t align, bus_size_t boundary, int flags,
158    bus_addr_t *addrp, bus_space_handle_t *bshp);
159
160
161/*
162 * Free a region of bus space accessible memory.
163 */
164void
165bus_space_free(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t size);
166
167
168/*
169 * Bus read/write barrier method.
170 */
171#define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
172#define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
173
174static __inline void
175bus_space_barrier(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
176    bus_size_t size, int flags)
177{
178	ia64_mf_a();
179	ia64_mf();
180}
181
182
183/*
184 * Read 1 unit of data from bus space described by the tag, handle and ofs
185 * tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
186 * data is returned.
187 */
188static __inline uint8_t
189bus_space_read_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
190{
191	uint8_t __volatile *bsp;
192	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
193	    __MEMIO_ADDR(bsh + ofs);
194	return (*bsp);
195}
196
197static __inline uint16_t
198bus_space_read_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
199{
200	uint16_t __volatile *bsp;
201	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
202	    __MEMIO_ADDR(bsh + ofs);
203	return (*bsp);
204}
205
206static __inline uint32_t
207bus_space_read_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
208{
209	uint32_t __volatile *bsp;
210	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
211	    __MEMIO_ADDR(bsh + ofs);
212	return (*bsp);
213}
214
215static __inline uint64_t
216bus_space_read_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
217{
218	uint64_t __volatile *bsp;
219	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
220	    __MEMIO_ADDR(bsh + ofs);
221	return (*bsp);
222}
223
224
225/*
226 * Write 1 unit of data to bus space described by the tag, handle and ofs
227 * tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
228 * data is passed by value.
229 */
230static __inline void
231bus_space_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
232    uint8_t val)
233{
234	uint8_t __volatile *bsp;
235	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
236	    __MEMIO_ADDR(bsh + ofs);
237	*bsp = val;
238}
239
240static __inline void
241bus_space_write_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
242    uint16_t val)
243{
244	uint16_t __volatile *bsp;
245	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
246	    __MEMIO_ADDR(bsh + ofs);
247	*bsp = val;
248}
249
250static __inline void
251bus_space_write_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
252    uint32_t val)
253{
254	uint32_t __volatile *bsp;
255	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
256	    __MEMIO_ADDR(bsh + ofs);
257	*bsp = val;
258}
259
260static __inline void
261bus_space_write_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
262    uint64_t val)
263{
264	uint64_t __volatile *bsp;
265	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
266	    __MEMIO_ADDR(bsh + ofs);
267	*bsp = val;
268}
269
270
271/*
272 * Read count units of data from bus space described by the tag, handle and
273 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
274 * data is returned in the buffer passed by reference.
275 */
276static __inline void
277bus_space_read_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
278    bus_size_t ofs, uint8_t *bufp, size_t count)
279{
280	uint8_t __volatile *bsp;
281	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
282	    __MEMIO_ADDR(bsh + ofs);
283	while (count-- > 0)
284		*bufp++ = *bsp;
285}
286
287static __inline void
288bus_space_read_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
289    bus_size_t ofs, uint16_t *bufp, size_t count)
290{
291	uint16_t __volatile *bsp;
292	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
293	    __MEMIO_ADDR(bsh + ofs);
294	while (count-- > 0)
295		*bufp++ = *bsp;
296}
297
298static __inline void
299bus_space_read_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
300    bus_size_t ofs, uint32_t *bufp, size_t count)
301{
302	uint32_t __volatile *bsp;
303	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
304	    __MEMIO_ADDR(bsh + ofs);
305	while (count-- > 0)
306		*bufp++ = *bsp;
307}
308
309static __inline void
310bus_space_read_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh,
311    bus_size_t ofs, uint64_t *bufp, size_t count)
312{
313	uint64_t __volatile *bsp;
314	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
315	    __MEMIO_ADDR(bsh + ofs);
316	while (count-- > 0)
317		*bufp++ = *bsp;
318}
319
320
321/*
322 * Write count units of data to bus space described by the tag, handle and
323 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
324 * data is read from the buffer passed by reference.
325 */
326static __inline void
327bus_space_write_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
328    bus_size_t ofs, const uint8_t *bufp, size_t count)
329{
330	uint8_t __volatile *bsp;
331	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
332	    __MEMIO_ADDR(bsh + ofs);
333	while (count-- > 0)
334		*bsp = *bufp++;
335}
336
337static __inline void
338bus_space_write_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
339    bus_size_t ofs, const uint16_t *bufp, size_t count)
340{
341	uint16_t __volatile *bsp;
342	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
343	    __MEMIO_ADDR(bsh + ofs);
344	while (count-- > 0)
345		*bsp = *bufp++;
346}
347
348static __inline void
349bus_space_write_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
350    bus_size_t ofs, const uint32_t *bufp, size_t count)
351{
352	uint32_t __volatile *bsp;
353	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
354	    __MEMIO_ADDR(bsh + ofs);
355	while (count-- > 0)
356		*bsp = *bufp++;
357}
358
359static __inline void
360bus_space_write_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh,
361    bus_size_t ofs, const uint64_t *bufp, size_t count)
362{
363	uint64_t __volatile *bsp;
364	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
365	    __MEMIO_ADDR(bsh + ofs);
366	while (count-- > 0)
367		*bsp = *bufp++;
368}
369
370
371/*
372 * Read count units of data from bus space described by the tag, handle and
373 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
374 * data is written to the buffer passed by reference and read from successive
375 * bus space addresses. Access is unordered.
376 */
377static __inline void
378bus_space_read_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
379    bus_size_t ofs, uint8_t *bufp, size_t count)
380{
381	uint8_t __volatile *bsp;
382	while (count-- > 0) {
383		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
384		    __MEMIO_ADDR(bsh + ofs);
385		*bufp++ = *bsp;
386		ofs += 1;
387	}
388}
389
390static __inline void
391bus_space_read_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
392    bus_size_t ofs, uint16_t *bufp, size_t count)
393{
394	uint16_t __volatile *bsp;
395	while (count-- > 0) {
396		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
397		    __MEMIO_ADDR(bsh + ofs);
398		*bufp++ = *bsp;
399		ofs += 2;
400	}
401}
402
403static __inline void
404bus_space_read_region_4(bus_space_tag_t bst, bus_space_handle_t bsh,
405    bus_size_t ofs, uint32_t *bufp, size_t count)
406{
407	uint32_t __volatile *bsp;
408	while (count-- > 0) {
409		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
410		    __MEMIO_ADDR(bsh + ofs);
411		*bufp++ = *bsp;
412		ofs += 4;
413	}
414}
415
416static __inline void
417bus_space_read_region_8(bus_space_tag_t bst, bus_space_handle_t bsh,
418    bus_size_t ofs, uint64_t *bufp, size_t count)
419{
420	uint64_t __volatile *bsp;
421	while (count-- > 0) {
422		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
423		    __MEMIO_ADDR(bsh + ofs);
424		*bufp++ = *bsp;
425		ofs += 8;
426	}
427}
428
429
430/*
431 * Write count units of data from bus space described by the tag, handle and
432 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
433 * data is read from the buffer passed by reference and written to successive
434 * bus space addresses. Access is unordered.
435 */
436static __inline void
437bus_space_write_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
438    bus_size_t ofs, const uint8_t *bufp, size_t count)
439{
440	uint8_t __volatile *bsp;
441	while (count-- > 0) {
442		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
443		    __MEMIO_ADDR(bsh + ofs);
444		*bsp = *bufp++;
445		ofs += 1;
446	}
447}
448
449static __inline void
450bus_space_write_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
451    bus_size_t ofs, const uint16_t *bufp, size_t count)
452{
453	uint16_t __volatile *bsp;
454	while (count-- > 0) {
455		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
456		    __MEMIO_ADDR(bsh + ofs);
457		*bsp = *bufp++;
458		ofs += 2;
459	}
460}
461
462static __inline void
463bus_space_write_region_4(bus_space_tag_t bst, bus_space_handle_t bsh,
464    bus_size_t ofs, const uint32_t *bufp, size_t count)
465{
466	uint32_t __volatile *bsp;
467	while (count-- > 0) {
468		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
469		    __MEMIO_ADDR(bsh + ofs);
470		*bsp = *bufp++;
471		ofs += 4;
472	}
473}
474
475static __inline void
476bus_space_write_region_8(bus_space_tag_t bst, bus_space_handle_t bsh,
477    bus_size_t ofs, const uint64_t *bufp, size_t count)
478{
479	uint64_t __volatile *bsp;
480	while (count-- > 0) {
481		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
482		    __MEMIO_ADDR(bsh + ofs);
483		*bsp = *bufp++;
484		ofs += 8;
485	}
486}
487
488
489/*
490 * Write count units of data from bus space described by the tag, handle and
491 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
492 * data is passed by value. Writes are unordered.
493 */
494static __inline void
495bus_space_set_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
496    bus_size_t ofs, uint8_t val, size_t count)
497{
498	uint8_t __volatile *bsp;
499	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
500	    __MEMIO_ADDR(bsh + ofs);
501	while (count-- > 0)
502		*bsp = val;
503}
504
505static __inline void
506bus_space_set_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
507    bus_size_t ofs, uint16_t val, size_t count)
508{
509	uint16_t __volatile *bsp;
510	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
511	    __MEMIO_ADDR(bsh + ofs);
512	while (count-- > 0)
513		*bsp = val;
514}
515
516static __inline void
517bus_space_set_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
518    bus_size_t ofs, uint32_t val, size_t count)
519{
520	uint32_t __volatile *bsp;
521	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
522	    __MEMIO_ADDR(bsh + ofs);
523	while (count-- > 0)
524		*bsp = val;
525}
526
527static __inline void
528bus_space_set_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh,
529    bus_size_t ofs, uint64_t val, size_t count)
530{
531	uint64_t __volatile *bsp;
532	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
533	    __MEMIO_ADDR(bsh + ofs);
534	while (count-- > 0)
535		*bsp = val;
536}
537
538
539/*
540 * Write count units of data from bus space described by the tag, handle and
541 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
542 * data is passed by value and written to successive bus space addresses.
543 * Writes are unordered.
544 */
545static __inline void
546bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
547    bus_size_t ofs, uint8_t val, size_t count)
548{
549	uint8_t __volatile *bsp;
550	while (count-- > 0) {
551		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
552		    __MEMIO_ADDR(bsh + ofs);
553		*bsp = val;
554		ofs += 1;
555	}
556}
557
558static __inline void
559bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
560    bus_size_t ofs, uint16_t val, size_t count)
561{
562	uint16_t __volatile *bsp;
563	while (count-- > 0) {
564		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
565		    __MEMIO_ADDR(bsh + ofs);
566		*bsp = val;
567		ofs += 2;
568	}
569}
570
571static __inline void
572bus_space_set_region_4(bus_space_tag_t bst, bus_space_handle_t bsh,
573    bus_size_t ofs, uint32_t val, size_t count)
574{
575	uint32_t __volatile *bsp;
576	while (count-- > 0) {
577		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
578		    __MEMIO_ADDR(bsh + ofs);
579		*bsp = val;
580		ofs += 4;
581	}
582}
583
584static __inline void
585bus_space_set_region_8(bus_space_tag_t bst, bus_space_handle_t bsh,
586    bus_size_t ofs, uint64_t val, size_t count)
587{
588	uint64_t __volatile *bsp;
589	while (count-- > 0) {
590		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
591		    __MEMIO_ADDR(bsh + ofs);
592		*bsp = val;
593		ofs += 8;
594	}
595}
596
597
598/*
599 * Copy count units of data from bus space described by the tag and the first
600 * handle and ofs pair to bus space described by the tag and the second handle
601 * and ofs pair. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes.
602 * The data is read from successive bus space addresses and also written to
603 * successive bus space addresses. Both reads and writes are unordered.
604 */
605static __inline void
606bus_space_copy_region_1(bus_space_tag_t bst, bus_space_handle_t bsh1,
607    bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count)
608{
609	bus_addr_t dst, src;
610	uint8_t __volatile *dstp, *srcp;
611	src = bsh1 + ofs1;
612	dst = bsh2 + ofs2;
613	if (dst > src) {
614		src += count - 1;
615		dst += count - 1;
616		while (count-- > 0) {
617			if (bst == IA64_BUS_SPACE_IO) {
618				srcp = __PIO_ADDR(src);
619				dstp = __PIO_ADDR(dst);
620			} else {
621				srcp = __MEMIO_ADDR(src);
622				dstp = __MEMIO_ADDR(dst);
623			}
624			*dstp = *srcp;
625			src -= 1;
626			dst -= 1;
627		}
628	} else {
629		while (count-- > 0) {
630			if (bst == IA64_BUS_SPACE_IO) {
631				srcp = __PIO_ADDR(src);
632				dstp = __PIO_ADDR(dst);
633			} else {
634				srcp = __MEMIO_ADDR(src);
635				dstp = __MEMIO_ADDR(dst);
636			}
637			*dstp = *srcp;
638			src += 1;
639			dst += 1;
640		}
641	}
642}
643
644static __inline void
645bus_space_copy_region_2(bus_space_tag_t bst, bus_space_handle_t bsh1,
646    bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count)
647{
648	bus_addr_t dst, src;
649	uint16_t __volatile *dstp, *srcp;
650	src = bsh1 + ofs1;
651	dst = bsh2 + ofs2;
652	if (dst > src) {
653		src += (count - 1) << 1;
654		dst += (count - 1) << 1;
655		while (count-- > 0) {
656			if (bst == IA64_BUS_SPACE_IO) {
657				srcp = __PIO_ADDR(src);
658				dstp = __PIO_ADDR(dst);
659			} else {
660				srcp = __MEMIO_ADDR(src);
661				dstp = __MEMIO_ADDR(dst);
662			}
663			*dstp = *srcp;
664			src -= 2;
665			dst -= 2;
666		}
667	} else {
668		while (count-- > 0) {
669			if (bst == IA64_BUS_SPACE_IO) {
670				srcp = __PIO_ADDR(src);
671				dstp = __PIO_ADDR(dst);
672			} else {
673				srcp = __MEMIO_ADDR(src);
674				dstp = __MEMIO_ADDR(dst);
675			}
676			*dstp = *srcp;
677			src += 2;
678			dst += 2;
679		}
680	}
681}
682
683static __inline void
684bus_space_copy_region_4(bus_space_tag_t bst, bus_space_handle_t bsh1,
685    bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count)
686{
687	bus_addr_t dst, src;
688	uint32_t __volatile *dstp, *srcp;
689	src = bsh1 + ofs1;
690	dst = bsh2 + ofs2;
691	if (dst > src) {
692		src += (count - 1) << 2;
693		dst += (count - 1) << 2;
694		while (count-- > 0) {
695			if (bst == IA64_BUS_SPACE_IO) {
696				srcp = __PIO_ADDR(src);
697				dstp = __PIO_ADDR(dst);
698			} else {
699				srcp = __MEMIO_ADDR(src);
700				dstp = __MEMIO_ADDR(dst);
701			}
702			*dstp = *srcp;
703			src -= 4;
704			dst -= 4;
705		}
706	} else {
707		while (count-- > 0) {
708			if (bst == IA64_BUS_SPACE_IO) {
709				srcp = __PIO_ADDR(src);
710				dstp = __PIO_ADDR(dst);
711			} else {
712				srcp = __MEMIO_ADDR(src);
713				dstp = __MEMIO_ADDR(dst);
714			}
715			*dstp = *srcp;
716			src += 4;
717			dst += 4;
718		}
719	}
720}
721
722static __inline void
723bus_space_copy_region_8(bus_space_tag_t bst, bus_space_handle_t bsh1,
724    bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count)
725{
726	bus_addr_t dst, src;
727	uint64_t __volatile *dstp, *srcp;
728	src = bsh1 + ofs1;
729	dst = bsh2 + ofs2;
730	if (dst > src) {
731		src += (count - 1) << 3;
732		dst += (count - 1) << 3;
733		while (count-- > 0) {
734			if (bst == IA64_BUS_SPACE_IO) {
735				srcp = __PIO_ADDR(src);
736				dstp = __PIO_ADDR(dst);
737			} else {
738				srcp = __MEMIO_ADDR(src);
739				dstp = __MEMIO_ADDR(dst);
740			}
741			*dstp = *srcp;
742			src -= 8;
743			dst -= 8;
744		}
745	} else {
746		while (count-- > 0) {
747			if (bst == IA64_BUS_SPACE_IO) {
748				srcp = __PIO_ADDR(src);
749				dstp = __PIO_ADDR(dst);
750			} else {
751				srcp = __MEMIO_ADDR(src);
752				dstp = __MEMIO_ADDR(dst);
753			}
754			*dstp = *srcp;
755			src += 8;
756			dst += 8;
757		}
758	}
759}
760
761
762/*
763 * Stream accesses are the same as normal accesses on ia64; there are no
764 * supported bus systems with an endianess different from the host one.
765 */
766#define	bus_space_read_stream_1(t, h, o)	\
767	bus_space_read_1(t, h, o)
768#define	bus_space_read_stream_2(t, h, o)	\
769	bus_space_read_2(t, h, o)
770#define	bus_space_read_stream_4(t, h, o)	\
771	bus_space_read_4(t, h, o)
772#define	bus_space_read_stream_8(t, h, o)	\
773	bus_space_read_8(t, h, o)
774
775#define	bus_space_read_multi_stream_1(t, h, o, a, c)	\
776	bus_space_read_multi_1(t, h, o, a, c)
777#define	bus_space_read_multi_stream_2(t, h, o, a, c)	\
778	bus_space_read_multi_2(t, h, o, a, c)
779#define	bus_space_read_multi_stream_4(t, h, o, a, c)	\
780	bus_space_read_multi_4(t, h, o, a, c)
781#define	bus_space_read_multi_stream_8(t, h, o, a, c)	\
782	bus_space_read_multi_8(t, h, o, a, c)
783
784#define	bus_space_write_stream_1(t, h, o, v)	\
785	bus_space_write_1(t, h, o, v)
786#define	bus_space_write_stream_2(t, h, o, v)	\
787	bus_space_write_2(t, h, o, v)
788#define	bus_space_write_stream_4(t, h, o, v)	\
789	bus_space_write_4(t, h, o, v)
790#define	bus_space_write_stream_8(t, h, o, v)	\
791	bus_space_write_8(t, h, o, v)
792
793#define	bus_space_write_multi_stream_1(t, h, o, a, c)	\
794	bus_space_write_multi_1(t, h, o, a, c)
795#define	bus_space_write_multi_stream_2(t, h, o, a, c)	\
796	bus_space_write_multi_2(t, h, o, a, c)
797#define	bus_space_write_multi_stream_4(t, h, o, a, c)	\
798	bus_space_write_multi_4(t, h, o, a, c)
799#define	bus_space_write_multi_stream_8(t, h, o, a, c)	\
800	bus_space_write_multi_8(t, h, o, a, c)
801
802#define	bus_space_set_multi_stream_1(t, h, o, v, c)	\
803	bus_space_set_multi_1(t, h, o, v, c)
804#define	bus_space_set_multi_stream_2(t, h, o, v, c)	\
805	bus_space_set_multi_2(t, h, o, v, c)
806#define	bus_space_set_multi_stream_4(t, h, o, v, c)	\
807	bus_space_set_multi_4(t, h, o, v, c)
808#define	bus_space_set_multi_stream_8(t, h, o, v, c)	\
809	bus_space_set_multi_8(t, h, o, v, c)
810
811#define	bus_space_read_region_stream_1(t, h, o, a, c)	\
812	bus_space_read_region_1(t, h, o, a, c)
813#define	bus_space_read_region_stream_2(t, h, o, a, c)	\
814	bus_space_read_region_2(t, h, o, a, c)
815#define	bus_space_read_region_stream_4(t, h, o, a, c)	\
816	bus_space_read_region_4(t, h, o, a, c)
817#define	bus_space_read_region_stream_8(t, h, o, a, c)	\
818	bus_space_read_region_8(t, h, o, a, c)
819
820#define	bus_space_write_region_stream_1(t, h, o, a, c)	\
821	bus_space_write_region_1(t, h, o, a, c)
822#define	bus_space_write_region_stream_2(t, h, o, a, c)	\
823	bus_space_write_region_2(t, h, o, a, c)
824#define	bus_space_write_region_stream_4(t, h, o, a, c)	\
825	bus_space_write_region_4(t, h, o, a, c)
826#define	bus_space_write_region_stream_8(t, h, o, a, c)	\
827	bus_space_write_region_8(t, h, o, a, c)
828
829#define	bus_space_set_region_stream_1(t, h, o, v, c)	\
830	bus_space_set_region_1(t, h, o, v, c)
831#define	bus_space_set_region_stream_2(t, h, o, v, c)	\
832	bus_space_set_region_2(t, h, o, v, c)
833#define	bus_space_set_region_stream_4(t, h, o, v, c)	\
834	bus_space_set_region_4(t, h, o, v, c)
835#define	bus_space_set_region_stream_8(t, h, o, v, c)	\
836	bus_space_set_region_8(t, h, o, v, c)
837
838#define	bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c)	\
839	bus_space_copy_region_1(t, h1, o1, h2, o2, c)
840#define	bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c)	\
841	bus_space_copy_region_2(t, h1, o1, h2, o2, c)
842#define	bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c)	\
843	bus_space_copy_region_4(t, h1, o1, h2, o2, c)
844#define	bus_space_copy_region_stream_8(t, h1, o1, h2, o2, c)	\
845	bus_space_copy_region_8(t, h1, o1, h2, o2, c)
846
847
848/*
849 * Flags used in various bus DMA methods.
850 */
851#define	BUS_DMA_WAITOK		0x00	/* safe to sleep (pseudo-flag) */
852#define	BUS_DMA_NOWAIT		0x01	/* not safe to sleep */
853#define	BUS_DMA_ALLOCNOW	0x02	/* perform resource allocation now */
854#define	BUS_DMA_COHERENT	0x04	/* hint: map memory in a coherent way */
855#define	BUS_DMA_ISA		0x10	/* map memory for ISA dma */
856#define	BUS_DMA_BUS2		0x20	/* placeholders for bus functions... */
857#define	BUS_DMA_BUS3		0x40
858#define	BUS_DMA_BUS4		0x80
859
860/* Forwards needed by prototypes below. */
861struct mbuf;
862struct uio;
863
864/*
865 *	Operations performed by bus_dmamap_sync().
866 */
867typedef int bus_dmasync_op_t;
868#define	BUS_DMASYNC_PREREAD	1
869#define	BUS_DMASYNC_POSTREAD	2
870#define	BUS_DMASYNC_PREWRITE	4
871#define	BUS_DMASYNC_POSTWRITE	8
872
873/*
874 *	bus_dma_tag_t
875 *
876 *	A machine-dependent opaque type describing the characteristics
877 *	of how to perform DMA mappings.  This structure encapsultes
878 *	information concerning address and alignment restrictions, number
879 *	of S/G	segments, amount of data per S/G segment, etc.
880 */
881typedef struct bus_dma_tag *bus_dma_tag_t;
882
883/*
884 *	bus_dmamap_t
885 *
886 *	DMA mapping instance information.
887 */
888typedef struct bus_dmamap *bus_dmamap_t;
889
890/*
891 *	bus_dma_segment_t
892 *
893 *	Describes a single contiguous DMA transaction.  Values
894 *	are suitable for programming into DMA registers.
895 */
896typedef struct bus_dma_segment {
897	bus_addr_t	ds_addr;	/* DMA address */
898	bus_size_t	ds_len;		/* length of transfer */
899} bus_dma_segment_t;
900
901/*
902 * A function that returns 1 if the address cannot be accessed by
903 * a device and 0 if it can be.
904 */
905typedef int bus_dma_filter_t(void *, bus_addr_t);
906
907/*
908 * Allocate a device specific dma_tag encapsulating the constraints of
909 * the parent tag in addition to other restrictions specified:
910 *
911 *	alignment:	alignment for segments.
912 *	boundary:	Boundary that segments cannot cross.
913 *	lowaddr:	Low restricted address that cannot appear in a mapping.
914 *	highaddr:	High restricted addr. that cannot appear in a mapping.
915 *	filtfunc:	An optional function to further test if an address
916 *			within the range of lowaddr and highaddr cannot appear
917 *			in a mapping.
918 *	filtfuncarg:	An argument that will be passed to filtfunc in addition
919 *			to the address to test.
920 *	maxsize:	Maximum mapping size supported by this tag.
921 *	nsegments:	Number of discontinuities allowed in maps.
922 *	maxsegsz:	Maximum size of a segment in the map.
923 *	flags:		Bus DMA flags.
924 *	dmat:		A pointer to set to a valid dma tag should the return
925 *			value of this function indicate success.
926 */
927/* XXX Should probably allow specification of alignment */
928int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignemnt,
929    bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr,
930    bus_dma_filter_t *filtfunc, void *filtfuncarg, bus_size_t maxsize,
931    int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat);
932
933int bus_dma_tag_destroy(bus_dma_tag_t dmat);
934
935/*
936 * Allocate a handle for mapping from kva/uva/physical
937 * address space into bus device space.
938 */
939int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp);
940
941/*
942 * Destroy  a handle for mapping from kva/uva/physical
943 * address space into bus device space.
944 */
945int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map);
946
947/*
948 * Allocate a piece of memory that can be efficiently mapped into
949 * bus device space based on the constraints lited in the dma tag.
950 * A dmamap to for use with dmamap_load is also allocated.
951 */
952int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
953    bus_dmamap_t *mapp);
954
955/*
956 * Free a piece of memory and it's allociated dmamap, that was allocated
957 * via bus_dmamem_alloc.
958 */
959void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map);
960
961/*
962 * A function that processes a successfully loaded dma map or an error
963 * from a delayed load map.
964 */
965typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
966
967/*
968 * Map the buffer buf into bus space using the dmamap map.
969 */
970int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
971    bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg,
972    int flags);
973
974/*
975 * Like bus_dmamap_callback but includes map size in bytes.  This is
976 * defined as a separate interface to maintain compatiiblity for users
977 * of bus_dmamap_callback_t--at some point these interfaces should be merged.
978 */
979typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int,
980    bus_size_t, int);
981
982/*
983 * Like bus_dmamap_load but for mbufs.  Note the use of the
984 * bus_dmamap_callback2_t interface.
985 */
986int bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map,
987    struct mbuf *mbuf, bus_dmamap_callback2_t *callback, void *callback_arg,
988    int flags);
989
990/*
991 * Like bus_dmamap_load but for uios.  Note the use of the
992 * bus_dmamap_callback2_t interface.
993 */
994int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *ui,
995    bus_dmamap_callback2_t *callback, void *callback_arg, int flags);
996
997/*
998 * Perform a syncronization operation on the given map.
999 */
1000void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, int);
1001static __inline void
1002bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t dmamap, bus_dmasync_op_t op)
1003{
1004	if ((dmamap) != NULL)
1005		_bus_dmamap_sync(dmat, dmamap, op);
1006}
1007
1008/*
1009 * Release the mapping held by map.
1010 */
1011void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map);
1012static __inline void
1013bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t dmamap)
1014{
1015	if ((dmamap) != NULL)
1016		_bus_dmamap_unload(dmat, dmamap);
1017}
1018
1019#endif /* _MACHINE_BUS_H_ */
1020