bus.h revision 110030
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 110030 2003-01-29 07:25:27Z scottl $
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		*bst_cookie;
127	bus_space_tag_t	bst_parent;
128	int		bst_type;
129
130	void		(*bst_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);
148static int bus_space_subregion(bus_space_tag_t, bus_space_handle_t,
149    bus_size_t, bus_size_t, bus_space_handle_t *);
150
151/* This macro finds the first "upstream" implementation of method `f' */
152#define _BS_CALL(t,f)							\
153	while (t->f == NULL)						\
154		t = t->bst_parent;						\
155	return (*(t)->f)
156
157static __inline void
158bus_space_barrier(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
159    bus_size_t s, int f)
160{
161	_BS_CALL(t, bst_bus_barrier)(t, h, o, s, f);
162}
163
164static __inline int
165bus_space_subregion(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
166    bus_size_t s, bus_space_handle_t *hp)
167{
168	*hp = h + o;
169	return (0);
170}
171
172/* flags for bus space map functions */
173#define BUS_SPACE_MAP_CACHEABLE		0x0001
174#define BUS_SPACE_MAP_LINEAR		0x0002
175#define BUS_SPACE_MAP_READONLY		0x0004
176#define BUS_SPACE_MAP_PREFETCHABLE	0x0008
177/* placeholders for bus functions... */
178#define BUS_SPACE_MAP_BUS1		0x0100
179#define BUS_SPACE_MAP_BUS2		0x0200
180#define BUS_SPACE_MAP_BUS3		0x0400
181#define BUS_SPACE_MAP_BUS4		0x0800
182
183/* flags for bus_space_barrier() */
184#define	BUS_SPACE_BARRIER_READ		0x01	/* force read barrier */
185#define	BUS_SPACE_BARRIER_WRITE		0x02	/* force write barrier */
186
187#ifdef BUS_SPACE_DEBUG
188#define	KTR_BUS				KTR_CT2
189#define	BUS_HANDLE_MIN			UPA_MEMSTART
190#define	__BUS_DEBUG_ACCESS(h, o, desc, sz) do {				\
191	CTR4(KTR_BUS, "bus space: %s %d: handle %#lx, offset %#lx",	\
192	    (desc), (sz), (h), (o));					\
193	if ((h) + (o) < BUS_HANDLE_MIN)					\
194		panic("bus space access at %#lx out of range",		\
195		    (h) + (o));						\
196} while (0)
197#else
198#define	__BUS_DEBUG_ACCESS(h, o, desc, sz)
199#endif
200
201static __inline uint8_t
202bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
203{
204
205	__BUS_DEBUG_ACCESS(h, o, "read", 1);
206	return (lduba_nc((caddr_t)(h + o), bus_type_asi[t->bst_type]));
207}
208
209static __inline uint16_t
210bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
211{
212
213	__BUS_DEBUG_ACCESS(h, o, "read", 2);
214	return (lduha_nc((caddr_t)(h + o), bus_type_asi[t->bst_type]));
215}
216
217static __inline uint32_t
218bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
219{
220
221	__BUS_DEBUG_ACCESS(h, o, "read", 4);
222	return (lduwa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type]));
223}
224
225static __inline uint64_t
226bus_space_read_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
227{
228
229	__BUS_DEBUG_ACCESS(h, o, "read", 8);
230	return (ldxa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type]));
231}
232
233static __inline void
234bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
235    uint8_t *a, size_t c)
236{
237
238	while (c-- > 0)
239		*a++ = bus_space_read_1(t, h, o);
240}
241
242static __inline void
243bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
244    uint16_t *a, size_t c)
245{
246
247	while (c-- > 0)
248		*a++ = bus_space_read_2(t, h, o);
249}
250
251static __inline void
252bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
253    uint32_t *a, size_t c)
254{
255
256	while (c-- > 0)
257		*a++ = bus_space_read_4(t, h, o);
258}
259
260static __inline void
261bus_space_read_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
262    uint64_t *a, size_t c)
263{
264
265	while (c-- > 0)
266		*a++ = bus_space_read_8(t, h, o);
267}
268
269static __inline void
270bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
271    uint8_t v)
272{
273
274	__BUS_DEBUG_ACCESS(h, o, "write", 1);
275	stba_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v);
276}
277
278static __inline void
279bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
280    uint16_t v)
281{
282
283	__BUS_DEBUG_ACCESS(h, o, "write", 2);
284	stha_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v);
285}
286
287static __inline void
288bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
289    uint32_t v)
290{
291
292	__BUS_DEBUG_ACCESS(h, o, "write", 4);
293	stwa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v);
294}
295
296static __inline void
297bus_space_write_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
298    uint64_t v)
299{
300
301	__BUS_DEBUG_ACCESS(h, o, "write", 8);
302	stxa_nc((caddr_t)(h + o), bus_type_asi[t->bst_type], v);
303}
304
305static __inline void
306bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
307    uint8_t *a, size_t c)
308{
309
310	while (c-- > 0)
311		bus_space_write_1(t, h, o, *a++);
312}
313
314static __inline void
315bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
316    uint16_t *a, size_t c)
317{
318
319	while (c-- > 0)
320		bus_space_write_2(t, h, o, *a++);
321}
322
323static __inline void
324bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
325    uint32_t *a, size_t c)
326{
327
328	while (c-- > 0)
329		bus_space_write_4(t, h, o, *a++);
330}
331
332static __inline void
333bus_space_write_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
334    uint64_t *a, size_t c)
335{
336
337	while (c-- > 0)
338		bus_space_write_8(t, h, o, *a++);
339}
340
341static __inline void
342bus_space_set_multi_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
343    uint8_t v, size_t c)
344{
345
346	while (c-- > 0)
347		bus_space_write_1(t, h, o, v);
348}
349
350static __inline void
351bus_space_set_multi_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
352    uint16_t v, size_t c)
353{
354
355	while (c-- > 0)
356		bus_space_write_2(t, h, o, v);
357}
358
359static __inline void
360bus_space_set_multi_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
361    uint32_t v, size_t c)
362{
363
364	while (c-- > 0)
365		bus_space_write_4(t, h, o, v);
366}
367
368static __inline void
369bus_space_set_multi_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
370    uint64_t v, size_t c)
371{
372
373	while (c-- > 0)
374		bus_space_write_8(t, h, o, v);
375}
376
377static __inline void
378bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
379    u_int8_t *a, bus_size_t c)
380{
381	for (; c; a++, c--, o++)
382		*a = bus_space_read_1(t, h, o);
383}
384
385static __inline void
386bus_space_read_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
387    u_int16_t *a, bus_size_t c)
388{
389	for (; c; a++, c--, o+=2)
390		*a = bus_space_read_2(t, h, o);
391}
392
393static __inline void
394bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
395    u_int32_t *a, bus_size_t c)
396{
397	for (; c; a++, c--, o+=4)
398		*a = bus_space_read_4(t, h, o);
399}
400
401static __inline void
402bus_space_read_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
403    u_int64_t *a, bus_size_t c)
404{
405	for (; c; a++, c--, o+=8)
406		*a = bus_space_read_8(t, h, o);
407}
408
409static __inline void
410bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
411    const u_int8_t *a, bus_size_t c)
412{
413	for (; c; a++, c--, o++)
414		bus_space_write_1(t, h, o, *a);
415}
416
417static __inline void
418bus_space_write_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
419    const u_int16_t *a, bus_size_t c)
420{
421	for (; c; a++, c--, o+=2)
422		bus_space_write_2(t, h, o, *a);
423}
424
425static __inline void
426bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
427    const u_int32_t *a, bus_size_t c)
428{
429	for (; c; a++, c--, o+=4)
430		bus_space_write_4(t, h, o, *a);
431}
432
433static __inline void
434bus_space_write_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
435    const u_int64_t *a, bus_size_t c)
436{
437	for (; c; a++, c--, o+=8)
438		bus_space_write_8(t, h, o, *a);
439}
440
441static __inline void
442bus_space_set_region_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
443    const u_int8_t v, bus_size_t c)
444{
445	for (; c; c--, o++)
446		bus_space_write_1(t, h, o, v);
447}
448
449static __inline void
450bus_space_set_region_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
451    const u_int16_t v, bus_size_t c)
452{
453	for (; c; c--, o+=2)
454		bus_space_write_2(t, h, o, v);
455}
456
457static __inline void
458bus_space_set_region_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
459    const u_int32_t v, bus_size_t c)
460{
461	for (; c; c--, o+=4)
462		bus_space_write_4(t, h, o, v);
463}
464
465static __inline void
466bus_space_set_region_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
467    const u_int64_t v, bus_size_t c)
468{
469	for (; c; c--, o+=8)
470		bus_space_write_8(t, h, o, v);
471}
472
473static __inline void
474bus_space_copy_region_1(bus_space_tag_t t, bus_space_handle_t h1,
475    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
476{
477	for (; c; c--, o1++, o2++)
478	    bus_space_write_1(t, h1, o1, bus_space_read_1(t, h2, o2));
479}
480
481static __inline void
482bus_space_copy_region_2(bus_space_tag_t t, bus_space_handle_t h1,
483    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
484{
485	for (; c; c--, o1+=2, o2+=2)
486	    bus_space_write_2(t, h1, o1, bus_space_read_2(t, h2, o2));
487}
488
489static __inline void
490bus_space_copy_region_4(bus_space_tag_t t, bus_space_handle_t h1,
491    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
492{
493	for (; c; c--, o1+=4, o2+=4)
494	    bus_space_write_4(t, h1, o1, bus_space_read_4(t, h2, o2));
495}
496
497static __inline void
498bus_space_copy_region_8(bus_space_tag_t t, bus_space_handle_t h1,
499    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
500{
501	for (; c; c--, o1+=8, o2+=8)
502	    bus_space_write_8(t, h1, o1, bus_space_read_8(t, h2, o2));
503}
504
505static __inline uint8_t
506bus_space_read_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
507{
508
509	__BUS_DEBUG_ACCESS(h, o, "read stream", 1);
510	return (lduba_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type]));
511}
512
513static __inline uint16_t
514bus_space_read_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
515{
516
517	__BUS_DEBUG_ACCESS(h, o, "read stream", 2);
518	return (lduha_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type]));
519}
520
521static __inline uint32_t
522bus_space_read_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
523{
524
525	__BUS_DEBUG_ACCESS(h, o, "read stream", 4);
526	return (lduwa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type]));
527}
528
529static __inline uint64_t
530bus_space_read_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
531{
532
533	__BUS_DEBUG_ACCESS(h, o, "read stream", 8);
534	return (ldxa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type]));
535}
536
537static __inline void
538bus_space_read_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
539    bus_size_t o, uint8_t *a, size_t c)
540{
541
542	while (c-- > 0)
543		*a++ = bus_space_read_stream_1(t, h, o);
544}
545
546static __inline void
547bus_space_read_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
548    bus_size_t o, uint16_t *a, size_t c)
549{
550
551	while (c-- > 0)
552		*a++ = bus_space_read_stream_2(t, h, o);
553}
554
555static __inline void
556bus_space_read_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
557    bus_size_t o, uint32_t *a, size_t c)
558{
559
560	while (c-- > 0)
561		*a++ = bus_space_read_stream_4(t, h, o);
562}
563
564static __inline void
565bus_space_read_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
566    bus_size_t o, uint64_t *a, size_t c)
567{
568
569	while (c-- > 0)
570		*a++ = bus_space_read_stream_8(t, h, o);
571}
572
573static __inline void
574bus_space_write_stream_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
575    uint8_t v)
576{
577
578	__BUS_DEBUG_ACCESS(h, o, "write stream", 1);
579	stba_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v);
580}
581
582static __inline void
583bus_space_write_stream_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
584    uint16_t v)
585{
586
587	__BUS_DEBUG_ACCESS(h, o, "write stream", 2);
588	stha_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v);
589}
590
591static __inline void
592bus_space_write_stream_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
593    uint32_t v)
594{
595
596	__BUS_DEBUG_ACCESS(h, o, "write stream", 4);
597	stwa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v);
598}
599
600static __inline void
601bus_space_write_stream_8(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o,
602    uint64_t v)
603{
604
605	__BUS_DEBUG_ACCESS(h, o, "write stream", 8);
606	stxa_nc((caddr_t)(h + o), bus_stream_asi[t->bst_type], v);
607}
608
609static __inline void
610bus_space_write_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
611    bus_size_t o, uint8_t *a, size_t c)
612{
613
614	while (c-- > 0)
615		bus_space_write_stream_1(t, h, o, *a++);
616}
617
618static __inline void
619bus_space_write_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
620    bus_size_t o, uint16_t *a, size_t c)
621{
622
623	while (c-- > 0)
624		bus_space_write_stream_2(t, h, o, *a++);
625}
626
627static __inline void
628bus_space_write_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
629    bus_size_t o, uint32_t *a, size_t c)
630{
631
632	while (c-- > 0)
633		bus_space_write_stream_4(t, h, o, *a++);
634}
635
636static __inline void
637bus_space_write_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
638    bus_size_t o, uint64_t *a, size_t c)
639{
640
641	while (c-- > 0)
642		bus_space_write_stream_8(t, h, o, *a++);
643}
644
645static __inline void
646bus_space_set_multi_stream_1(bus_space_tag_t t, bus_space_handle_t h,
647    bus_size_t o, uint8_t v, size_t c)
648{
649
650	while (c-- > 0)
651		bus_space_write_stream_1(t, h, o, v);
652}
653
654static __inline void
655bus_space_set_multi_stream_2(bus_space_tag_t t, bus_space_handle_t h,
656    bus_size_t o, uint16_t v, size_t c)
657{
658
659	while (c-- > 0)
660		bus_space_write_stream_2(t, h, o, v);
661}
662
663static __inline void
664bus_space_set_multi_stream_4(bus_space_tag_t t, bus_space_handle_t h,
665    bus_size_t o, uint32_t v, size_t c)
666{
667
668	while (c-- > 0)
669		bus_space_write_stream_4(t, h, o, v);
670}
671
672static __inline void
673bus_space_set_multi_stream_8(bus_space_tag_t t, bus_space_handle_t h,
674    bus_size_t o, uint64_t v, size_t c)
675{
676
677	while (c-- > 0)
678		bus_space_write_stream_8(t, h, o, v);
679}
680
681static __inline void
682bus_space_read_region_stream_1(bus_space_tag_t t, bus_space_handle_t h,
683    bus_size_t o, u_int8_t *a, bus_size_t c)
684{
685	for (; c; a++, c--, o++)
686		*a = bus_space_read_stream_1(t, h, o);
687}
688
689static __inline void
690bus_space_read_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
691    bus_size_t o, u_int16_t *a, bus_size_t c)
692{
693	for (; c; a++, c--, o+=2)
694		*a = bus_space_read_stream_2(t, h, o);
695}
696
697static __inline void
698bus_space_read_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
699    bus_size_t o, u_int32_t *a, bus_size_t c)
700{
701	for (; c; a++, c--, o+=4)
702		*a = bus_space_read_stream_4(t, h, o);
703}
704
705static __inline void
706bus_space_read_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
707    bus_size_t o, u_int64_t *a, bus_size_t c)
708{
709	for (; c; a++, c--, o+=8)
710		*a = bus_space_read_stream_8(t, h, o);
711}
712
713static __inline void
714bus_space_write_region_stream_1(bus_space_tag_t t, bus_space_handle_t h,
715    bus_size_t o, const u_int8_t *a, bus_size_t c)
716{
717	for (; c; a++, c--, o++)
718		bus_space_write_stream_1(t, h, o, *a);
719}
720
721static __inline void
722bus_space_write_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
723    bus_size_t o, const u_int16_t *a, bus_size_t c)
724{
725	for (; c; a++, c--, o+=2)
726		bus_space_write_stream_2(t, h, o, *a);
727}
728
729static __inline void
730bus_space_write_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
731    bus_size_t o, const u_int32_t *a, bus_size_t c)
732{
733	for (; c; a++, c--, o+=4)
734		bus_space_write_stream_4(t, h, o, *a);
735}
736
737static __inline void
738bus_space_write_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
739    bus_size_t o, const u_int64_t *a, bus_size_t c)
740{
741	for (; c; a++, c--, o+=8)
742		bus_space_write_stream_8(t, h, o, *a);
743}
744
745static __inline void
746bus_space_set_region_stream_1(bus_space_tag_t t, bus_space_handle_t h,
747    bus_size_t o, const u_int8_t v, bus_size_t c)
748{
749	for (; c; c--, o++)
750		bus_space_write_stream_1(t, h, o, v);
751}
752
753static __inline void
754bus_space_set_region_stream_2(bus_space_tag_t t, bus_space_handle_t h,
755    bus_size_t o, const u_int16_t v, bus_size_t c)
756{
757	for (; c; c--, o+=2)
758		bus_space_write_stream_2(t, h, o, v);
759}
760
761static __inline void
762bus_space_set_region_stream_4(bus_space_tag_t t, bus_space_handle_t h,
763    bus_size_t o, const u_int32_t v, bus_size_t c)
764{
765	for (; c; c--, o+=4)
766		bus_space_write_stream_4(t, h, o, v);
767}
768
769static __inline void
770bus_space_set_region_stream_8(bus_space_tag_t t, bus_space_handle_t h,
771    bus_size_t o, const u_int64_t v, bus_size_t c)
772{
773	for (; c; c--, o+=8)
774		bus_space_write_stream_8(t, h, o, v);
775}
776
777static __inline void
778bus_space_copy_region_stream_1(bus_space_tag_t t, bus_space_handle_t h1,
779    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
780{
781	for (; c; c--, o1++, o2++)
782	    bus_space_write_stream_1(t, h1, o1, bus_space_read_stream_1(t, h2,
783		o2));
784}
785
786static __inline void
787bus_space_copy_region_stream_2(bus_space_tag_t t, bus_space_handle_t h1,
788    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
789{
790	for (; c; c--, o1+=2, o2+=2)
791	    bus_space_write_stream_2(t, h1, o1, bus_space_read_stream_2(t, h2,
792		o2));
793}
794
795static __inline void
796bus_space_copy_region_stream_4(bus_space_tag_t t, bus_space_handle_t h1,
797    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
798{
799	for (; c; c--, o1+=4, o2+=4)
800	    bus_space_write_stream_4(t, h1, o1, bus_space_read_stream_4(t, h2,
801		o2));
802}
803
804static __inline void
805bus_space_copy_region_stream_8(bus_space_tag_t t, bus_space_handle_t h1,
806    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
807{
808	for (; c; c--, o1+=8, o2+=8)
809	    bus_space_write_stream_8(t, h1, o1, bus_space_read_8(t, h2, o2));
810}
811
812/* Back-compat functions for old ISA drivers */
813extern bus_space_tag_t isa_io_bt;
814extern bus_space_handle_t isa_io_hdl;
815extern bus_space_tag_t isa_mem_bt;
816extern bus_space_handle_t isa_mem_hdl;
817
818#define inb(o)		bus_space_read_1(isa_io_bt, isa_io_hdl, o)
819#define inw(o)		bus_space_read_2(isa_io_bt, isa_io_hdl, o)
820#define inl(o)		bus_space_read_4(isa_io_bt, isa_io_hdl, o)
821#define outb(o, v)	bus_space_write_1(isa_io_bt, isa_io_hdl, o, v)
822#define outw(o, v)	bus_space_write_2(isa_io_bt, isa_io_hdl, o, v)
823#define outl(o, v)	bus_space_write_4(isa_io_bt, isa_io_hdl, o, v)
824
825#define readb(o)	bus_space_read_1(isa_mem_bt, isa_mem_hdl, o)
826#define readw(o)	bus_space_read_2(isa_mem_bt, isa_mem_hdl, o)
827#define readl(o)	bus_space_read_4(isa_mem_bt, isa_mem_hdl, o)
828#define writeb(o, v)	bus_space_write_1(isa_mem_bt, isa_mem_hdl, o, v)
829#define writew(o, v)	bus_space_write_2(isa_mem_bt, isa_mem_hdl, o, v)
830#define writel(o, v)	bus_space_write_4(isa_mem_bt, isa_mem_hdl, o, v)
831
832#define insb(o, a, c) \
833	bus_space_read_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c)
834#define insw(o, a, c) \
835	bus_space_read_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c)
836#define insl(o, a, c) \
837	bus_space_read_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c)
838#define outsb(o, a, c) \
839	bus_space_write_multi_1(isa_io_bt, isa_io_hdl, o, (void*)a, c)
840#define outsw(o, a, c) \
841	bus_space_write_multi_2(isa_io_bt, isa_io_hdl, o, (void*)a, c)
842#define outsl(o, a, c) \
843	bus_space_write_multi_4(isa_io_bt, isa_io_hdl, o, (void*)a, c)
844
845#define memcpy_fromio(d, s, c) \
846	bus_space_read_region_1(isa_mem_bt, isa_mem_hdl, s, d, c)
847#define memcpy_toio(d, s, c) \
848	bus_space_write_region_1(isa_mem_bt, isa_mem_hdl, d, s, c)
849#define memcpy_io(d, s, c) \
850	bus_space_copy_region_1(isa_mem_bt, isa_mem_hdl, s, isa_mem_hdl, d, c)
851#define memset_io(d, v, c) \
852	bus_space_set_region_1(isa_mem_bt, isa_mem_hdl, d, v, c)
853#define memsetw_io(d, v, c) \
854	bus_space_set_region_2(isa_mem_bt, isa_mem_hdl, d, v, c)
855
856static __inline void
857memsetw(void *d, int val, size_t size)
858{
859    u_int16_t *sp = d;
860
861    while (size--)
862	*sp++ = val;
863}
864
865/* DMA support */
866
867/*
868 * Flags used in various bus DMA methods.
869 */
870#define	BUS_DMA_WAITOK		0x000	/* safe to sleep (pseudo-flag) */
871#define	BUS_DMA_NOWAIT		0x001	/* not safe to sleep */
872#define	BUS_DMA_ALLOCNOW	0x002	/* perform resource allocation now */
873#define	BUS_DMAMEM_NOSYNC	0x004	/* map memory to not require sync */
874#define	BUS_DMA_NOWRITE		0x008
875#define	BUS_DMA_BUS1		0x010
876#define	BUS_DMA_BUS2		0x020
877#define	BUS_DMA_BUS3		0x040
878#define	BUS_DMA_BUS4		0x080
879/*
880 * The following flags are from NetBSD, but are not implemented for all
881 * architetures, and should therefore not be used in MI code.
882 * Some have different values than under NetBSD.
883 */
884#define	BUS_DMA_STREAMING	0x100	/* hint: sequential, unidirectional */
885#define	BUS_DMA_READ		0x200	/* mapping is device -> memory only */
886#define	BUS_DMA_WRITE		0x400	/* mapping is memory -> device only */
887#define	BUS_DMA_COHERENT	0x800	/* hint: map memory DMA coherent */
888
889#define	BUS_DMA_NOCACHE		BUS_DMA_BUS1
890/* Don't bother with alignment */
891#define	BUS_DMA_DVMA		BUS_DMA_BUS2
892
893/* Forwards needed by prototypes below. */
894struct mbuf;
895struct uio;
896
897typedef enum {
898	BUS_DMASYNC_PREREAD,
899	BUS_DMASYNC_POSTREAD,
900	BUS_DMASYNC_PREWRITE,
901	BUS_DMASYNC_POSTWRITE,
902} bus_dmasync_op_t;
903
904/*
905 * A function that returns 1 if the address cannot be accessed by
906 * a device and 0 if it can be.
907 */
908typedef int bus_dma_filter_t(void *, bus_addr_t);
909
910typedef struct bus_dma_tag	*bus_dma_tag_t;
911typedef struct bus_dmamap	*bus_dmamap_t;
912
913struct bus_dma_segment {
914	bus_addr_t	ds_addr;	/* DVMA address */
915	bus_size_t	ds_len;		/* length of transfer */
916};
917typedef struct bus_dma_segment	bus_dma_segment_t;
918
919/*
920 * A function that processes a successfully loaded dma map or an error
921 * from a delayed load map.
922 */
923typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
924
925/*
926 * Like bus_dmamap_callback but includes map size in bytes.  This is
927 * defined as a separate interface to maintain compatiiblity for users
928 * of bus_dmamap_callback_t--at some point these interfaces should be merged.
929 */
930typedef void bus_dmamap_callback2_t(void *, bus_dma_segment_t *, int, bus_size_t, int);
931
932/*
933 *	bus_dma_tag_t
934 *
935 *	A machine-dependent opaque type describing the implementation of
936 *	DMA for a given bus.
937 */
938struct bus_dma_tag {
939	void		*dt_cookie;		/* cookie used in the guts */
940	bus_dma_tag_t	dt_parent;
941	bus_size_t	dt_alignment;
942	bus_size_t	dt_boundary;
943	bus_addr_t	dt_lowaddr;
944	bus_addr_t	dt_highaddr;
945	bus_dma_filter_t	*dt_filter;
946	void		*dt_filterarg;
947	bus_size_t	dt_maxsize;
948	int		dt_nsegments;
949	bus_size_t	dt_maxsegsz;
950	int		dt_flags;
951	int		dt_ref_count;
952	int		dt_map_count;
953
954	/*
955	 * DMA mapping methods.
956	 */
957	int	(*dt_dmamap_create)(bus_dma_tag_t, bus_dma_tag_t, int,
958	    bus_dmamap_t *);
959	int	(*dt_dmamap_destroy)(bus_dma_tag_t, bus_dma_tag_t,
960	    bus_dmamap_t);
961	int	(*dt_dmamap_load)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t,
962	    void *, bus_size_t, bus_dmamap_callback_t *, void *, int);
963	int	(*dt_dmamap_load_mbuf)(bus_dma_tag_t, bus_dma_tag_t,
964	    bus_dmamap_t, struct mbuf *, bus_dmamap_callback2_t *, void *, int);
965	int	(*dt_dmamap_load_uio)(bus_dma_tag_t, bus_dma_tag_t,
966	    bus_dmamap_t, struct uio *, bus_dmamap_callback2_t *, void *, int);
967	void	(*dt_dmamap_unload)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t);
968	void	(*dt_dmamap_sync)(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t,
969	    bus_dmasync_op_t);
970
971	/*
972	 * DMA memory utility functions.
973	 */
974	int	(*dt_dmamem_alloc_size)(bus_dma_tag_t, bus_dma_tag_t, void **,
975	    int, bus_dmamap_t *, bus_size_t size);
976	int	(*dt_dmamem_alloc)(bus_dma_tag_t, bus_dma_tag_t, void **, int,
977	    bus_dmamap_t *);
978	void	(*dt_dmamem_free_size)(bus_dma_tag_t, bus_dma_tag_t, void *,
979	    bus_dmamap_t, bus_size_t size);
980	void	(*dt_dmamem_free)(bus_dma_tag_t, bus_dma_tag_t, void *,
981	    bus_dmamap_t);
982};
983
984/*
985 * XXX: This is a kluge. It would be better to handle dma tags in a hierarchical
986 * way, and have a BUS_GET_DMA_TAG(); however, since this is not currently the
987 * case, save a root tag in the relevant bus attach function and use that.
988 * Keep the hierarchical structure, it might become needed in the future.
989 */
990extern bus_dma_tag_t sparc64_root_dma_tag;
991
992int bus_dma_tag_create(bus_dma_tag_t, bus_size_t, bus_size_t, bus_addr_t,
993    bus_addr_t, bus_dma_filter_t *, void *, bus_size_t, int, bus_size_t,
994    int, bus_dma_tag_t *);
995
996int bus_dma_tag_destroy(bus_dma_tag_t);
997
998int sparc64_dmamem_alloc_map(bus_dma_tag_t dmat, bus_dmamap_t *mapp);
999void sparc64_dmamem_free_map(bus_dma_tag_t dmat, bus_dmamap_t map);
1000
1001static __inline int
1002sparc64_dmamap_create(bus_dma_tag_t pt, bus_dma_tag_t dt, int f,
1003    bus_dmamap_t *p)
1004{
1005	bus_dma_tag_t lt;
1006
1007	for (lt = pt; lt->dt_dmamap_create == NULL; lt = lt->dt_parent)
1008		;
1009	return ((*lt->dt_dmamap_create)(lt, dt, f, p));
1010}
1011#define	bus_dmamap_create(t, f, p)					\
1012	sparc64_dmamap_create((t), (t), (f), (p))
1013
1014static __inline int
1015sparc64_dmamap_destroy(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t p)
1016{
1017	bus_dma_tag_t lt;
1018
1019	for (lt = pt; lt->dt_dmamap_destroy == NULL; lt = lt->dt_parent)
1020		;
1021	return ((*lt->dt_dmamap_destroy)(lt, dt, p));
1022}
1023#define	bus_dmamap_destroy(t, p)					\
1024	sparc64_dmamap_destroy((t), (t), (p))
1025
1026static __inline int
1027sparc64_dmamap_load(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m,
1028    void *p, bus_size_t s, bus_dmamap_callback_t *cb, void *cba, int f)
1029{
1030	bus_dma_tag_t lt;
1031
1032	for (lt = pt; lt->dt_dmamap_load == NULL; lt = lt->dt_parent)
1033		;
1034	return ((*lt->dt_dmamap_load)(lt, dt, m, p, s, cb, cba, f));
1035}
1036#define	bus_dmamap_load(t, m, p, s, cb, cba, f)				\
1037	sparc64_dmamap_load((t), (t), (m), (p), (s), (cb), (cba), (f))
1038
1039static __inline int
1040sparc64_dmamap_load_mbuf(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m,
1041    struct mbuf *mb, bus_dmamap_callback2_t *cb, void *cba, int f)
1042{
1043	bus_dma_tag_t lt;
1044
1045	for (lt = pt; lt->dt_dmamap_load_mbuf == NULL; lt = lt->dt_parent)
1046		;
1047	return ((*lt->dt_dmamap_load_mbuf)(lt, dt, m, mb, cb, cba, f));
1048}
1049#define	bus_dmamap_load_mbuf(t, m, mb, cb, cba, f)				\
1050	sparc64_dmamap_load_mbuf((t), (t), (m), (mb), (cb), (cba), (f))
1051
1052static __inline int
1053sparc64_dmamap_load_uio(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m,
1054    struct uio *ui, bus_dmamap_callback2_t *cb, void *cba, int f)
1055{
1056	bus_dma_tag_t lt;
1057
1058	for (lt = pt; lt->dt_dmamap_load_uio == NULL; lt = lt->dt_parent)
1059		;
1060	return ((*lt->dt_dmamap_load_uio)(lt, dt, m, ui, cb, cba, f));
1061}
1062#define	bus_dmamap_load_uio(t, m, ui, cb, cba, f)				\
1063	sparc64_dmamap_load_uio((t), (t), (m), (ui), (cb), (cba), (f))
1064
1065static __inline void
1066sparc64_dmamap_unload(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t p)
1067{
1068	bus_dma_tag_t lt;
1069
1070	for (lt = pt; lt->dt_dmamap_unload == NULL; lt = lt->dt_parent)
1071		;
1072	(*lt->dt_dmamap_unload)(lt, dt, p);
1073}
1074#define	bus_dmamap_unload(t, p)						\
1075	sparc64_dmamap_unload((t), (t), (p))
1076
1077static __inline void
1078sparc64_dmamap_sync(bus_dma_tag_t pt, bus_dma_tag_t dt, bus_dmamap_t m,
1079    bus_dmasync_op_t op)
1080{
1081	bus_dma_tag_t lt;
1082
1083	for (lt = pt; lt->dt_dmamap_sync == NULL; lt = lt->dt_parent)
1084		;
1085	(*lt->dt_dmamap_sync)(lt, dt, m, op);
1086}
1087#define	bus_dmamap_sync(t, m, op)					\
1088	sparc64_dmamap_sync((t), (t), (m), (op))
1089
1090static __inline int
1091sparc64_dmamem_alloc_size(bus_dma_tag_t pt, bus_dma_tag_t dt, void **v, int f,
1092    bus_dmamap_t *m, bus_size_t s)
1093{
1094	bus_dma_tag_t lt;
1095
1096	for (lt = pt; lt->dmamem_alloc == NULL; lt = lt->parent)
1097		;
1098	return ((*lt->dmamem_alloc_size)(lt, dt, v, f, m, s));
1099}
1100#define	bus_dmamem_alloc_size(t, v, f, m, s)				\
1101	sparc64_dmamem_alloc_size((t), (t), (v), (f), (m), (s))
1102
1103static __inline int
1104sparc64_dmamem_alloc(bus_dma_tag_t pt, bus_dma_tag_t dt, void **v, int f,
1105    bus_dmamap_t *m)
1106{
1107	bus_dma_tag_t lt;
1108
1109	for (lt = pt; lt->dt_dmamem_alloc == NULL; lt = lt->dt_parent)
1110		;
1111	return ((*lt->dt_dmamem_alloc)(lt, dt, v, f, m));
1112}
1113#define	bus_dmamem_alloc(t, v, f, m)					\
1114	sparc64_dmamem_alloc((t), (t), (v), (f), (m))
1115
1116static __inline void
1117sparc64_dmamem_free_size(bus_dma_tag_t pt, bus_dma_tag_t dt, void *v,
1118    bus_dmamap_t m, bus_size_t s)
1119{
1120	bus_dma_tag_t lt;
1121
1122	for (lt = pt; lt->dmamem_free == NULL; lt = lt->parent)
1123		;
1124	(*lt->dmamem_free_size)(lt, dt, v, m, s);
1125}
1126#define	bus_dmamem_free_size(t, v, m, s)				\
1127	sparc64_dmamem_free_size((t), (t), (v), (m), (s))
1128
1129static __inline void
1130sparc64_dmamem_free(bus_dma_tag_t pt, bus_dma_tag_t dt, void *v,
1131    bus_dmamap_t m)
1132{
1133	bus_dma_tag_t lt;
1134
1135	for (lt = pt; lt->dt_dmamem_free == NULL; lt = lt->dt_parent)
1136		;
1137	(*lt->dt_dmamem_free)(lt, dt, v, m);
1138}
1139#define	bus_dmamem_free(t, v, m)					\
1140	sparc64_dmamem_free((t), (t), (v), (m))
1141
1142#endif /* !_MACHINE_BUS_H_ */
1143