bus.h revision 122266
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 122266 2003-11-07 23:29:42Z scottl $ */
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
123static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
124				  bus_size_t size, int flags,
125				  bus_space_handle_t *bshp);
126
127static __inline int
128bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
129	      bus_size_t size __unused, int flags __unused,
130	      bus_space_handle_t *bshp)
131{
132
133	*bshp = addr;
134	return (0);
135}
136
137/*
138 * Unmap a region of device bus space.
139 */
140static __inline void
141bus_space_unmap(bus_space_tag_t bst __unused, bus_space_handle_t bsh __unused,
142    bus_size_t size __unused)
143{
144}
145
146
147/*
148 * Get a new handle for a subregion of an already-mapped area of bus space.
149 */
150static __inline int
151bus_space_subregion(bus_space_tag_t bst, bus_space_handle_t bsh,
152    bus_size_t ofs, bus_size_t size, bus_space_handle_t *nbshp)
153{
154	*nbshp = bsh + ofs;
155	return (0);
156}
157
158
159/*
160 * Allocate a region of memory that is accessible to devices in bus space.
161 */
162int
163bus_space_alloc(bus_space_tag_t bst, bus_addr_t rstart, bus_addr_t rend,
164    bus_size_t size, bus_size_t align, bus_size_t boundary, int flags,
165    bus_addr_t *addrp, bus_space_handle_t *bshp);
166
167
168/*
169 * Free a region of bus space accessible memory.
170 */
171void
172bus_space_free(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t size);
173
174
175/*
176 * Bus read/write barrier method.
177 */
178#define	BUS_SPACE_BARRIER_READ	0x01		/* force read barrier */
179#define	BUS_SPACE_BARRIER_WRITE	0x02		/* force write barrier */
180
181static __inline void
182bus_space_barrier(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
183    bus_size_t size, int flags)
184{
185	ia64_mf_a();
186	ia64_mf();
187}
188
189
190/*
191 * Read 1 unit of data from bus space described by the tag, handle and ofs
192 * tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
193 * data is returned.
194 */
195static __inline uint8_t
196bus_space_read_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
197{
198	uint8_t __volatile *bsp;
199	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
200	    __MEMIO_ADDR(bsh + ofs);
201	return (*bsp);
202}
203
204static __inline uint16_t
205bus_space_read_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
206{
207	uint16_t __volatile *bsp;
208	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
209	    __MEMIO_ADDR(bsh + ofs);
210	return (*bsp);
211}
212
213static __inline uint32_t
214bus_space_read_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
215{
216	uint32_t __volatile *bsp;
217	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
218	    __MEMIO_ADDR(bsh + ofs);
219	return (*bsp);
220}
221
222static __inline uint64_t
223bus_space_read_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
224{
225	uint64_t __volatile *bsp;
226	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
227	    __MEMIO_ADDR(bsh + ofs);
228	return (*bsp);
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 */
237static __inline void
238bus_space_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
239    uint8_t val)
240{
241	uint8_t __volatile *bsp;
242	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
243	    __MEMIO_ADDR(bsh + ofs);
244	*bsp = val;
245}
246
247static __inline void
248bus_space_write_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
249    uint16_t val)
250{
251	uint16_t __volatile *bsp;
252	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
253	    __MEMIO_ADDR(bsh + ofs);
254	*bsp = val;
255}
256
257static __inline void
258bus_space_write_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
259    uint32_t val)
260{
261	uint32_t __volatile *bsp;
262	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
263	    __MEMIO_ADDR(bsh + ofs);
264	*bsp = val;
265}
266
267static __inline void
268bus_space_write_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
269    uint64_t val)
270{
271	uint64_t __volatile *bsp;
272	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
273	    __MEMIO_ADDR(bsh + ofs);
274	*bsp = val;
275}
276
277
278/*
279 * Read count units of data from bus space described by the tag, handle and
280 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
281 * data is returned in the buffer passed by reference.
282 */
283static __inline void
284bus_space_read_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
285    bus_size_t ofs, uint8_t *bufp, size_t count)
286{
287	uint8_t __volatile *bsp;
288	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
289	    __MEMIO_ADDR(bsh + ofs);
290	while (count-- > 0)
291		*bufp++ = *bsp;
292}
293
294static __inline void
295bus_space_read_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
296    bus_size_t ofs, uint16_t *bufp, size_t count)
297{
298	uint16_t __volatile *bsp;
299	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
300	    __MEMIO_ADDR(bsh + ofs);
301	while (count-- > 0)
302		*bufp++ = *bsp;
303}
304
305static __inline void
306bus_space_read_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
307    bus_size_t ofs, uint32_t *bufp, size_t count)
308{
309	uint32_t __volatile *bsp;
310	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
311	    __MEMIO_ADDR(bsh + ofs);
312	while (count-- > 0)
313		*bufp++ = *bsp;
314}
315
316static __inline void
317bus_space_read_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh,
318    bus_size_t ofs, uint64_t *bufp, size_t count)
319{
320	uint64_t __volatile *bsp;
321	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
322	    __MEMIO_ADDR(bsh + ofs);
323	while (count-- > 0)
324		*bufp++ = *bsp;
325}
326
327
328/*
329 * Write count units of data to bus space described by the tag, handle and
330 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
331 * data is read from the buffer passed by reference.
332 */
333static __inline void
334bus_space_write_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
335    bus_size_t ofs, const uint8_t *bufp, size_t count)
336{
337	uint8_t __volatile *bsp;
338	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
339	    __MEMIO_ADDR(bsh + ofs);
340	while (count-- > 0)
341		*bsp = *bufp++;
342}
343
344static __inline void
345bus_space_write_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
346    bus_size_t ofs, const uint16_t *bufp, size_t count)
347{
348	uint16_t __volatile *bsp;
349	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
350	    __MEMIO_ADDR(bsh + ofs);
351	while (count-- > 0)
352		*bsp = *bufp++;
353}
354
355static __inline void
356bus_space_write_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
357    bus_size_t ofs, const uint32_t *bufp, size_t count)
358{
359	uint32_t __volatile *bsp;
360	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
361	    __MEMIO_ADDR(bsh + ofs);
362	while (count-- > 0)
363		*bsp = *bufp++;
364}
365
366static __inline void
367bus_space_write_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh,
368    bus_size_t ofs, const uint64_t *bufp, size_t count)
369{
370	uint64_t __volatile *bsp;
371	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
372	    __MEMIO_ADDR(bsh + ofs);
373	while (count-- > 0)
374		*bsp = *bufp++;
375}
376
377
378/*
379 * Read count units of data from bus space described by the tag, handle and
380 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
381 * data is written to the buffer passed by reference and read from successive
382 * bus space addresses. Access is unordered.
383 */
384static __inline void
385bus_space_read_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
386    bus_size_t ofs, uint8_t *bufp, size_t count)
387{
388	uint8_t __volatile *bsp;
389	while (count-- > 0) {
390		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
391		    __MEMIO_ADDR(bsh + ofs);
392		*bufp++ = *bsp;
393		ofs += 1;
394	}
395}
396
397static __inline void
398bus_space_read_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
399    bus_size_t ofs, uint16_t *bufp, size_t count)
400{
401	uint16_t __volatile *bsp;
402	while (count-- > 0) {
403		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
404		    __MEMIO_ADDR(bsh + ofs);
405		*bufp++ = *bsp;
406		ofs += 2;
407	}
408}
409
410static __inline void
411bus_space_read_region_4(bus_space_tag_t bst, bus_space_handle_t bsh,
412    bus_size_t ofs, uint32_t *bufp, size_t count)
413{
414	uint32_t __volatile *bsp;
415	while (count-- > 0) {
416		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
417		    __MEMIO_ADDR(bsh + ofs);
418		*bufp++ = *bsp;
419		ofs += 4;
420	}
421}
422
423static __inline void
424bus_space_read_region_8(bus_space_tag_t bst, bus_space_handle_t bsh,
425    bus_size_t ofs, uint64_t *bufp, size_t count)
426{
427	uint64_t __volatile *bsp;
428	while (count-- > 0) {
429		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
430		    __MEMIO_ADDR(bsh + ofs);
431		*bufp++ = *bsp;
432		ofs += 8;
433	}
434}
435
436
437/*
438 * Write count units of data from bus space described by the tag, handle and
439 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
440 * data is read from the buffer passed by reference and written to successive
441 * bus space addresses. Access is unordered.
442 */
443static __inline void
444bus_space_write_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
445    bus_size_t ofs, const uint8_t *bufp, size_t count)
446{
447	uint8_t __volatile *bsp;
448	while (count-- > 0) {
449		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
450		    __MEMIO_ADDR(bsh + ofs);
451		*bsp = *bufp++;
452		ofs += 1;
453	}
454}
455
456static __inline void
457bus_space_write_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
458    bus_size_t ofs, const uint16_t *bufp, size_t count)
459{
460	uint16_t __volatile *bsp;
461	while (count-- > 0) {
462		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
463		    __MEMIO_ADDR(bsh + ofs);
464		*bsp = *bufp++;
465		ofs += 2;
466	}
467}
468
469static __inline void
470bus_space_write_region_4(bus_space_tag_t bst, bus_space_handle_t bsh,
471    bus_size_t ofs, const uint32_t *bufp, size_t count)
472{
473	uint32_t __volatile *bsp;
474	while (count-- > 0) {
475		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
476		    __MEMIO_ADDR(bsh + ofs);
477		*bsp = *bufp++;
478		ofs += 4;
479	}
480}
481
482static __inline void
483bus_space_write_region_8(bus_space_tag_t bst, bus_space_handle_t bsh,
484    bus_size_t ofs, const uint64_t *bufp, size_t count)
485{
486	uint64_t __volatile *bsp;
487	while (count-- > 0) {
488		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
489		    __MEMIO_ADDR(bsh + ofs);
490		*bsp = *bufp++;
491		ofs += 8;
492	}
493}
494
495
496/*
497 * Write count units of data from bus space described by the tag, handle and
498 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
499 * data is passed by value. Writes are unordered.
500 */
501static __inline void
502bus_space_set_multi_1(bus_space_tag_t bst, bus_space_handle_t bsh,
503    bus_size_t ofs, uint8_t val, size_t count)
504{
505	uint8_t __volatile *bsp;
506	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
507	    __MEMIO_ADDR(bsh + ofs);
508	while (count-- > 0)
509		*bsp = val;
510}
511
512static __inline void
513bus_space_set_multi_2(bus_space_tag_t bst, bus_space_handle_t bsh,
514    bus_size_t ofs, uint16_t val, size_t count)
515{
516	uint16_t __volatile *bsp;
517	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
518	    __MEMIO_ADDR(bsh + ofs);
519	while (count-- > 0)
520		*bsp = val;
521}
522
523static __inline void
524bus_space_set_multi_4(bus_space_tag_t bst, bus_space_handle_t bsh,
525    bus_size_t ofs, uint32_t val, size_t count)
526{
527	uint32_t __volatile *bsp;
528	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
529	    __MEMIO_ADDR(bsh + ofs);
530	while (count-- > 0)
531		*bsp = val;
532}
533
534static __inline void
535bus_space_set_multi_8(bus_space_tag_t bst, bus_space_handle_t bsh,
536    bus_size_t ofs, uint64_t val, size_t count)
537{
538	uint64_t __volatile *bsp;
539	bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
540	    __MEMIO_ADDR(bsh + ofs);
541	while (count-- > 0)
542		*bsp = val;
543}
544
545
546/*
547 * Write count units of data from bus space described by the tag, handle and
548 * ofs tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
549 * data is passed by value and written to successive bus space addresses.
550 * Writes are unordered.
551 */
552static __inline void
553bus_space_set_region_1(bus_space_tag_t bst, bus_space_handle_t bsh,
554    bus_size_t ofs, uint8_t val, size_t count)
555{
556	uint8_t __volatile *bsp;
557	while (count-- > 0) {
558		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
559		    __MEMIO_ADDR(bsh + ofs);
560		*bsp = val;
561		ofs += 1;
562	}
563}
564
565static __inline void
566bus_space_set_region_2(bus_space_tag_t bst, bus_space_handle_t bsh,
567    bus_size_t ofs, uint16_t val, size_t count)
568{
569	uint16_t __volatile *bsp;
570	while (count-- > 0) {
571		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
572		    __MEMIO_ADDR(bsh + ofs);
573		*bsp = val;
574		ofs += 2;
575	}
576}
577
578static __inline void
579bus_space_set_region_4(bus_space_tag_t bst, bus_space_handle_t bsh,
580    bus_size_t ofs, uint32_t val, size_t count)
581{
582	uint32_t __volatile *bsp;
583	while (count-- > 0) {
584		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
585		    __MEMIO_ADDR(bsh + ofs);
586		*bsp = val;
587		ofs += 4;
588	}
589}
590
591static __inline void
592bus_space_set_region_8(bus_space_tag_t bst, bus_space_handle_t bsh,
593    bus_size_t ofs, uint64_t val, size_t count)
594{
595	uint64_t __volatile *bsp;
596	while (count-- > 0) {
597		bsp = (bst == IA64_BUS_SPACE_IO) ? __PIO_ADDR(bsh + ofs) :
598		    __MEMIO_ADDR(bsh + ofs);
599		*bsp = val;
600		ofs += 8;
601	}
602}
603
604
605/*
606 * Copy count units of data from bus space described by the tag and the first
607 * handle and ofs pair to bus space described by the tag and the second handle
608 * and ofs pair. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes.
609 * The data is read from successive bus space addresses and also written to
610 * successive bus space addresses. Both reads and writes are unordered.
611 */
612static __inline void
613bus_space_copy_region_1(bus_space_tag_t bst, bus_space_handle_t bsh1,
614    bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count)
615{
616	bus_addr_t dst, src;
617	uint8_t __volatile *dstp, *srcp;
618	src = bsh1 + ofs1;
619	dst = bsh2 + ofs2;
620	if (dst > src) {
621		src += count - 1;
622		dst += count - 1;
623		while (count-- > 0) {
624			if (bst == IA64_BUS_SPACE_IO) {
625				srcp = __PIO_ADDR(src);
626				dstp = __PIO_ADDR(dst);
627			} else {
628				srcp = __MEMIO_ADDR(src);
629				dstp = __MEMIO_ADDR(dst);
630			}
631			*dstp = *srcp;
632			src -= 1;
633			dst -= 1;
634		}
635	} else {
636		while (count-- > 0) {
637			if (bst == IA64_BUS_SPACE_IO) {
638				srcp = __PIO_ADDR(src);
639				dstp = __PIO_ADDR(dst);
640			} else {
641				srcp = __MEMIO_ADDR(src);
642				dstp = __MEMIO_ADDR(dst);
643			}
644			*dstp = *srcp;
645			src += 1;
646			dst += 1;
647		}
648	}
649}
650
651static __inline void
652bus_space_copy_region_2(bus_space_tag_t bst, bus_space_handle_t bsh1,
653    bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count)
654{
655	bus_addr_t dst, src;
656	uint16_t __volatile *dstp, *srcp;
657	src = bsh1 + ofs1;
658	dst = bsh2 + ofs2;
659	if (dst > src) {
660		src += (count - 1) << 1;
661		dst += (count - 1) << 1;
662		while (count-- > 0) {
663			if (bst == IA64_BUS_SPACE_IO) {
664				srcp = __PIO_ADDR(src);
665				dstp = __PIO_ADDR(dst);
666			} else {
667				srcp = __MEMIO_ADDR(src);
668				dstp = __MEMIO_ADDR(dst);
669			}
670			*dstp = *srcp;
671			src -= 2;
672			dst -= 2;
673		}
674	} else {
675		while (count-- > 0) {
676			if (bst == IA64_BUS_SPACE_IO) {
677				srcp = __PIO_ADDR(src);
678				dstp = __PIO_ADDR(dst);
679			} else {
680				srcp = __MEMIO_ADDR(src);
681				dstp = __MEMIO_ADDR(dst);
682			}
683			*dstp = *srcp;
684			src += 2;
685			dst += 2;
686		}
687	}
688}
689
690static __inline void
691bus_space_copy_region_4(bus_space_tag_t bst, bus_space_handle_t bsh1,
692    bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count)
693{
694	bus_addr_t dst, src;
695	uint32_t __volatile *dstp, *srcp;
696	src = bsh1 + ofs1;
697	dst = bsh2 + ofs2;
698	if (dst > src) {
699		src += (count - 1) << 2;
700		dst += (count - 1) << 2;
701		while (count-- > 0) {
702			if (bst == IA64_BUS_SPACE_IO) {
703				srcp = __PIO_ADDR(src);
704				dstp = __PIO_ADDR(dst);
705			} else {
706				srcp = __MEMIO_ADDR(src);
707				dstp = __MEMIO_ADDR(dst);
708			}
709			*dstp = *srcp;
710			src -= 4;
711			dst -= 4;
712		}
713	} else {
714		while (count-- > 0) {
715			if (bst == IA64_BUS_SPACE_IO) {
716				srcp = __PIO_ADDR(src);
717				dstp = __PIO_ADDR(dst);
718			} else {
719				srcp = __MEMIO_ADDR(src);
720				dstp = __MEMIO_ADDR(dst);
721			}
722			*dstp = *srcp;
723			src += 4;
724			dst += 4;
725		}
726	}
727}
728
729static __inline void
730bus_space_copy_region_8(bus_space_tag_t bst, bus_space_handle_t bsh1,
731    bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, size_t count)
732{
733	bus_addr_t dst, src;
734	uint64_t __volatile *dstp, *srcp;
735	src = bsh1 + ofs1;
736	dst = bsh2 + ofs2;
737	if (dst > src) {
738		src += (count - 1) << 3;
739		dst += (count - 1) << 3;
740		while (count-- > 0) {
741			if (bst == IA64_BUS_SPACE_IO) {
742				srcp = __PIO_ADDR(src);
743				dstp = __PIO_ADDR(dst);
744			} else {
745				srcp = __MEMIO_ADDR(src);
746				dstp = __MEMIO_ADDR(dst);
747			}
748			*dstp = *srcp;
749			src -= 8;
750			dst -= 8;
751		}
752	} else {
753		while (count-- > 0) {
754			if (bst == IA64_BUS_SPACE_IO) {
755				srcp = __PIO_ADDR(src);
756				dstp = __PIO_ADDR(dst);
757			} else {
758				srcp = __MEMIO_ADDR(src);
759				dstp = __MEMIO_ADDR(dst);
760			}
761			*dstp = *srcp;
762			src += 8;
763			dst += 8;
764		}
765	}
766}
767
768
769/*
770 * Stream accesses are the same as normal accesses on ia64; there are no
771 * supported bus systems with an endianess different from the host one.
772 */
773#define	bus_space_read_stream_1(t, h, o)	\
774	bus_space_read_1(t, h, o)
775#define	bus_space_read_stream_2(t, h, o)	\
776	bus_space_read_2(t, h, o)
777#define	bus_space_read_stream_4(t, h, o)	\
778	bus_space_read_4(t, h, o)
779#define	bus_space_read_stream_8(t, h, o)	\
780	bus_space_read_8(t, h, o)
781
782#define	bus_space_read_multi_stream_1(t, h, o, a, c)	\
783	bus_space_read_multi_1(t, h, o, a, c)
784#define	bus_space_read_multi_stream_2(t, h, o, a, c)	\
785	bus_space_read_multi_2(t, h, o, a, c)
786#define	bus_space_read_multi_stream_4(t, h, o, a, c)	\
787	bus_space_read_multi_4(t, h, o, a, c)
788#define	bus_space_read_multi_stream_8(t, h, o, a, c)	\
789	bus_space_read_multi_8(t, h, o, a, c)
790
791#define	bus_space_write_stream_1(t, h, o, v)	\
792	bus_space_write_1(t, h, o, v)
793#define	bus_space_write_stream_2(t, h, o, v)	\
794	bus_space_write_2(t, h, o, v)
795#define	bus_space_write_stream_4(t, h, o, v)	\
796	bus_space_write_4(t, h, o, v)
797#define	bus_space_write_stream_8(t, h, o, v)	\
798	bus_space_write_8(t, h, o, v)
799
800#define	bus_space_write_multi_stream_1(t, h, o, a, c)	\
801	bus_space_write_multi_1(t, h, o, a, c)
802#define	bus_space_write_multi_stream_2(t, h, o, a, c)	\
803	bus_space_write_multi_2(t, h, o, a, c)
804#define	bus_space_write_multi_stream_4(t, h, o, a, c)	\
805	bus_space_write_multi_4(t, h, o, a, c)
806#define	bus_space_write_multi_stream_8(t, h, o, a, c)	\
807	bus_space_write_multi_8(t, h, o, a, c)
808
809#define	bus_space_set_multi_stream_1(t, h, o, v, c)	\
810	bus_space_set_multi_1(t, h, o, v, c)
811#define	bus_space_set_multi_stream_2(t, h, o, v, c)	\
812	bus_space_set_multi_2(t, h, o, v, c)
813#define	bus_space_set_multi_stream_4(t, h, o, v, c)	\
814	bus_space_set_multi_4(t, h, o, v, c)
815#define	bus_space_set_multi_stream_8(t, h, o, v, c)	\
816	bus_space_set_multi_8(t, h, o, v, c)
817
818#define	bus_space_read_region_stream_1(t, h, o, a, c)	\
819	bus_space_read_region_1(t, h, o, a, c)
820#define	bus_space_read_region_stream_2(t, h, o, a, c)	\
821	bus_space_read_region_2(t, h, o, a, c)
822#define	bus_space_read_region_stream_4(t, h, o, a, c)	\
823	bus_space_read_region_4(t, h, o, a, c)
824#define	bus_space_read_region_stream_8(t, h, o, a, c)	\
825	bus_space_read_region_8(t, h, o, a, c)
826
827#define	bus_space_write_region_stream_1(t, h, o, a, c)	\
828	bus_space_write_region_1(t, h, o, a, c)
829#define	bus_space_write_region_stream_2(t, h, o, a, c)	\
830	bus_space_write_region_2(t, h, o, a, c)
831#define	bus_space_write_region_stream_4(t, h, o, a, c)	\
832	bus_space_write_region_4(t, h, o, a, c)
833#define	bus_space_write_region_stream_8(t, h, o, a, c)	\
834	bus_space_write_region_8(t, h, o, a, c)
835
836#define	bus_space_set_region_stream_1(t, h, o, v, c)	\
837	bus_space_set_region_1(t, h, o, v, c)
838#define	bus_space_set_region_stream_2(t, h, o, v, c)	\
839	bus_space_set_region_2(t, h, o, v, c)
840#define	bus_space_set_region_stream_4(t, h, o, v, c)	\
841	bus_space_set_region_4(t, h, o, v, c)
842#define	bus_space_set_region_stream_8(t, h, o, v, c)	\
843	bus_space_set_region_8(t, h, o, v, c)
844
845#define	bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c)	\
846	bus_space_copy_region_1(t, h1, o1, h2, o2, c)
847#define	bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c)	\
848	bus_space_copy_region_2(t, h1, o1, h2, o2, c)
849#define	bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c)	\
850	bus_space_copy_region_4(t, h1, o1, h2, o2, c)
851#define	bus_space_copy_region_stream_8(t, h1, o1, h2, o2, c)	\
852	bus_space_copy_region_8(t, h1, o1, h2, o2, c)
853
854
855/*
856 * Flags used in various bus DMA methods.
857 */
858#define	BUS_DMA_WAITOK		0x00	/* safe to sleep (pseudo-flag) */
859#define	BUS_DMA_NOWAIT		0x01	/* not safe to sleep */
860#define	BUS_DMA_ALLOCNOW	0x02	/* perform resource allocation now */
861#define	BUS_DMA_COHERENT	0x04	/* hint: map memory in a coherent way */
862#define	BUS_DMA_ZERO		0x08	/* allocate zero'ed memory */
863#define	BUS_DMA_ISA		0x10	/* map memory for ISA dma */
864#define	BUS_DMA_BUS2		0x20	/* placeholders for bus functions... */
865#define	BUS_DMA_BUS3		0x40
866#define	BUS_DMA_BUS4		0x80
867
868/* Forwards needed by prototypes below. */
869struct mbuf;
870struct uio;
871
872/*
873 *	Operations performed by bus_dmamap_sync().
874 */
875typedef int bus_dmasync_op_t;
876#define	BUS_DMASYNC_PREREAD	1
877#define	BUS_DMASYNC_POSTREAD	2
878#define	BUS_DMASYNC_PREWRITE	4
879#define	BUS_DMASYNC_POSTWRITE	8
880
881/*
882 *	bus_dma_tag_t
883 *
884 *	A machine-dependent opaque type describing the characteristics
885 *	of how to perform DMA mappings.  This structure encapsultes
886 *	information concerning address and alignment restrictions, number
887 *	of S/G	segments, amount of data per S/G segment, etc.
888 */
889typedef struct bus_dma_tag *bus_dma_tag_t;
890
891/*
892 *	bus_dmamap_t
893 *
894 *	DMA mapping instance information.
895 */
896typedef struct bus_dmamap *bus_dmamap_t;
897
898/*
899 *	bus_dma_segment_t
900 *
901 *	Describes a single contiguous DMA transaction.  Values
902 *	are suitable for programming into DMA registers.
903 */
904typedef struct bus_dma_segment {
905	bus_addr_t	ds_addr;	/* DMA address */
906	bus_size_t	ds_len;		/* length of transfer */
907} bus_dma_segment_t;
908
909/*
910 * A function that returns 1 if the address cannot be accessed by
911 * a device and 0 if it can be.
912 */
913typedef int bus_dma_filter_t(void *, bus_addr_t);
914
915/*
916 * A function that performs driver-specific syncronization on behalf of
917 * busdma.
918 */
919typedef enum {
920	BUS_DMA_LOCK	= 0x01,
921	BUS_DMA_UNLOCK	= 0x02,
922} bus_dma_lock_op_t;
923
924typedef void bus_dma_lock_t(void *, bus_dma_lock_op_t);
925
926/*
927 * Allocate a device specific dma_tag encapsulating the constraints of
928 * the parent tag in addition to other restrictions specified:
929 *
930 *	alignment:	alignment for segments.
931 *	boundary:	Boundary that segments cannot cross.
932 *	lowaddr:	Low restricted address that cannot appear in a mapping.
933 *	highaddr:	High restricted addr. that cannot appear in a mapping.
934 *	filtfunc:	An optional function to further test if an address
935 *			within the range of lowaddr and highaddr cannot appear
936 *			in a mapping.
937 *	filtfuncarg:	An argument that will be passed to filtfunc in addition
938 *			to the address to test.
939 *	maxsize:	Maximum mapping size supported by this tag.
940 *	nsegments:	Number of discontinuities allowed in maps.
941 *	maxsegsz:	Maximum size of a segment in the map.
942 *	flags:		Bus DMA flags.
943 *	lockfunc:	An optional function to handle driver-defined lock
944 *			operations.
945 *	lockfuncarg:	An argument that will be passed to lockfunc in addition
946 *			to the lock operation.
947 *	dmat:		A pointer to set to a valid dma tag should the return
948 *			value of this function indicate success.
949 */
950/* XXX Should probably allow specification of alignment */
951int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignemnt,
952    bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr,
953    bus_dma_filter_t *filtfunc, void *filtfuncarg, bus_size_t maxsize,
954    int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
955    void *lockfuncarg, bus_dma_tag_t *dmat);
956
957int bus_dma_tag_destroy(bus_dma_tag_t dmat);
958
959/*
960 * Allocate a handle for mapping from kva/uva/physical
961 * address space into bus device space.
962 */
963int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp);
964
965/*
966 * Destroy  a handle for mapping from kva/uva/physical
967 * address space into bus device space.
968 */
969int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map);
970
971/*
972 * Allocate a piece of memory that can be efficiently mapped into
973 * bus device space based on the constraints lited in the dma tag.
974 * A dmamap to for use with dmamap_load is also allocated.
975 */
976int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
977    bus_dmamap_t *mapp);
978
979/*
980 * Free a piece of memory and it's allociated dmamap, that was allocated
981 * via bus_dmamem_alloc.
982 */
983void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map);
984
985/*
986 * A function that processes a successfully loaded dma map or an error
987 * from a delayed load map.
988 */
989typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
990
991/*
992 * Map the buffer buf into bus space using the dmamap map.
993 */
994int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
995    bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg,
996    int flags);
997
998/*
999 * Like bus_dmamap_callback but includes map size in bytes.  This is
1000 * defined as a separate interface to maintain compatiiblity for users
1001 * of bus_dmamap_callback_t--at some point these interfaces should be merged.
1002 */
1003typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int,
1004    bus_size_t, int);
1005
1006/*
1007 * Like bus_dmamap_load but for mbufs.  Note the use of the
1008 * bus_dmamap_callback2_t interface.
1009 */
1010int bus_dmamap_load_mbuf(bus_dma_tag_t dmat, bus_dmamap_t map,
1011    struct mbuf *mbuf, bus_dmamap_callback2_t *callback, void *callback_arg,
1012    int flags);
1013
1014/*
1015 * Like bus_dmamap_load but for uios.  Note the use of the
1016 * bus_dmamap_callback2_t interface.
1017 */
1018int bus_dmamap_load_uio(bus_dma_tag_t dmat, bus_dmamap_t map, struct uio *ui,
1019    bus_dmamap_callback2_t *callback, void *callback_arg, int flags);
1020
1021/*
1022 * Perform a syncronization operation on the given map.
1023 */
1024void _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, int);
1025static __inline void
1026bus_dmamap_sync(bus_dma_tag_t dmat, bus_dmamap_t dmamap, bus_dmasync_op_t op)
1027{
1028	if ((dmamap) != NULL)
1029		_bus_dmamap_sync(dmat, dmamap, op);
1030}
1031
1032/*
1033 * Release the mapping held by map.
1034 */
1035void _bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map);
1036static __inline void
1037bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t dmamap)
1038{
1039	if ((dmamap) != NULL)
1040		_bus_dmamap_unload(dmat, dmamap);
1041}
1042
1043/*
1044 * Generic helper function for manipulating mutexes.
1045 */
1046void busdma_lock_mutex(void *arg, bus_dma_lock_op_t op);
1047#endif /* _MACHINE_BUS_H_ */
1048