1/*	$NetBSD: bus.h,v 1.5 2007/03/04 05:59:47 christos Exp $	*/
2
3/*-
4 * Copyright (c) 1997, 1998, 2000, 2001, 2005 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/*
34 * Copyright (c) 1996 Carnegie-Mellon University.
35 * All rights reserved.
36 *
37 * Author: Chris G. Demetriou
38 *
39 * Permission to use, copy, modify and distribute this software and
40 * its documentation is hereby granted, provided that both the copyright
41 * notice and this permission notice appear in all copies of the
42 * software, derivative works or modified versions, and any portions
43 * thereof, and that both notices appear in supporting documentation.
44 *
45 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
46 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
47 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
48 *
49 * Carnegie Mellon requests users of this software to return to
50 *
51 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
52 *  School of Computer Science
53 *  Carnegie Mellon University
54 *  Pittsburgh PA 15213-3890
55 *
56 * any improvements or extensions that they make and grant Carnegie the
57 * rights to redistribute these changes.
58 */
59
60#ifndef _EWS4800MIPS_BUS_H_
61#define	_EWS4800MIPS_BUS_H_
62
63#include <sys/types.h>
64#ifdef _KERNEL
65/*
66 * Turn on BUS_SPACE_DEBUG if the global DEBUG option is enabled.
67 */
68#if defined(DEBUG) && !defined(BUS_SPACE_DEBUG)
69#define	BUS_SPACE_DEBUG
70#endif
71
72#ifdef BUS_SPACE_DEBUG
73#include <sys/systm.h> /* for printf() prototype */
74/*
75 * Macros for checking the aligned-ness of pointers passed to bus
76 * space ops.  Strict alignment is required by the MIPS architecture,
77 * and a trap will occur if unaligned access is performed.  These
78 * may aid in the debugging of a broken device driver by displaying
79 * useful information about the problem.
80 */
81#define	__BUS_SPACE_ALIGNED_ADDRESS(p, t)				\
82	((((uint32_t)(p)) & (sizeof(t)-1)) == 0)
83
84#define	__BUS_SPACE_ADDRESS_SANITY(p, t, d)				\
85({									\
86	if (__BUS_SPACE_ALIGNED_ADDRESS((p), t) == 0) {			\
87		printf("%s 0x%x not aligned to %u bytes %s:%d\n",	\
88		    d, (uint32_t)(p), (uint32_t)sizeof(t), __FILE__,	\
89		    __LINE__);						\
90	}								\
91	(void) 0;							\
92})
93
94#define	BUS_SPACE_ALIGNED_POINTER(p, t) __BUS_SPACE_ALIGNED_ADDRESS(p, t)
95#else
96#define	__BUS_SPACE_ADDRESS_SANITY(p, t, d)	(void) 0
97#define	BUS_SPACE_ALIGNED_POINTER(p, t) ALIGNED_POINTER(p, t)
98#endif /* BUS_SPACE_DEBUG */
99#endif /* _KERNEL */
100
101/*
102 * Addresses (in bus space).
103 */
104typedef long bus_addr_t;
105typedef long bus_size_t;
106
107/*
108 * Access methods for bus space.
109 */
110typedef struct ews4800mips_bus_space *bus_space_tag_t;
111typedef bus_addr_t bus_space_handle_t;
112
113struct extent; /* forward declaration */
114
115struct ews4800mips_bus_space {
116	struct extent	*ebs_extent;
117	bus_addr_t	ebs_base_addr;
118	bus_size_t	ebs_size;
119
120	/* cookie */
121	void		*ebs_cookie;
122
123	/* mapping/unmapping */
124	int		(*ebs_map)(void *, bus_addr_t, bus_size_t,
125			    int, bus_space_handle_t *);
126	void		(*ebs_unmap)(void *, bus_space_handle_t,
127			    bus_size_t);
128	int		(*ebs_subregion)(void *, bus_space_handle_t,
129			    bus_size_t, bus_size_t, bus_space_handle_t *);
130
131	/* allocation/deallocation */
132	int		(*ebs_alloc)(void *, bus_addr_t, bus_addr_t,
133			    bus_size_t, bus_size_t, bus_size_t, int,
134			    bus_addr_t *, bus_space_handle_t *);
135	void		(*ebs_free)(void *, bus_space_handle_t,
136			    bus_size_t);
137
138	/* get kernel virtual address */
139	void *		(*ebs_vaddr)(void *, bus_space_handle_t);
140
141	/* read (single) */
142	uint8_t		(*ebs_r_1)(void *, bus_space_handle_t,
143			    bus_size_t);
144	uint16_t	(*ebs_r_2)(void *, bus_space_handle_t,
145			    bus_size_t);
146	uint32_t	(*ebs_r_4)(void *, bus_space_handle_t,
147			    bus_size_t);
148	uint64_t	(*ebs_r_8)(void *, bus_space_handle_t,
149			    bus_size_t);
150
151	/* read multiple */
152	void		(*ebs_rm_1)(void *, bus_space_handle_t,
153			    bus_size_t, uint8_t *, bus_size_t);
154	void		(*ebs_rm_2)(void *, bus_space_handle_t,
155			    bus_size_t, uint16_t *, bus_size_t);
156	void		(*ebs_rm_4)(void *, bus_space_handle_t,
157			    bus_size_t, uint32_t *, bus_size_t);
158	void		(*ebs_rm_8)(void *, bus_space_handle_t,
159			    bus_size_t, uint64_t *, bus_size_t);
160
161	/* read region */
162	void		(*ebs_rr_1)(void *, bus_space_handle_t,
163			    bus_size_t, uint8_t *, bus_size_t);
164	void		(*ebs_rr_2)(void *, bus_space_handle_t,
165			    bus_size_t, uint16_t *, bus_size_t);
166	void		(*ebs_rr_4)(void *, bus_space_handle_t,
167			    bus_size_t, uint32_t *, bus_size_t);
168	void		(*ebs_rr_8)(void *, bus_space_handle_t,
169			    bus_size_t, uint64_t *, bus_size_t);
170
171	/* write (single) */
172	void		(*ebs_w_1)(void *, bus_space_handle_t,
173			    bus_size_t, uint8_t);
174	void		(*ebs_w_2)(void *, bus_space_handle_t,
175			    bus_size_t, uint16_t);
176	void		(*ebs_w_4)(void *, bus_space_handle_t,
177			    bus_size_t, uint32_t);
178	void		(*ebs_w_8)(void *, bus_space_handle_t,
179			    bus_size_t, uint64_t);
180
181	/* write multiple */
182	void		(*ebs_wm_1)(void *, bus_space_handle_t,
183			    bus_size_t, const uint8_t *, bus_size_t);
184	void		(*ebs_wm_2)(void *, bus_space_handle_t,
185			    bus_size_t, const uint16_t *, bus_size_t);
186	void		(*ebs_wm_4)(void *, bus_space_handle_t,
187			    bus_size_t, const uint32_t *, bus_size_t);
188	void		(*ebs_wm_8)(void *, bus_space_handle_t,
189			    bus_size_t, const uint64_t *, bus_size_t);
190
191	/* write region */
192	void		(*ebs_wr_1)(void *, bus_space_handle_t,
193			    bus_size_t, const uint8_t *, bus_size_t);
194	void		(*ebs_wr_2)(void *, bus_space_handle_t,
195			    bus_size_t, const uint16_t *, bus_size_t);
196	void		(*ebs_wr_4)(void *, bus_space_handle_t,
197			    bus_size_t, const uint32_t *, bus_size_t);
198	void		(*ebs_wr_8)(void *, bus_space_handle_t,
199			    bus_size_t, const uint64_t *, bus_size_t);
200
201	/* set multiple */
202	void		(*ebs_sm_1)(void *, bus_space_handle_t,
203			    bus_size_t, uint8_t, bus_size_t);
204	void		(*ebs_sm_2)(void *, bus_space_handle_t,
205			    bus_size_t, uint16_t, bus_size_t);
206	void		(*ebs_sm_4)(void *, bus_space_handle_t,
207			    bus_size_t, uint32_t, bus_size_t);
208	void		(*ebs_sm_8)(void *, bus_space_handle_t,
209			    bus_size_t, uint64_t, bus_size_t);
210
211	/* set region */
212	void		(*ebs_sr_1)(void *, bus_space_handle_t,
213			    bus_size_t, uint8_t, bus_size_t);
214	void		(*ebs_sr_2)(void *, bus_space_handle_t,
215			    bus_size_t, uint16_t, bus_size_t);
216	void		(*ebs_sr_4)(void *, bus_space_handle_t,
217			    bus_size_t, uint32_t, bus_size_t);
218	void		(*ebs_sr_8)(void *, bus_space_handle_t,
219			    bus_size_t, uint64_t, bus_size_t);
220
221	/* copy */
222	void		(*ebs_c_1)(void *, bus_space_handle_t, bus_size_t,
223			    bus_space_handle_t, bus_size_t, bus_size_t);
224	void		(*ebs_c_2)(void *, bus_space_handle_t, bus_size_t,
225			    bus_space_handle_t, bus_size_t, bus_size_t);
226	void		(*ebs_c_4)(void *, bus_space_handle_t, bus_size_t,
227			    bus_space_handle_t, bus_size_t, bus_size_t);
228	void		(*ebs_c_8)(void *, bus_space_handle_t, bus_size_t,
229			    bus_space_handle_t, bus_size_t, bus_size_t);
230};
231
232#ifdef _KERNEL
233/* Don't use locore.h wbflush */
234#undef wbflush
235#define	wbflush()	platform.wbflush()
236#ifdef _EWS4800MIPS_BUS_SPACE_PRIVATE
237
238#ifndef __read_1
239#define	__read_1(a)	(*(volatile uint8_t *)(a))
240#endif
241#ifndef __read_2
242#define	__read_2(a)	(*(volatile uint16_t *)(a))
243#endif
244#ifndef __read_4
245#define	__read_4(a)	(*(volatile uint32_t *)(a))
246#endif
247#ifndef __read_8
248#define	__read_8(a)	(*(volatile uint64_t *)(a))
249#endif
250#define	__read_16(a)	"error. not yet"
251
252#ifndef __write_1
253#define	__write_1(a, v) {						\
254	*(volatile uint8_t *)(a) = (v);				\
255	wbflush();							\
256}
257#endif
258#ifndef __write_2
259#define	__write_2(a, v)	{						\
260	*(volatile uint16_t *)(a) = (v);				\
261	wbflush();							\
262}
263#endif
264#ifndef __write_4
265#define	__write_4(a, v)	{						\
266	*(volatile uint32_t *)(a) = (v);				\
267	wbflush();							\
268}
269#endif
270#ifndef __write_8
271#define	__write_8(a, v) {						\
272	*(volatile uint64_t *)(a) = (v);				\
273	wbflush();							\
274}
275#endif
276
277#define	__TYPENAME(BITS)	uint##BITS##_t
278
279#define	_BUS_SPACE_READ(PREFIX, BYTES, BITS)				\
280static __TYPENAME(BITS)							\
281PREFIX##_read_##BYTES(void *, bus_space_handle_t,  bus_size_t);		\
282static __TYPENAME(BITS)							\
283PREFIX##_read_##BYTES(void *tag, bus_space_handle_t bsh,		\
284    bus_size_t offset)							\
285{									\
286	return __read_##BYTES(VADDR(bsh, offset));			\
287}
288
289#define	_BUS_SPACE_READ_MULTI(PREFIX, BYTES, BITS)			\
290static void								\
291PREFIX##_read_multi_##BYTES(void *, bus_space_handle_t,	bus_size_t,	\
292    __TYPENAME(BITS) *,	bus_size_t);					\
293static void								\
294PREFIX##_read_multi_##BYTES(void *tag, bus_space_handle_t bsh,		\
295    bus_size_t offset, __TYPENAME(BITS) *addr, bus_size_t count)	\
296{									\
297	bus_addr_t a = VADDR(bsh, offset);				\
298	while (count--)							\
299		*addr++ = __read_##BYTES(a);				\
300}
301
302#define	_BUS_SPACE_READ_REGION(PREFIX, BYTES, BITS)			\
303static void								\
304PREFIX##_read_region_##BYTES(void *, bus_space_handle_t, bus_size_t,	\
305    __TYPENAME(BITS) *, bus_size_t);					\
306static void								\
307PREFIX##_read_region_##BYTES(void *tag, bus_space_handle_t bsh,		\
308    bus_size_t offset, __TYPENAME(BITS) *addr, bus_size_t count)	\
309{									\
310	while (count--) {						\
311		*addr++ = __read_##BYTES(VADDR(bsh, offset));		\
312		offset += BYTES;					\
313	}								\
314}
315
316#define	_BUS_SPACE_WRITE(PREFIX, BYTES, BITS)				\
317static void								\
318PREFIX##_write_##BYTES(void *, bus_space_handle_t, bus_size_t,		\
319    __TYPENAME(BITS));							\
320static void								\
321PREFIX##_write_##BYTES(void *tag, bus_space_handle_t bsh,		\
322    bus_size_t offset, __TYPENAME(BITS) value)				\
323{									\
324	__write_##BYTES(VADDR(bsh, offset), value);			\
325}
326
327#define	_BUS_SPACE_WRITE_MULTI(PREFIX, BYTES, BITS)			\
328static void								\
329PREFIX##_write_multi_##BYTES(void *, bus_space_handle_t, bus_size_t,	\
330    const __TYPENAME(BITS) *, bus_size_t);				\
331static void								\
332PREFIX##_write_multi_##BYTES(void *tag, bus_space_handle_t bsh,		\
333    bus_size_t offset, const __TYPENAME(BITS) *addr, bus_size_t count)	\
334{									\
335	bus_addr_t a = VADDR(bsh, offset);				\
336	while (count--) {						\
337		__write_##BYTES(a, *addr++);				\
338	}								\
339}
340
341#define	_BUS_SPACE_WRITE_REGION(PREFIX, BYTES, BITS)			\
342static void								\
343PREFIX##_write_region_##BYTES(void *, bus_space_handle_t, bus_size_t,	\
344    const __TYPENAME(BITS) *, bus_size_t);				\
345static void								\
346PREFIX##_write_region_##BYTES(void *tag, bus_space_handle_t bsh,	\
347    bus_size_t offset, const __TYPENAME(BITS) *addr, bus_size_t count)	\
348{									\
349	while (count--) {						\
350		__write_##BYTES(VADDR(bsh, offset), *addr++);		\
351		offset += BYTES;					\
352	}								\
353}
354
355#define	_BUS_SPACE_SET_MULTI(PREFIX, BYTES, BITS)			\
356static void								\
357PREFIX##_set_multi_##BYTES(void *, bus_space_handle_t, bus_size_t,	\
358    __TYPENAME(BITS), bus_size_t);					\
359static void								\
360PREFIX##_set_multi_##BYTES(void *tag, bus_space_handle_t bsh,		\
361    bus_size_t offset, __TYPENAME(BITS) value, bus_size_t count)	\
362{									\
363	bus_addr_t a = VADDR(bsh, offset);				\
364	while (count--) {						\
365		__write_##BYTES(a, value);				\
366	}								\
367}
368
369#define	_BUS_SPACE_SET_REGION(PREFIX, BYTES, BITS)			\
370static void								\
371PREFIX##_set_region_##BYTES(void *, bus_space_handle_t, bus_size_t,	\
372    __TYPENAME(BITS), bus_size_t);					\
373static void								\
374PREFIX##_set_region_##BYTES(void *tag, bus_space_handle_t bsh,		\
375    bus_size_t offset, __TYPENAME(BITS) value, bus_size_t count)	\
376{									\
377	while (count--) {						\
378		__write_##BYTES(VADDR(bsh, offset), value);		\
379		offset += BYTES;					\
380	}								\
381}
382
383#define	_BUS_SPACE_COPY_REGION(PREFIX, BYTES, BITS)			\
384static void								\
385PREFIX##_copy_region_##BYTES(void *, bus_space_handle_t, bus_size_t,	\
386    bus_space_handle_t, bus_size_t, bus_size_t);			\
387static void								\
388PREFIX##_copy_region_##BYTES(void *t, bus_space_handle_t h1,		\
389    bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c)	\
390{									\
391	bus_size_t o;							\
392	if ((h1 + o1) >= (h2 + o2)) {					\
393		/* src after dest: copy forward */			\
394		for (o = 0; c != 0; c--, o += BYTES)			\
395			__write_##BYTES(VADDR(h2, o2 + o),		\
396			    __read_##BYTES(VADDR(h1, o1 + o)));	\
397	} else {							\
398		/* dest after src: copy backwards */			\
399		for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES)	\
400			__write_##BYTES(VADDR(h2, o2 + o),		\
401			    __read_##BYTES(VADDR(h1, o1 + o)));	\
402	}								\
403}
404
405#define	_BUS_SPACE_NO_MAP						\
406	(int (*)(void *, bus_addr_t, bus_size_t, int,			\
407	bus_space_handle_t *))_bus_space_invalid_access
408#define	_BUS_SPACE_NO_UNMAP						\
409	(void (*)(void *, bus_space_handle_t, bus_size_t))		\
410	_bus_space_invalid_access
411#define	_BUS_SPACE_NO_SUBREGION						\
412	(int (*)(void *, bus_space_handle_t, bus_size_t, bus_size_t,	\
413	bus_space_handle_t *))_bus_space_invalid_access
414#define	_BUS_SPACE_NO_ALLOC						\
415	(int (*)(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t,\
416	 bus_size_t, int, bus_addr_t *,	bus_space_handle_t *))		\
417	_bus_space_invalid_access
418#define	_BUS_SPACE_NO_FREE						\
419	(void (*)(void *, bus_space_handle_t, bus_size_t))		\
420	_bus_space_invalid_access
421#define	_BUS_SPACE_NO_VADDR						\
422	(void *(*)(void *, bus_space_handle_t))_bus_space_invalid_access
423#define	_BUS_SPACE_NO_READ(BYTES, BITS)					\
424	(uint##BITS##_t (*)(void *, bus_space_handle_t, bus_size_t))	\
425	_bus_space_invalid_access
426#define	_BUS_SPACE_NO_READ_MULTI(BYTES, BITS)				\
427	(void (*)(void *, bus_space_handle_t, bus_size_t,		\
428	uint##BITS##_t *, bus_size_t))_bus_space_invalid_access
429#define	_BUS_SPACE_NO_READ_REGION(BYTES, BITS)				\
430	(void (*)(void *, bus_space_handle_t, bus_size_t,		\
431	uint##BITS##_t *, bus_size_t))_bus_space_invalid_access
432#define	_BUS_SPACE_NO_WRITE(BYTES, BITS)				\
433	(void (*)(void *, bus_space_handle_t, bus_size_t,		\
434	uint##BITS##_t))_bus_space_invalid_access
435#define	_BUS_SPACE_NO_WRITE_MULTI(BYTES, BITS)				\
436	(void (*)(void *, bus_space_handle_t, bus_size_t,		\
437	const uint##BITS##_t *, bus_size_t))_bus_space_invalid_access
438#define	_BUS_SPACE_NO_WRITE_REGION(BYTES, BITS)				\
439	(void (*)(void *, bus_space_handle_t, bus_size_t,		\
440	const uint##BITS##_t *, bus_size_t))_bus_space_invalid_access
441#define	_BUS_SPACE_NO_SET_MULTI(BYTES, BITS)				\
442	(void (*)(void *, bus_space_handle_t, bus_size_t,		\
443	uint##BITS##_t, bus_size_t))_bus_space_invalid_access
444#define	_BUS_SPACE_NO_SET_REGION(BYTES, BITS)				\
445	(void (*)(void *, bus_space_handle_t, bus_size_t,		\
446	uint##BITS##_t, bus_size_t))_bus_space_invalid_access
447#define	_BUS_SPACE_NO_COPY_REGION(BYTES, BITS)				\
448	(void (*)(void *, bus_space_handle_t, bus_size_t,		\
449	bus_space_handle_t, bus_size_t, bus_size_t))_bus_space_invalid_access
450
451void _bus_space_invalid_access(void);
452#endif /* _EWS4800MIPS_BUS_SPACE_PRIVATE */
453
454#define	__ebs_c(a,b)		__CONCAT(a,b)
455#define	__ebs_opname(op,size)	__ebs_c(__ebs_c(__ebs_c(ebs_,op),_),size)
456
457#define	__ebs_rs(sz, tn, t, h, o)					\
458	(__BUS_SPACE_ADDRESS_SANITY((h) + (o), tn, "bus addr"),		\
459	 (*(t)->__ebs_opname(r,sz))((t)->ebs_cookie, h, o))
460
461#define	__ebs_ws(sz, tn, t, h, o, v)					\
462({									\
463	__BUS_SPACE_ADDRESS_SANITY((h) + (o), tn, "bus addr");		\
464	(*(t)->__ebs_opname(w,sz))((t)->ebs_cookie, h, o, v);		\
465})
466
467#define	__ebs_nonsingle(type, sz, tn, t, h, o, a, c)			\
468({									\
469	__BUS_SPACE_ADDRESS_SANITY((a), tn, "buffer");			\
470	__BUS_SPACE_ADDRESS_SANITY((h) + (o), tn, "bus addr");		\
471	(*(t)->__ebs_opname(type,sz))((t)->ebs_cookie, h, o, a, c);	\
472})
473
474#define	__ebs_set(type, sz, tn, t, h, o, v, c)				\
475({									\
476	__BUS_SPACE_ADDRESS_SANITY((h) + (o), tn, "bus addr");		\
477	(*(t)->__ebs_opname(type,sz))((t)->ebs_cookie, h, o, v, c);	\
478})
479
480#define	__ebs_copy(sz, tn, t, h1, o1, h2, o2, cnt)			\
481({									\
482	__BUS_SPACE_ADDRESS_SANITY((h1) + (o1), tn, "bus addr 1");	\
483	__BUS_SPACE_ADDRESS_SANITY((h2) + (o2), tn, "bus addr 2");	\
484	(*(t)->__ebs_opname(c,sz))((t)->ebs_cookie, h1, o1, h2, o2, cnt); \
485})
486
487/*
488 * Create/destroy default bus_space tag.
489 */
490int bus_space_create(bus_space_tag_t, const char *, bus_addr_t, bus_size_t);
491void bus_space_destroy(bus_space_tag_t);
492
493/*
494 * Mapping and unmapping operations.
495 */
496#define	bus_space_map(t, a, s, f, hp)					\
497	(*(t)->ebs_map)((t)->ebs_cookie, (a), (s), (f), (hp))
498#define	bus_space_unmap(t, h, s)					\
499	(*(t)->ebs_unmap)((t)->ebs_cookie, (h), (s))
500#define	bus_space_subregion(t, h, o, s, hp)				\
501	(*(t)->ebs_subregion)((t)->ebs_cookie, (h), (o), (s), (hp))
502
503#endif /* _KERNEL */
504
505#define	BUS_SPACE_MAP_CACHEABLE		0x01
506#define	BUS_SPACE_MAP_LINEAR		0x02
507#define	BUS_SPACE_MAP_PREFETCHABLE     	0x04
508
509#ifdef _KERNEL
510/*
511 * Allocation and deallocation operations.
512 */
513#define	bus_space_alloc(t, rs, re, s, a, b, f, ap, hp)			\
514	(*(t)->ebs_alloc)((t)->ebs_cookie, (rs), (re), (s), (a), (b),	\
515	    (f), (ap), (hp))
516#define	bus_space_free(t, h, s)						\
517	(*(t)->ebs_free)((t)->ebs_cookie, (h), (s))
518
519/*
520 * Get kernel virtual address for ranges mapped BUS_SPACE_MAP_LINEAR.
521 */
522#define	bus_space_vaddr(t, h)						\
523	(*(t)->ebs_vaddr)((t)->ebs_cookie, (h))
524
525/*
526 * Bus read/write barrier methods.
527 *
528 *	void bus_space_barrier(bus_space_tag_t tag,
529 *	    bus_space_handle_t bsh, bus_size_t offset,
530 *	    bus_size_t len, int flags);
531 *
532 * On the MIPS, we just flush the write buffer.
533 */
534#define	bus_space_barrier(t, h, o, l, f)				\
535	((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f),	\
536	 wbflush()))
537#define	BUS_SPACE_BARRIER_READ	0x01
538#define	BUS_SPACE_BARRIER_WRITE	0x02
539
540
541/*
542 * Bus read (single) operations.
543 */
544#define	bus_space_read_1(t, h, o)	__ebs_rs(1,uint8_t,(t),(h),(o))
545#define	bus_space_read_2(t, h, o)	__ebs_rs(2,uint16_t,(t),(h),(o))
546#define	bus_space_read_4(t, h, o)	__ebs_rs(4,uint32_t,(t),(h),(o))
547#define	bus_space_read_8(t, h, o)	__ebs_rs(8,uint64_t,(t),(h),(o))
548
549
550/*
551 * Bus read multiple operations.
552 */
553#define	bus_space_read_multi_1(t, h, o, a, c)				\
554	__ebs_nonsingle(rm,1,uint8_t,(t),(h),(o),(a),(c))
555#define	bus_space_read_multi_2(t, h, o, a, c)				\
556	__ebs_nonsingle(rm,2,uint16_t,(t),(h),(o),(a),(c))
557#define	bus_space_read_multi_4(t, h, o, a, c)				\
558	__ebs_nonsingle(rm,4,uint32_t,(t),(h),(o),(a),(c))
559#define	bus_space_read_multi_8(t, h, o, a, c)				\
560	__ebs_nonsingle(rm,8,uint64_t,(t),(h),(o),(a),(c))
561
562
563/*
564 * Bus read region operations.
565 */
566#define	bus_space_read_region_1(t, h, o, a, c)				\
567	__ebs_nonsingle(rr,1,uint8_t,(t),(h),(o),(a),(c))
568#define	bus_space_read_region_2(t, h, o, a, c)				\
569	__ebs_nonsingle(rr,2,uint16_t,(t),(h),(o),(a),(c))
570#define	bus_space_read_region_4(t, h, o, a, c)				\
571	__ebs_nonsingle(rr,4,uint32_t,(t),(h),(o),(a),(c))
572#define	bus_space_read_region_8(t, h, o, a, c)				\
573	__ebs_nonsingle(rr,8,uint64_t,(t),(h),(o),(a),(c))
574
575
576/*
577 * Bus write (single) operations.
578 */
579#define	bus_space_write_1(t, h, o, v)	__ebs_ws(1,uint8_t,(t),(h),(o),(v))
580#define	bus_space_write_2(t, h, o, v)	__ebs_ws(2,uint16_t,(t),(h),(o),(v))
581#define	bus_space_write_4(t, h, o, v)	__ebs_ws(4,uint32_t,(t),(h),(o),(v))
582#define	bus_space_write_8(t, h, o, v)	__ebs_ws(8,uint64_t,(t),(h),(o),(v))
583
584
585/*
586 * Bus write multiple operations.
587 */
588#define	bus_space_write_multi_1(t, h, o, a, c)				\
589	__ebs_nonsingle(wm,1,uint8_t,(t),(h),(o),(a),(c))
590#define	bus_space_write_multi_2(t, h, o, a, c)				\
591	__ebs_nonsingle(wm,2,uint16_t,(t),(h),(o),(a),(c))
592#define	bus_space_write_multi_4(t, h, o, a, c)				\
593	__ebs_nonsingle(wm,4,uint32_t,(t),(h),(o),(a),(c))
594#define	bus_space_write_multi_8(t, h, o, a, c)				\
595	__ebs_nonsingle(wm,8,uint64_t,(t),(h),(o),(a),(c))
596
597
598/*
599 * Bus write region operations.
600 */
601#define	bus_space_write_region_1(t, h, o, a, c)				\
602	__ebs_nonsingle(wr,1,uint8_t,(t),(h),(o),(a),(c))
603#define	bus_space_write_region_2(t, h, o, a, c)				\
604	__ebs_nonsingle(wr,2,uint16_t,(t),(h),(o),(a),(c))
605#define	bus_space_write_region_4(t, h, o, a, c)				\
606	__ebs_nonsingle(wr,4,uint32_t,(t),(h),(o),(a),(c))
607#define	bus_space_write_region_8(t, h, o, a, c)				\
608	__ebs_nonsingle(wr,8,uint64_t,(t),(h),(o),(a),(c))
609
610
611/*
612 * Set multiple operations.
613 */
614#define	bus_space_set_multi_1(t, h, o, v, c)				\
615	__ebs_set(sm,1,uint8_t,(t),(h),(o),(v),(c))
616#define	bus_space_set_multi_2(t, h, o, v, c)				\
617	__ebs_set(sm,2,uint16_t,(t),(h),(o),(v),(c))
618#define	bus_space_set_multi_4(t, h, o, v, c)				\
619	__ebs_set(sm,4,uint32_t,(t),(h),(o),(v),(c))
620#define	bus_space_set_multi_8(t, h, o, v, c)				\
621	__ebs_set(sm,8,uint64_t,(t),(h),(o),(v),(c))
622
623
624/*
625 * Set region operations.
626 */
627#define	bus_space_set_region_1(t, h, o, v, c)				\
628	__ebs_set(sr,1,uint8_t,(t),(h),(o),(v),(c))
629#define	bus_space_set_region_2(t, h, o, v, c)				\
630	__ebs_set(sr,2,uint16_t,(t),(h),(o),(v),(c))
631#define	bus_space_set_region_4(t, h, o, v, c)				\
632	__ebs_set(sr,4,uint32_t,(t),(h),(o),(v),(c))
633#define	bus_space_set_region_8(t, h, o, v, c)				\
634	__ebs_set(sr,8,uint64_t,(t),(h),(o),(v),(c))
635
636
637/*
638 * Copy region operations.
639 */
640#define	bus_space_copy_region_1(t, h1, o1, h2, o2, c)			\
641	__ebs_copy(1, uint8_t, (t), (h1), (o1), (h2), (o2), (c))
642#define	bus_space_copy_region_2(t, h1, o1, h2, o2, c)			\
643	__ebs_copy(2, uint16_t, (t), (h1), (o1), (h2), (o2), (c))
644#define	bus_space_copy_region_4(t, h1, o1, h2, o2, c)			\
645	__ebs_copy(4, uint32_t, (t), (h1), (o1), (h2), (o2), (c))
646#define	bus_space_copy_region_8(t, h1, o1, h2, o2, c)			\
647	__ebs_copy(8, uint64_t, (t), (h1), (o1), (h2), (o2), (c))
648
649/*
650 * Bus stream operations--defined in terms of non-stream counterparts
651 */
652#define	__BUS_SPACE_HAS_STREAM_METHODS 1
653#define	bus_space_read_stream_1 bus_space_read_1
654#define	bus_space_read_stream_2 bus_space_read_2
655#define	bus_space_read_stream_4 bus_space_read_4
656#define	bus_space_read_stream_8 bus_space_read_8
657#define	bus_space_read_multi_stream_1 bus_space_read_multi_1
658#define	bus_space_read_multi_stream_2 bus_space_read_multi_2
659#define	bus_space_read_multi_stream_4 bus_space_read_multi_4
660#define	bus_space_read_multi_stream_8 bus_space_read_multi_8
661#define	bus_space_read_region_stream_1 bus_space_read_region_1
662#define	bus_space_read_region_stream_2 bus_space_read_region_2
663#define	bus_space_read_region_stream_4 bus_space_read_region_4
664#define	bus_space_read_region_stream_8 bus_space_read_region_8
665#define	bus_space_write_stream_1 bus_space_write_1
666#define	bus_space_write_stream_2 bus_space_write_2
667#define	bus_space_write_stream_4 bus_space_write_4
668#define	bus_space_write_stream_8 bus_space_write_8
669#define	bus_space_write_multi_stream_1 bus_space_write_multi_1
670#define	bus_space_write_multi_stream_2 bus_space_write_multi_2
671#define	bus_space_write_multi_stream_4 bus_space_write_multi_4
672#define	bus_space_write_multi_stream_8 bus_space_write_multi_8
673#define	bus_space_write_region_stream_1 bus_space_write_region_1
674#define	bus_space_write_region_stream_2 bus_space_write_region_2
675#define	bus_space_write_region_stream_4 bus_space_write_region_4
676#define	bus_space_write_region_stream_8	bus_space_write_region_8
677
678#endif /* _KERNEL */
679
680/*
681 * Flags used in various bus DMA methods.
682 */
683#define	BUS_DMA_WAITOK		0x000	/* safe to sleep (pseudo-flag) */
684#define	BUS_DMA_NOWAIT		0x001	/* not safe to sleep */
685#define	BUS_DMA_ALLOCNOW	0x002	/* perform resource allocation now */
686#define	BUS_DMA_COHERENT	0x004	/* hint: map memory DMA coherent */
687#define	BUS_DMA_STREAMING	0x008	/* hint: sequential, unidirectional */
688#define	BUS_DMA_BUS1		0x010	/* placeholders for bus functions... */
689#define	BUS_DMA_BUS2		0x020
690#define	BUS_DMA_BUS3		0x040
691#define	BUS_DMA_BUS4		0x080
692#define	BUS_DMA_READ		0x100	/* mapping is device -> memory only */
693#define	BUS_DMA_WRITE		0x200	/* mapping is memory -> device only */
694#define	BUS_DMA_NOCACHE		0x400	/* hint: map non-cached memory */
695
696#define	EWS4800MIPS_DMAMAP_COHERENT	0x10000	/* no cache flush necessary on sync */
697
698/* Forwards needed by prototypes below. */
699struct mbuf;
700struct uio;
701
702/*
703 * Operations performed by bus_dmamap_sync().
704 */
705#define	BUS_DMASYNC_PREREAD	0x01	/* pre-read synchronization */
706#define	BUS_DMASYNC_POSTREAD	0x02	/* post-read synchronization */
707#define	BUS_DMASYNC_PREWRITE	0x04	/* pre-write synchronization */
708#define	BUS_DMASYNC_POSTWRITE	0x08	/* post-write synchronization */
709
710typedef struct ews4800mips_bus_dma_tag		*bus_dma_tag_t;
711typedef struct ews4800mips_bus_dmamap		*bus_dmamap_t;
712
713#define	BUS_DMA_TAG_VALID(t)    ((t) != (bus_dma_tag_t)0)
714
715/*
716 *	bus_dma_segment_t
717 *
718 *	Describes a single contiguous DMA transaction.  Values
719 *	are suitable for programming into DMA registers.
720 */
721struct ews4800mips_bus_dma_segment {
722	bus_addr_t	ds_addr;	/* DMA address */
723	bus_size_t	ds_len;		/* length of transfer */
724	vaddr_t		_ds_vaddr;	/* virtual address, 0 if invalid */
725};
726typedef struct ews4800mips_bus_dma_segment	bus_dma_segment_t;
727
728/*
729 *	bus_dma_tag_t
730 *
731 *	A machine-dependent opaque type describing the implementation of
732 *	DMA for a given bus.
733 */
734
735struct ews4800mips_bus_dma_tag {
736	/*
737	 * DMA mapping methods.
738	 */
739	int	(*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
740		    bus_size_t, bus_size_t, int, bus_dmamap_t *);
741	void	(*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
742	int	(*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
743		    bus_size_t, struct proc *, int);
744	int	(*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
745		    struct mbuf *, int);
746	int	(*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
747		    struct uio *, int);
748	int	(*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
749		    bus_dma_segment_t *, int, bus_size_t, int);
750	void	(*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
751	void	(*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
752		    bus_addr_t, bus_size_t, int);
753
754	/*
755	 * DMA memory utility functions.
756	 */
757	int	(*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
758		    bus_size_t, bus_dma_segment_t *, int, int *, int);
759	void	(*_dmamem_free)(bus_dma_tag_t,
760		    bus_dma_segment_t *, int);
761	int	(*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
762		    int, size_t, void **, int);
763	void	(*_dmamem_unmap)(bus_dma_tag_t, void *, size_t);
764	paddr_t	(*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
765		    int, off_t, int, int);
766
767	/*
768	 * DMA controller private.
769	 */
770	void	*_dmachip_cookie;
771};
772
773#define	bus_dmamap_create(t, s, n, m, b, f, p)			\
774	(*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
775#define	bus_dmamap_destroy(t, p)				\
776	(*(t)->_dmamap_destroy)((t), (p))
777#define	bus_dmamap_load(t, m, b, s, p, f)			\
778	(*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
779#define	bus_dmamap_load_mbuf(t, m, b, f)			\
780	(*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
781#define	bus_dmamap_load_uio(t, m, u, f)				\
782	(*(t)->_dmamap_load_uio)((t), (m), (u), (f))
783#define	bus_dmamap_load_raw(t, m, sg, n, s, f)			\
784	(*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
785#define	bus_dmamap_unload(t, p)					\
786	(*(t)->_dmamap_unload)((t), (p))
787#define	bus_dmamap_sync(t, p, o, l, ops)			\
788	(*(t)->_dmamap_sync)((t), (p), (o), (l), (ops))
789
790#define	bus_dmamem_alloc(t, s, a, b, sg, n, r, f)		\
791	(*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
792#define	bus_dmamem_free(t, sg, n)				\
793	(*(t)->_dmamem_free)((t), (sg), (n))
794#define	bus_dmamem_map(t, sg, n, s, k, f)			\
795	(*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
796#define	bus_dmamem_unmap(t, k, s)				\
797	(*(t)->_dmamem_unmap)((t), (k), (s))
798#define	bus_dmamem_mmap(t, sg, n, o, p, f)			\
799	(*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
800
801#define bus_dmatag_subregion(t, mna, mxa, nt, f) EOPNOTSUPP
802#define bus_dmatag_destroy(t)
803
804/*
805 *	bus_dmamap_t
806 *
807 *	Describes a DMA mapping.
808 */
809struct ews4800mips_bus_dmamap {
810	/*
811	 * PRIVATE MEMBERS: not for use my machine-independent code.
812	 */
813	bus_size_t	_dm_size;	/* largest DMA transfer mappable */
814	int		_dm_segcnt;	/* number of segs this map can map */
815	bus_size_t	_dm_maxmaxsegsz; /* fixed largest possible segment */
816	bus_size_t	_dm_boundary;	/* don't cross this */
817	int		_dm_flags;	/* misc. flags */
818	struct vmspace	*_dm_vmspace;	/* vmspace that owns the mapping */
819
820	/*
821	 * PUBLIC MEMBERS: these are used by machine-independent code.
822	 */
823	bus_size_t	dm_maxsegsz;	/* largest possible segment */
824	bus_size_t	dm_mapsize;	/* size of the mapping */
825	int		dm_nsegs;	/* # valid segments in mapping */
826	bus_dma_segment_t dm_segs[1];	/* segments; variable length */
827};
828
829#ifdef _EWS4800MIPS_BUS_DMA_PRIVATE
830int	_bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
831	    bus_size_t, int, bus_dmamap_t *);
832void	_bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
833int	_bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
834	    bus_size_t, struct proc *, int);
835int	_bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
836	    struct mbuf *, int);
837int	_bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
838	    struct uio *, int);
839int	_bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
840	    bus_dma_segment_t *, int, bus_size_t, int);
841void	_bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
842void	_bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
843	    bus_size_t, int);
844
845int	_bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
846	    bus_size_t alignment, bus_size_t boundary,
847	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
848void	_bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
849	    int nsegs);
850int	_bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
851	    int nsegs, size_t size, void **kvap, int flags);
852void	_bus_dmamem_unmap(bus_dma_tag_t tag, void *kva,
853	    size_t size);
854paddr_t	_bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
855	    int nsegs, off_t off, int prot, int flags);
856
857int	_bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
858	    bus_size_t alignment, bus_size_t boundary,
859	    bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
860	    vaddr_t low, vaddr_t high);
861
862extern struct ews4800mips_bus_dma_tag ews4800mips_default_bus_dma_tag;
863#endif /* _EWS4800MIPS_BUS_DMA_PRIVATE */
864
865#endif /* _EWS4800MIPS_BUS_H_ */
866