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