xref: /netbsd-src/sys/arch/sun3/sun3x/bus_subr.c (revision 037708cbd4616ccd0d7d0381ebd3964d6696c188)
1 /*	$NetBSD: bus_subr.c,v 1.5 1997/04/25 18:02:47 gwr 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 /* This is defined in _startup.c */
136 extern vm_offset_t tmp_vpages[];
137 
138 static const int bustype_to_patype[4] = {
139 	0,		/* OBMEM  */
140 	0,		/* OBIO   */
141 	PMAP_VME16,	/* VMED16 */
142 	PMAP_VME32,	/* VMED32 */
143 };
144 
145 /*
146  * Read addr with size len (1,2,4) into val.
147  * If this generates a bus error, return -1
148  *
149  *	Create a temporary mapping,
150  *	Try the access using peek_*
151  *	Clean up temp. mapping
152  */
153 int bus_peek(bustype, paddr, sz)
154 	int bustype, paddr, sz;
155 {
156 	int	offset, rtn;
157 	vm_offset_t va_page;
158 	caddr_t va;
159 
160 	/* XXX - Must fix for VME support... */
161 	if (bustype != OBIO && bustype != OBMEM)
162 		return -1;
163 
164 	offset = paddr & ~(MMU_PAGE_MASK);
165 	paddr = _trunc_page(paddr);
166 	paddr |= bustype_to_patype[bustype];
167 	paddr |= PMAP_NC;
168 
169 	va_page = tmp_vpages[0];
170 	va      = (caddr_t) va_page + offset;
171 
172 	pmap_enter(pmap_kernel(), va_page, paddr, (VM_PROT_READ|VM_PROT_WRITE),
173 		TRUE);
174 
175 	switch (sz) {
176 		case 1:
177 			rtn = peek_byte(va);
178 			break;
179 		case 2:
180 			rtn = peek_word(va);
181 			break;
182 		case 4:
183 			rtn = peek_long(va);
184 			break;
185 		default:
186 			printf(" bus_peek: invalid size=%d\n", sz);
187 			rtn = -1;
188 	}
189 
190 	pmap_remove(pmap_kernel(), va_page, va_page + NBPG);
191 
192 
193 	return rtn;
194 }
195 
196 
197 void *
198 bus_mapin(bustype, paddr, sz)
199 	int bustype, paddr, sz;
200 {
201 	int off, pa, pmt;
202 	vm_offset_t va, retval;
203 
204 	if (bustype & ~3)
205 		return (NULL);
206 
207 	off = paddr & PGOFSET;
208 	pa = paddr - off;
209 	sz += off;
210 	sz = round_page(sz);
211 
212 	pmt = PMAP_NC;	/* non-cached */
213 
214 	/* Get some kernel virtual address space. */
215 	va = kmem_alloc_wait(kernel_map, sz);
216 	if (va == 0)
217 		panic("bus_mapin");
218 	retval = va + off;
219 
220 	/* Map it to the specified bus. */
221 #if 0	/* XXX */
222 	/* This has a problem with wrap-around... */
223 	pmap_map((int)va, pa | pmt, pa + sz, VM_PROT_ALL);
224 #else
225 	do {
226 		pmap_enter(pmap_kernel(), va, pa | pmt, VM_PROT_ALL, FALSE);
227 		va += NBPG;
228 		pa += NBPG;
229 	} while ((sz -= NBPG) > 0);
230 #endif
231 
232 	return ((void*)retval);
233 }
234 
235 /* from hp300: badbaddr() */
236 int
237 peek_byte(addr)
238 	register caddr_t addr;
239 {
240 	label_t 	faultbuf;
241 	register int x;
242 
243 	nofault = &faultbuf;
244 	if (setjmp(&faultbuf)) {
245 		nofault = NULL;
246 		return(-1);
247 	}
248 	x = *(volatile u_char *)addr;
249 	nofault = NULL;
250 	return(x);
251 }
252 
253 int
254 peek_word(addr)
255 	register caddr_t addr;
256 {
257 	label_t		faultbuf;
258 	register int x;
259 
260 	nofault = &faultbuf;
261 	if (setjmp(&faultbuf)) {
262 		nofault = NULL;
263 		return(-1);
264 	}
265 	x = *(volatile u_short *)addr;
266 	nofault = NULL;
267 	return(x);
268 }
269 
270 int
271 peek_long(addr)
272 	register caddr_t addr;
273 {
274 	label_t		faultbuf;
275 	register int x;
276 
277 	nofault = &faultbuf;
278 	if (setjmp(&faultbuf)) {
279 		nofault = NULL;
280 		return(-1);
281 	}
282 	x = *(volatile int *)addr;
283 	nofault = NULL;
284 	return(x);
285 }
286