xref: /netbsd-src/sys/arch/sun3/sun3x/bus_subr.c (revision fdecd6a253f999ae92b139670d9e15cc9df4497c)
1 /*	$NetBSD: bus_subr.c,v 1.8 1997/06/10 19:36:53 veego Exp $	*/
2 
3 /*-
4  * Copyright (c) 1996 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Adam Glass and Gordon W. Ross.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *        This product includes software developed by the NetBSD
21  *        Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * bus_xxx support functions
41  */
42 
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
46 
47 #include <vm/vm.h>
48 #include <vm/vm_kern.h>
49 #include <vm/vm_map.h>
50 
51 #include <machine/autoconf.h>
52 #include <machine/cpu.h>
53 #include <machine/pte.h>
54 #include <machine/pmap.h>
55 #include <machine/machdep.h>
56 #include <machine/mon.h>
57 
58 /*
59  * bus_scan:
60  * This function is passed to config_search() by the attach function
61  * for each of the "bus" drivers (obctl, obio, obmem, vmes, vmel).
62  * The purpose of this function is to copy the "locators" into our
63  * confargs structure, so child drivers may use the confargs both
64  * as match parameters and as temporary storage for the defaulted
65  * locator values determined in the child_match and preserved for
66  * the child_attach function.  If the bus attach functions just
67  * used config_found, then we would not have an opportunity to
68  * setup the confargs for each child match and attach call.
69  */
70 int bus_scan(parent, cf, aux)
71 	struct device *parent;
72 	struct cfdata *cf;
73 	void *aux;
74 {
75 	struct confargs *ca = aux;
76 	cfmatch_t mf;
77 
78 #ifdef	DIAGNOSTIC
79 	if (cf->cf_fstate == FSTATE_STAR)
80 		panic("bus_scan: FSTATE_STAR");
81 #endif
82 
83 	/*
84 	 * Copy the locators into our confargs.
85 	 * Our parent set ca->ca_bustype already.
86 	 */
87 	ca->ca_paddr  = cf->cf_paddr;
88 	ca->ca_intpri = cf->cf_intpri;
89 	ca->ca_intvec = cf->cf_intvec;
90 
91 	/*
92 	 * Note that this allows the match function to save
93 	 * defaulted locators in the confargs that will be
94 	 * preserved for the related attach call.
95 	 * XXX - This is a hack...
96 	 */
97 	mf = cf->cf_attach->ca_match;
98 	if ((*mf)(parent, cf, ca) > 0) {
99 		config_attach(parent, cf, ca, bus_print);
100 	}
101 	return (0);
102 }
103 
104 /*
105  * bus_print:
106  * Just print out the final (non-default) locators.
107  * The parent name is non-NULL when there was no match
108  * found by config_found().
109  */
110 int
111 bus_print(args, name)
112 	void *args;
113 	const char *name;
114 {
115 	struct confargs *ca = args;
116 
117 	if (name)
118 		printf("%s:", name);
119 
120 	if (ca->ca_paddr != -1)
121 		printf(" addr 0x%x", ca->ca_paddr);
122 	if (ca->ca_intpri != -1)
123 		printf(" ipl %d", ca->ca_intpri);
124 	if (ca->ca_intvec != -1)
125 		printf(" vect 0x%x", ca->ca_intvec);
126 
127 	return(UNCONF);
128 }
129 
130 /****************************************************************/
131 /* support functions */
132 
133 label_t *nofault;
134 
135 /* These are defined in pmap.c */
136 extern vm_offset_t tmp_vpages[];
137 extern int tmp_vpages_inuse;
138 
139 static const int bustype_to_patype[4] = {
140 	0,		/* OBMEM  */
141 	0,		/* OBIO   */
142 	PMAP_VME16,	/* VMED16 */
143 	PMAP_VME32,	/* VMED32 */
144 };
145 
146 /*
147  * Read addr with size len (1,2,4) into val.
148  * If this generates a bus error, return -1
149  *
150  *	Create a temporary mapping,
151  *	Try the access using peek_*
152  *	Clean up temp. mapping
153  */
154 int
155 bus_peek(bustype, paddr, sz)
156 	int bustype, paddr, sz;
157 {
158 	int	offset, rtn, s;
159 	vm_offset_t va_page;
160 	caddr_t va;
161 
162 	/* XXX - Must fix for VME support... */
163 	if (bustype != OBIO && bustype != OBMEM)
164 		return -1;
165 
166 	offset = paddr & ~(MMU_PAGE_MASK);
167 	paddr = m68k_trunc_page(paddr);
168 	paddr |= bustype_to_patype[bustype];
169 	paddr |= PMAP_NC;
170 
171 	s = splimp();
172 	if (tmp_vpages_inuse)
173 		panic("bus_peek: temporary vpages are in use.");
174 	tmp_vpages_inuse++;
175 
176 	va_page = tmp_vpages[1];
177 	va      = (caddr_t) va_page + offset;
178 
179 	pmap_enter(pmap_kernel(), va_page, paddr, (VM_PROT_READ|VM_PROT_WRITE),
180 		TRUE);
181 
182 	switch (sz) {
183 		case 1:
184 			rtn = peek_byte(va);
185 			break;
186 		case 2:
187 			rtn = peek_word(va);
188 			break;
189 		case 4:
190 			rtn = peek_long(va);
191 			break;
192 		default:
193 			printf(" bus_peek: invalid size=%d\n", sz);
194 			rtn = -1;
195 	}
196 
197 	pmap_remove(pmap_kernel(), va_page, va_page + NBPG);
198 	--tmp_vpages_inuse;
199 	splx(s);
200 
201 	return (rtn);
202 }
203 
204 
205 void *
206 bus_mapin(bustype, paddr, sz)
207 	int bustype, paddr, sz;
208 {
209 	int off, pa, pmt;
210 	vm_offset_t va, retval;
211 
212 	if (bustype & ~3)
213 		return (NULL);
214 
215 	off = paddr & PGOFSET;
216 	pa = paddr - off;
217 	sz += off;
218 	sz = round_page(sz);
219 
220 	pmt = PMAP_NC;	/* non-cached */
221 
222 	/* Get some kernel virtual address space. */
223 	va = kmem_alloc_wait(kernel_map, sz);
224 	if (va == 0)
225 		panic("bus_mapin");
226 	retval = va + off;
227 
228 	/* Map it to the specified bus. */
229 #if 0
230 	/* This has a problem with wrap-around... (on the sun3x? -j) */
231 	pmap_map((int)va, pa | pmt, pa + sz, VM_PROT_ALL);
232 #else
233 	do {
234 		pmap_enter(pmap_kernel(), va, pa | pmt, VM_PROT_ALL, FALSE);
235 		va += NBPG;
236 		pa += NBPG;
237 	} while ((sz -= NBPG) > 0);
238 #endif
239 
240 	return ((void*)retval);
241 }
242 
243 /* from hp300: badbaddr() */
244 int
245 peek_byte(addr)
246 	register caddr_t addr;
247 {
248 	label_t 	faultbuf;
249 	register int x;
250 
251 	nofault = &faultbuf;
252 	if (setjmp(&faultbuf)) {
253 		nofault = NULL;
254 		return(-1);
255 	}
256 	x = *(volatile u_char *)addr;
257 	nofault = NULL;
258 	return(x);
259 }
260 
261 int
262 peek_word(addr)
263 	register caddr_t addr;
264 {
265 	label_t		faultbuf;
266 	register int x;
267 
268 	nofault = &faultbuf;
269 	if (setjmp(&faultbuf)) {
270 		nofault = NULL;
271 		return(-1);
272 	}
273 	x = *(volatile u_short *)addr;
274 	nofault = NULL;
275 	return(x);
276 }
277 
278 int
279 peek_long(addr)
280 	register caddr_t addr;
281 {
282 	label_t		faultbuf;
283 	register int x;
284 
285 	nofault = &faultbuf;
286 	if (setjmp(&faultbuf)) {
287 		nofault = NULL;
288 		return(-1);
289 	}
290 	x = *(volatile int *)addr;
291 	nofault = NULL;
292 	return(x);
293 }
294