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