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