bus.h revision 104486
1/*-
2 * Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
7 * NASA Ames Research Center.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by the NetBSD
20 *	Foundation, Inc. and its contributors.
21 * 4. Neither the name of The NetBSD Foundation nor the names of its
22 *    contributors may be used to endorse or promote products derived
23 *    from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37/*
38 * Copyright (c) 1997-1999 Eduardo E. Horvath. All rights reserved.
39 * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
40 * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 *    notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 *    notice, this list of conditions and the following disclaimer in the
49 *    documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software
51 *    must display the following acknowledgement:
52 *      This product includes software developed by Christopher G. Demetriou
53 *	for the NetBSD Project.
54 * 4. The name of the author may not be used to endorse or promote products
55 *    derived from this software without specific prior written permission
56 *
57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
61 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
62 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
63 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
64 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
65 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
66 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 *
68 * 	from: NetBSD: bus.h,v 1.28 2001/07/19 15:32:19 thorpej Exp
69 *	and
70 *	from: FreeBSD: src/sys/alpha/include/bus.h,v 1.9 2001/01/09
71 *
72 * $FreeBSD: head/sys/sparc64/include/bus.h 104486 2002-10-04 20:40:39Z sam $
73 */
74
75#ifndef	_MACHINE_BUS_H_
76#define	_MACHINE_BUS_H_
77
78#ifdef BUS_SPACE_DEBUG
79#include <sys/ktr.h>
80#endif
81
82#include <machine/cpufunc.h>
83#include <machine/upa.h>
84
85/*
86 * UPA and SBUS spaces are non-cached and big endian
87 * (except for RAM and PROM)
88 *
89 * PCI spaces are non-cached and little endian
90 */
91#define	UPA_BUS_SPACE		0
92#define	SBUS_BUS_SPACE		1
93#define	PCI_CONFIG_BUS_SPACE	2
94#define	PCI_IO_BUS_SPACE	3
95#define	PCI_MEMORY_BUS_SPACE	4
96#define	LAST_BUS_SPACE		5
97
98extern int bus_type_asi[];
99extern int bus_stream_asi[];
100
101#define __BUS_SPACE_HAS_STREAM_METHODS	1
102
103/*
104 * Bus address and size types
105 */
106typedef	u_long		bus_space_handle_t;
107typedef int		bus_type_t;
108typedef u_long		bus_addr_t;
109typedef u_long		bus_size_t;
110
111#define BUS_SPACE_MAXSIZE_24BIT	0xFFFFFF
112#define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
113#define BUS_SPACE_MAXSIZE	(128 * 1024) /* Maximum supported size */
114#define BUS_SPACE_MAXADDR_24BIT	0xFFFFFF
115#define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
116#define BUS_SPACE_MAXADDR	0xFFFFFFFF
117
118#define BUS_SPACE_UNRESTRICTED	(~0UL)
119
120/*
121 * Access methods for bus resources and address space.
122 */
123typedef struct bus_space_tag	*bus_space_tag_t;
124
125struct bus_space_tag {
126	void		*cookie;
127	bus_space_tag_t	parent;
128	int		type;
129
130	void		(*bus_barrier)(bus_space_tag_t,	bus_space_handle_t,
131	    bus_size_t, bus_size_t, int);
132};
133
134/*
135 * Helpers
136 */
137int sparc64_bus_mem_map(bus_space_tag_t, bus_space_handle_t, bus_size_t,
138    int, vm_offset_t, void **);
139int sparc64_bus_mem_unmap(void *, bus_size_t);
140bus_space_handle_t sparc64_fake_bustag(int, bus_addr_t,
141    struct bus_space_tag *);
142
143/*
144 * Bus space function prototypes.
145 */
146static void bus_space_barrier(bus_space_tag_t, bus_space_handle_t, bus_size_t,
147    bus_size_t, int);
148
149/* This macro finds the first "upstream" implementation of method `f' */
150#define _BS_CALL(t,f)							\
151	while (t->f == NULL)						\
152		t = t->parent;						\
153	return (*(t)->f)
154
155static __inline void
156bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
157    bus_size_t s, int f)
158{
159	_BS_CALL(t, bus_barrier)(t, h, o, s, f);
160}
161
162/* flags for bus space map functions */
163#define BUS_SPACE_MAP_CACHEABLE		0x0001
164#define BUS_SPACE_MAP_LINEAR		0x0002
165#define BUS_SPACE_MAP_READONLY		0x0004
166#define BUS_SPACE_MAP_PREFETCHABLE	0x0008
167/* placeholders for bus functions... */
168#define BUS_SPACE_MAP_BUS1		0x0100
169#define BUS_SPACE_MAP_BUS2		0x0200
170#define BUS_SPACE_MAP_BUS3		0x0400
171#define BUS_SPACE_MAP_BUS4		0x0800
172
173/* flags for bus_space_barrier() */
174#define	BUS_SPACE_BARRIER_READ		0x01	/* force read barrier */
175#define	BUS_SPACE_BARRIER_WRITE		0x02	/* force write barrier */
176
177#ifdef BUS_SPACE_DEBUG
178#define	KTR_BUS				KTR_CT2
179#define	BUS_HANDLE_MIN			UPA_MEMSTART
180#define	__BUS_DEBUG_ACCESS(h, o, desc, sz) do {				\
181	CTR4(KTR_BUS, "bus space: %s %d: handle %#lx, offset %#lx",	\
182	    (desc), (sz), (h), (o));					\
183	if ((h) + (o) < BUS_HANDLE_MIN)					\
184		panic("bus space access at %#lx out of range",		\
185		    (h) + (o));						\
186} while (0)
187#else
188#define	__BUS_DEBUG_ACCESS(h, o, desc, sz)
189#endif
190
191static __inline uint8_t
192bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
193{
194
195	__BUS_DEBUG_ACCESS(h, o, "read", 1);
196	return (lduba_nc((caddr_t)(h + o), bus_type_asi[t->type]));
197}
198
199static __inline uint16_t
200bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
201{
202
203	__BUS_DEBUG_ACCESS(h, o, "read", 2);
204	return (lduha_nc((caddr_t)(h + o), bus_type_asi[t->type]));
205}
206
207static __inline uint32_t
208bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
209{
210
211	__BUS_DEBUG_ACCESS(h, o, "read", 4);
212	return (lduwa_nc((caddr_t)(h + o), bus_type_asi[t->type]));
213}
214
215static __inline uint64_t
216bus_space_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
217{
218
219	__BUS_DEBUG_ACCESS(h, o, "read", 8);
220	return (ldxa_nc((caddr_t)(h + o), bus_type_asi[t->type]));
221}
222
223static __inline void
224bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
225    uint8_t *a, size_t c)
226{
227
228	while (c-- > 0)
229		*a++ = bus_space_read_1(t, h, o);
230}
231
232static __inline void
233bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
234    uint16_t *a, size_t c)
235{
236
237	while (c-- > 0)
238		*a++ = bus_space_read_2(t, h, o);
239}
240
241static __inline void
242bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
243    uint32_t *a, size_t c)
244{
245
246	while (c-- > 0)
247		*a++ = bus_space_read_4(t, h, o);
248}
249
250static __inline void
251bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
252    uint64_t *a, size_t c)
253{
254
255	while (c-- > 0)
256		*a++ = bus_space_read_8(t, h, o);
257}
258
259static __inline void
260bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
261    uint8_t v)
262{
263
264	__BUS_DEBUG_ACCESS(h, o, "write", 1);
265	stba_nc((caddr_t)(h + o), bus_type_asi[t->type], v);
266}
267
268static __inline void
269bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
270    uint16_t v)
271{
272
273	__BUS_DEBUG_ACCESS(h, o, "write", 2);
274	stha_nc((caddr_t)(h + o), bus_type_asi[t->type], v);
275}
276
277static __inline void
278bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
279    uint32_t v)
280{
281
282	__BUS_DEBUG_ACCESS(h, o, "write", 4);
283	stwa_nc((caddr_t)(h + o), bus_type_asi[t->type], v);
284}
285
286static __inline void
287bus_space_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
288    uint64_t v)
289{
290
291	__BUS_DEBUG_ACCESS(h, o, "write", 8);
292	stxa_nc((caddr_t)(h + o), bus_type_asi[t->type], v);
293}
294
295static __inline void
296bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
297    uint8_t *a, size_t c)
298{
299
300	while (c-- > 0)
301		bus_space_write_1(t, h, o, *a++);
302}
303
304static __inline void
305bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
306    uint16_t *a, size_t c)
307{
308
309	while (c-- > 0)
310		bus_space_write_2(t, h, o, *a++);
311}
312
313static __inline void
314bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
315    uint32_t *a, size_t c)
316{
317
318	while (c-- > 0)
319		bus_space_write_4(t, h, o, *a++);
320}
321
322static __inline void
323bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
324    uint64_t *a, size_t c)
325{
326
327	while (c-- > 0)
328		bus_space_write_8(t, h, o, *a++);
329}
330
331static __inline void
332bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
333    uint8_t v, size_t c)
334{
335
336	while (c-- > 0)
337		bus_space_write_1(t, h, o, v);
338}
339
340static __inline void
341bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
342    uint16_t v, size_t c)
343{
344
345	while (c-- > 0)
346		bus_space_write_2(t, h, o, v);
347}
348
349static __inline void
350bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
351    uint32_t v, size_t c)
352{
353
354	while (c-- > 0)
355		bus_space_write_4(t, h, o, v);
356}
357
358static __inline void
359bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
360    uint64_t v, size_t c)
361{
362
363	while (c-- > 0)
364		bus_space_write_8(t, h, o, v);
365}
366
367static __inline void
368bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
369    u_int8_t *a, bus_size_t c)
370{
371	for (; c; a++, c--, o++)
372		*a = bus_space_read_1(t, h, o);
373}
374
375static __inline void
376bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
377    u_int16_t *a, bus_size_t c)
378{
379	for (; c; a++, c--, o+=2)
380		*a = bus_space_read_2(t, h, o);
381}
382
383static __inline void
384bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
385    u_int32_t *a, bus_size_t c)
386{
387	for (; c; a++, c--, o+=4)
388		*a = bus_space_read_4(t, h, o);
389}
390
391static __inline void
392bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
393    u_int64_t *a, bus_size_t c)
394{
395	for (; c; a++, c--, o+=8)
396		*a = bus_space_read_8(t, h, o);
397}
398
399static __inline void
400bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
401    const u_int8_t *a, bus_size_t c)
402{
403	for (; c; a++, c--, o++)
404		bus_space_write_1(t, h, o, *a);
405}
406
407static __inline void
408bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
409    const u_int16_t *a, bus_size_t c)
410{
411	for (; c; a++, c--, o+=2)
412		bus_space_write_2(t, h, o, *a);
413}
414
415static __inline void
416bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
417    const u_int32_t *a, bus_size_t c)
418{
419	for (; c; a++, c--, o+=4)
420		bus_space_write_4(t, h, o, *a);
421}
422
423static __inline void
424bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
425    const u_int64_t *a, bus_size_t c)
426{
427	for (; c; a++, c--, o+=8)
428		bus_space_write_8(t, h, o, *a);
429}
430
431static __inline void
432bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
433    const u_int8_t v, bus_size_t c)
434{
435	for (; c; c--, o++)
436		bus_space_write_1(t, h, o, v);
437}
438
439static __inline void
440bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
441    const u_int16_t v, bus_size_t c)
442{
443	for (; c; c--, o+=2)
444		bus_space_write_2(t, h, o, v);
445}
446
447static __inline void
448bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
449    const u_int32_t v, bus_size_t c)
450{
451	for (; c; c--, o+=4)
452		bus_space_write_4(t, h, o, v);
453}
454
455static __inline void
456bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
457    const u_int64_t v, bus_size_t c)
458{
459	for (; c; c--, o+=8)
460		bus_space_write_8(t, h, o, v);
461}
462
463static __inline void
464bus_space_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1,
465    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
466{
467	for (; c; c--, o1++, o2++)
468	    bus_space_write_1(t, h1, o1, bus_space_read_1(t, h2, o2));
469}
470
471static __inline void
472bus_space_copy_region_2(bus_space_tag_t t, bus_space_handle_t h1,
473    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
474{
475	for (; c; c--, o1+=2, o2+=2)
476	    bus_space_write_2(t, h1, o1, bus_space_read_2(t, h2, o2));
477}
478
479static __inline void
480bus_space_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1,
481    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
482{
483	for (; c; c--, o1+=4, o2+=4)
484	    bus_space_write_4(t, h1, o1, bus_space_read_4(t, h2, o2));
485}
486
487static __inline void
488bus_space_copy_region_8(bus_space_tag_t t, bus_space_handle_t h1,
489    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
490{
491	for (; c; c--, o1+=8, o2+=8)
492	    bus_space_write_8(t, h1, o1, bus_space_read_8(t, h2, o2));
493}
494
495static __inline uint8_t
496bus_space_read_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
497{
498
499	__BUS_DEBUG_ACCESS(h, o, "read stream", 1);
500	return (lduba_nc((caddr_t)(h + o), bus_stream_asi[t->type]));
501}
502
503static __inline uint16_t
504bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
505{
506
507	__BUS_DEBUG_ACCESS(h, o, "read stream", 2);
508	return (lduha_nc((caddr_t)(h + o), bus_stream_asi[t->type]));
509}
510
511static __inline uint32_t
512bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
513{
514
515	__BUS_DEBUG_ACCESS(h, o, "read stream", 4);
516	return (lduwa_nc((caddr_t)(h + o), bus_stream_asi[t->type]));
517}
518
519static __inline uint64_t
520bus_space_read_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
521{
522
523	__BUS_DEBUG_ACCESS(h, o, "read stream", 8);
524	return (ldxa_nc((caddr_t)(h + o), bus_stream_asi[t->type]));
525}
526
527static __inline void
528bus_space_read_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
529    bus_size_t o, uint8_t *a, size_t c)
530{
531
532	while (c-- > 0)
533		*a++ = bus_space_read_stream_1(t, h, o);
534}
535
536static __inline void
537bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
538    bus_size_t o, uint16_t *a, size_t c)
539{
540
541	while (c-- > 0)
542		*a++ = bus_space_read_stream_2(t, h, o);
543}
544
545static __inline void
546bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
547    bus_size_t o, uint32_t *a, size_t c)
548{
549
550	while (c-- > 0)
551		*a++ = bus_space_read_stream_4(t, h, o);
552}
553
554static __inline void
555bus_space_read_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
556    bus_size_t o, uint64_t *a, size_t c)
557{
558
559	while (c-- > 0)
560		*a++ = bus_space_read_stream_8(t, h, o);
561}
562
563static __inline void
564bus_space_write_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
565    uint8_t v)
566{
567
568	__BUS_DEBUG_ACCESS(h, o, "write stream", 1);
569	stba_nc((caddr_t)(h + o), bus_stream_asi[t->type], v);
570}
571
572static __inline void
573bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
574    uint16_t v)
575{
576
577	__BUS_DEBUG_ACCESS(h, o, "write stream", 2);
578	stha_nc((caddr_t)(h + o), bus_stream_asi[t->type], v);
579}
580
581static __inline void
582bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
583    uint32_t v)
584{
585
586	__BUS_DEBUG_ACCESS(h, o, "write stream", 4);
587	stwa_nc((caddr_t)(h + o), bus_stream_asi[t->type], v);
588}
589
590static __inline void
591bus_space_write_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
592    uint64_t v)
593{
594
595	__BUS_DEBUG_ACCESS(h, o, "write stream", 8);
596	stxa_nc((caddr_t)(h + o), bus_stream_asi[t->type], v);
597}
598
599static __inline void
600bus_space_write_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
601    bus_size_t o, uint8_t *a, size_t c)
602{
603
604	while (c-- > 0)
605		bus_space_write_stream_1(t, h, o, *a++);
606}
607
608static __inline void
609bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
610    bus_size_t o, uint16_t *a, size_t c)
611{
612
613	while (c-- > 0)
614		bus_space_write_stream_2(t, h, o, *a++);
615}
616
617static __inline void
618bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
619    bus_size_t o, uint32_t *a, size_t c)
620{
621
622	while (c-- > 0)
623		bus_space_write_stream_4(t, h, o, *a++);
624}
625
626static __inline void
627bus_space_write_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
628    bus_size_t o, uint64_t *a, size_t c)
629{
630
631	while (c-- > 0)
632		bus_space_write_stream_8(t, h, o, *a++);
633}
634
635static __inline void
636bus_space_set_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
637    bus_size_t o, uint8_t v, size_t c)
638{
639
640	while (c-- > 0)
641		bus_space_write_stream_1(t, h, o, v);
642}
643
644static __inline void
645bus_space_set_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
646    bus_size_t o, uint16_t v, size_t c)
647{
648
649	while (c-- > 0)
650		bus_space_write_stream_2(t, h, o, v);
651}
652
653static __inline void
654bus_space_set_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
655    bus_size_t o, uint32_t v, size_t c)
656{
657
658	while (c-- > 0)
659		bus_space_write_stream_4(t, h, o, v);
660}
661
662static __inline void
663bus_space_set_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
664    bus_size_t o, uint64_t v, size_t c)
665{
666
667	while (c-- > 0)
668		bus_space_write_stream_8(t, h, o, v);
669}
670
671static __inline void
672bus_space_read_region_stream_1(bus_space_tag_t t, bus_space_handle_t h,
673    bus_size_t o, u_int8_t *a, bus_size_t c)
674{
675	for (; c; a++, c--, o++)
676		*a = bus_space_read_stream_1(t, h, o);
677}
678
679static __inline void
680bus_space_read_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
681    bus_size_t o, u_int16_t *a, bus_size_t c)
682{
683	for (; c; a++, c--, o+=2)
684		*a = bus_space_read_stream_2(t, h, o);
685}
686
687static __inline void
688bus_space_read_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
689    bus_size_t o, u_int32_t *a, bus_size_t c)
690{
691	for (; c; a++, c--, o+=4)
692		*a = bus_space_read_stream_4(t, h, o);
693}
694
695static __inline void
696bus_space_read_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
697    bus_size_t o, u_int64_t *a, bus_size_t c)
698{
699	for (; c; a++, c--, o+=8)
700		*a = bus_space_read_stream_8(t, h, o);
701}
702
703static __inline void
704bus_space_write_region_stream_1(bus_space_tag_t t, bus_space_handle_t h,
705    bus_size_t o, const u_int8_t *a, bus_size_t c)
706{
707	for (; c; a++, c--, o++)
708		bus_space_write_stream_1(t, h, o, *a);
709}
710
711static __inline void
712bus_space_write_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
713    bus_size_t o, const u_int16_t *a, bus_size_t c)
714{
715	for (; c; a++, c--, o+=2)
716		bus_space_write_stream_2(t, h, o, *a);
717}
718
719static __inline void
720bus_space_write_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
721    bus_size_t o, const u_int32_t *a, bus_size_t c)
722{
723	for (; c; a++, c--, o+=4)
724		bus_space_write_stream_4(t, h, o, *a);
725}
726
727static __inline void
728bus_space_write_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
729    bus_size_t o, const u_int64_t *a, bus_size_t c)
730{
731	for (; c; a++, c--, o+=8)
732		bus_space_write_stream_8(t, h, o, *a);
733}
734
735static __inline void
736bus_space_set_region_stream_1(bus_space_tag_t t, bus_space_handle_t h,
737    bus_size_t o, const u_int8_t v, bus_size_t c)
738{
739	for (; c; c--, o++)
740		bus_space_write_stream_1(t, h, o, v);
741}
742
743static __inline void
744bus_space_set_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
745    bus_size_t o, const u_int16_t v, bus_size_t c)
746{
747	for (; c; c--, o+=2)
748		bus_space_write_stream_2(t, h, o, v);
749}
750
751static __inline void
752bus_space_set_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
753    bus_size_t o, const u_int32_t v, bus_size_t c)
754{
755	for (; c; c--, o+=4)
756		bus_space_write_stream_4(t, h, o, v);
757}
758
759static __inline void
760bus_space_set_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
761    bus_size_t o, const u_int64_t v, bus_size_t c)
762{
763	for (; c; c--, o+=8)
764		bus_space_write_stream_8(t, h, o, v);
765}
766
767static __inline void
768bus_space_copy_region_stream_1(bus_space_tag_t t, bus_space_handle_t h1,
769    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
770{
771	for (; c; c--, o1++, o2++)
772	    bus_space_write_stream_1(t, h1, o1, bus_space_read_stream_1(t, h2,
773		o2));
774}
775
776static __inline void
777bus_space_copy_region_stream_2(bus_space_tag_t t, bus_space_handle_t h1,
778    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
779{
780	for (; c; c--, o1+=2, o2+=2)
781	    bus_space_write_stream_2(t, h1, o1, bus_space_read_stream_2(t, h2,
782		o2));
783}
784
785static __inline void
786bus_space_copy_region_stream_4(bus_space_tag_t t, bus_space_handle_t h1,
787    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
788{
789	for (; c; c--, o1+=4, o2+=4)
790	    bus_space_write_stream_4(t, h1, o1, bus_space_read_stream_4(t, h2,
791		o2));
792}
793
794static __inline void
795bus_space_copy_region_stream_8(bus_space_tag_t t, bus_space_handle_t h1,
796    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
797{
798	for (; c; c--, o1+=8, o2+=8)
799	    bus_space_write_stream_8(t, h1, o1, bus_space_read_8(t, h2, o2));
800}
801
802/* Back-compat functions for old ISA drivers */
803extern bus_space_tag_t isa_io_bt;
804extern bus_space_handle_t isa_io_hdl;
805extern bus_space_tag_t isa_mem_bt;
806extern bus_space_handle_t isa_mem_hdl;
807
808#define inb(o)		bus_space_read_1(isa_io_bt, isa_io_hdl, o)
809#define inw(o)		bus_space_read_2(isa_io_bt, isa_io_hdl, o)
810#define inl(o)		bus_space_read_4(isa_io_bt, isa_io_hdl, o)
811#define outb(o, v)	bus_space_write_1(isa_io_bt, isa_io_hdl, o, v)
812#define outw(o, v)	bus_space_write_2(isa_io_bt, isa_io_hdl, o, v)
813#define outl(o, v)	bus_space_write_4(isa_io_bt, isa_io_hdl, o, v)
814
815#define readb(o)	bus_space_read_1(isa_mem_bt, isa_mem_hdl, o)
816#define readw(o)	bus_space_read_2(isa_mem_bt, isa_mem_hdl, o)
817#define readl(o)	bus_space_read_4(isa_mem_bt, isa_mem_hdl, o)
818#define writeb(o, v)	bus_space_write_1(isa_mem_bt, isa_mem_hdl, o, v)
819#define writew(o, v)	bus_space_write_2(isa_mem_bt, isa_mem_hdl, o, v)
820#define writel(o, v)	bus_space_write_4(isa_mem_bt, isa_mem_hdl, o, v)
821
822#define insb(o, a, c) \
823	bus_space_read_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c)
824#define insw(o, a, c) \
825	bus_space_read_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c)
826#define insl(o, a, c) \
827	bus_space_read_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c)
828#define outsb(o, a, c) \
829	bus_space_write_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c)
830#define outsw(o, a, c) \
831	bus_space_write_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c)
832#define outsl(o, a, c) \
833	bus_space_write_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c)
834
835#define memcpy_fromio(d, s, c) \
836	bus_space_read_region_1(isa_mem_bt, isa_mem_hdl, s, d, c)
837#define memcpy_toio(d, s, c) \
838	bus_space_write_region_1(isa_mem_bt, isa_mem_hdl, d, s, c)
839#define memcpy_io(d, s, c) \
840	bus_space_copy_region_1(isa_mem_bt, isa_mem_hdl, s, isa_mem_hdl, d, c)
841#define memset_io(d, v, c) \
842	bus_space_set_region_1(isa_mem_bt, isa_mem_hdl, d, v, c)
843#define memsetw_io(d, v, c) \
844	bus_space_set_region_2(isa_mem_bt, isa_mem_hdl, d, v, c)
845
846static __inline void
847memsetw(void *d, int val, size_t size)
848{
849    u_int16_t *sp = d;
850
851    while (size--)
852	*sp++ = val;
853}
854
855/* DMA support */
856
857/*
858 * Flags used in various bus DMA methods.
859 */
860#define	BUS_DMA_WAITOK		0x000	/* safe to sleep (pseudo-flag) */
861#define	BUS_DMA_NOWAIT		0x001	/* not safe to sleep */
862#define	BUS_DMA_ALLOCNOW	0x002	/* perform resource allocation now */
863#define	BUS_DMAMEM_NOSYNC	0x004	/* map memory to not require sync */
864#define	BUS_DMA_NOWRITE		0x008
865#define	BUS_DMA_BUS1		0x010
866#define	BUS_DMA_BUS2		0x020
867#define	BUS_DMA_BUS3		0x040
868#define	BUS_DMA_BUS4		0x080
869/*
870 * The following flags are from NetBSD, but are not implemented for all
871 * architetures, and should therefore not be used in MI code.
872 * Some have different values than under NetBSD.
873 */
874#define	BUS_DMA_STREAMING	0x100	/* hint: sequential, unidirectional */
875#define	BUS_DMA_READ		0x200	/* mapping is device -> memory only */
876#define	BUS_DMA_WRITE		0x400	/* mapping is memory -> device only */
877#define	BUS_DMA_COHERENT	0x800	/* hint: map memory DMA coherent */
878
879#define	BUS_DMA_NOCACHE		BUS_DMA_BUS1
880/* Don't bother with alignment */
881#define	BUS_DMA_DVMA		BUS_DMA_BUS2
882
883/* Forwards needed by prototypes below. */
884struct mbuf;
885struct uio;
886
887typedef enum {
888	BUS_DMASYNC_PREREAD,
889	BUS_DMASYNC_POSTREAD,
890	BUS_DMASYNC_PREWRITE,
891	BUS_DMASYNC_POSTWRITE,
892} bus_dmasync_op_t;
893
894/*
895 * A function that returns 1 if the address cannot be accessed by
896 * a device and 0 if it can be.
897 */
898typedef int bus_dma_filter_t(void *, bus_addr_t);
899
900typedef struct bus_dma_tag	*bus_dma_tag_t;
901typedef struct bus_dmamap	*bus_dmamap_t;
902
903struct bus_dma_segment {
904	bus_addr_t	ds_addr;	/* DVMA address */
905	bus_size_t	ds_len;		/* length of transfer */
906};
907typedef struct bus_dma_segment	bus_dma_segment_t;
908
909/*
910 * A function that processes a successfully loaded dma map or an error
911 * from a delayed load map.
912 */
913typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
914
915/*
916 * Like bus_dmamap_callback but includes map size in bytes.  This is
917 * defined as a separate interface to maintain compatiiblity for users
918 * of bus_dmamap_callback_t--at some point these interfaces should be merged.
919 */
920typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int);
921
922/*
923 *	bus_dma_tag_t
924 *
925 *	A machine-dependent opaque type describing the implementation of
926 *	DMA for a given bus.
927 */
928struct bus_dma_tag {
929	void		*cookie;		/* cookie used in the guts */
930	bus_dma_tag_t	parent;
931	bus_size_t	alignment;
932	bus_size_t	boundary;
933	bus_addr_t	lowaddr;
934	bus_addr_t	highaddr;
935	bus_dma_filter_t	*filter;
936	void		*filterarg;
937	bus_size_t	maxsize;
938	u_int		nsegments;
939	bus_size_t	maxsegsz;
940	int		flags;
941	int		ref_count;
942	int		map_count;
943
944	/*
945	 * DMA mapping methods.
946	 */
947	int	(*dmamap_create)(bus_dma_tag_t, bus_dma_tag_t, int,
948	    bus_dmamap_t *);
949	int	(*dmamap_destroy)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t);
950	int	(*dmamap_load)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t,
951	    void *, bus_size_t, bus_dmamap_callback_t *, void *, int);
952	int	(*dmamap_load_mbuf)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t,
953	    struct mbuf *, bus_dmamap_callback2_t *, void *, int);
954	int	(*dmamap_load_uio)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t,
955	    struct uio *, bus_dmamap_callback2_t *, void *, int);
956	void	(*dmamap_unload)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t);
957	void	(*dmamap_sync)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t,
958	    bus_dmasync_op_t);
959
960	/*
961	 * DMA memory utility functions.
962	 */
963	int	(*dmamem_alloc)(bus_dma_tag_t, bus_dma_tag_t, void **, int,
964	    bus_dmamap_t *);
965	void	(*dmamem_free)(bus_dma_tag_t, bus_dma_tag_t, void *,
966	    bus_dmamap_t);
967};
968
969/*
970 * XXX: This is a kluge. It would be better to handle dma tags in a hierarchical
971 * way, and have a BUS_GET_DMA_TAG(); however, since this is not currently the
972 * case, save a root tag in the relevant bus attach function and use that.
973 * Keep the hierarchical structure, it might become needed in the future.
974 */
975extern bus_dma_tag_t sparc64_root_dma_tag;
976
977int bus_dma_tag_create(bus_dma_tag_t, bus_size_t, bus_size_t, bus_addr_t,
978    bus_addr_t, bus_dma_filter_t *, void *, bus_size_t, int, bus_size_t,
979    int, bus_dma_tag_t *);
980
981int bus_dma_tag_destroy(bus_dma_tag_t);
982
983int sparc64_dmamem_alloc_map(bus_dma_tag_t dmat, bus_dmamap_t *mapp);
984void sparc64_dmamem_free_map(bus_dma_tag_t dmat, bus_dmamap_t map);
985
986static __inline int
987sparc64_dmamap_create(bus_dma_tag_t pt, bus_dma_tag_t dt, int f,
988    bus_dmamap_t *p)
989{
990	bus_dma_tag_t lt;
991
992	for (lt = pt; lt->dmamap_create == NULL; lt = lt->parent)
993		;
994	return ((*lt->dmamap_create)(lt, dt, f, p));
995}
996#define	bus_dmamap_create(t, f, p)					\
997	sparc64_dmamap_create((t), (t), (f), (p))
998
999static __inline int
1000sparc64_dmamap_destroy(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t p)
1001{
1002	bus_dma_tag_t lt;
1003
1004	for (lt = pt; lt->dmamap_destroy == NULL; lt = lt->parent)
1005		;
1006	return ((*lt->dmamap_destroy)(lt, dt, p));
1007}
1008#define	bus_dmamap_destroy(t, p)					\
1009	sparc64_dmamap_destroy((t), (t), (p))
1010
1011static __inline int
1012sparc64_dmamap_load(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m,
1013    void *p, bus_size_t s, bus_dmamap_callback_t *cb, void *cba, int f)
1014{
1015	bus_dma_tag_t lt;
1016
1017	for (lt = pt; lt->dmamap_load == NULL; lt = lt->parent)
1018		;
1019	return ((*lt->dmamap_load)(lt, dt, m, p, s, cb, cba, f));
1020}
1021#define	bus_dmamap_load(t, m, p, s, cb, cba, f)				\
1022	sparc64_dmamap_load((t), (t), (m), (p), (s), (cb), (cba), (f))
1023
1024static __inline int
1025sparc64_dmamap_load_mbuf(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m,
1026    struct mbuf *mb, bus_dmamap_callback2_t *cb, void *cba, int f)
1027{
1028	bus_dma_tag_t lt;
1029
1030	for (lt = pt; lt->dmamap_load == NULL; lt = lt->parent)
1031		;
1032	return ((*lt->dmamap_load_mbuf)(lt, dt, m, mb, cb, cba, f));
1033}
1034#define	bus_dmamap_load_mbuf(t, m, mb, cb, cba, f)				\
1035	sparc64_dmamap_load_mbuf((t), (t), (m), (mb), (cb), (cba), (f))
1036
1037static __inline int
1038sparc64_dmamap_load_uio(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m,
1039    struct uio *ui, bus_dmamap_callback2_t *cb, void *cba, int f)
1040{
1041	bus_dma_tag_t lt;
1042
1043	for (lt = pt; lt->dmamap_load == NULL; lt = lt->parent)
1044		;
1045	return ((*lt->dmamap_load_uio)(lt, dt, m, ui, cb, cba, f));
1046}
1047#define	bus_dmamap_load_uio(t, m, ui, cb, cba, f)				\
1048	sparc64_dmamap_load_uio((t), (t), (m), (ui), (cb), (cba), (f))
1049
1050static __inline void
1051sparc64_dmamap_unload(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t p)
1052{
1053	bus_dma_tag_t lt;
1054
1055	for (lt = pt; lt->dmamap_unload == NULL; lt = lt->parent)
1056		;
1057	(*lt->dmamap_unload)(lt, dt, p);
1058}
1059#define	bus_dmamap_unload(t, p)						\
1060	sparc64_dmamap_unload((t), (t), (p))
1061
1062static __inline void
1063sparc64_dmamap_sync(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m,
1064    bus_dmasync_op_t op)
1065{
1066	bus_dma_tag_t lt;
1067
1068	for (lt = pt; lt->dmamap_sync == NULL; lt = lt->parent)
1069		;
1070	(*lt->dmamap_sync)(lt, dt, m, op);
1071}
1072#define	bus_dmamap_sync(t, m, op)					\
1073	sparc64_dmamap_sync((t), (t), (m), (op))
1074
1075static __inline int
1076sparc64_dmamem_alloc(bus_dma_tag_t pt, bus_dma_tag_t dt, void **v, int f,
1077    bus_dmamap_t *m)
1078{
1079	bus_dma_tag_t lt;
1080
1081	for (lt = pt; lt->dmamem_alloc == NULL; lt = lt->parent)
1082		;
1083	return ((*lt->dmamem_alloc)(lt, dt, v, f, m));
1084}
1085#define	bus_dmamem_alloc(t, v, f, m)					\
1086	sparc64_dmamem_alloc((t), (t), (v), (f), (m))
1087
1088static __inline void
1089sparc64_dmamem_free(bus_dma_tag_t pt, bus_dma_tag_t dt, void *v,
1090    bus_dmamap_t m)
1091{
1092	bus_dma_tag_t lt;
1093
1094	for (lt = pt; lt->dmamem_free == NULL; lt = lt->parent)
1095		;
1096	(*lt->dmamem_free)(lt, dt, v, m);
1097}
1098#define	bus_dmamem_free(t, v, m)					\
1099	sparc64_dmamem_free((t), (t), (v), (m))
1100
1101#endif /* !_MACHINE_BUS_H_ */
1102