obio.c revision 1.1
1/*	$NetBSD: obio.c,v 1.1 1997/01/14 20:57:03 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#include <sys/param.h>
40#include <sys/systm.h>
41#include <sys/device.h>
42
43#include <machine/autoconf.h>
44#include <machine/pte.h>
45#include <machine/mon.h>
46#include <machine/obio.h>
47
48short *enable_reg;
49
50static int  obio_match __P((struct device *, struct cfdata *, void *));
51static void obio_attach __P((struct device *, struct device *, void *));
52static int  obio_print __P((void *, const char *parentname));
53static int	obio_submatch __P((struct device *, struct cfdata *, void *));
54
55struct cfattach obio_ca = {
56	sizeof(struct device), obio_match, obio_attach
57};
58
59struct cfdriver obio_cd = {
60	NULL, "obio", DV_DULL
61};
62
63static int
64obio_match(parent, cf, aux)
65	struct device *parent;
66	struct cfdata *cf;
67	void *aux;
68{
69	struct confargs *ca = aux;
70
71	if (ca->ca_bustype != BUS_OBIO)
72		return (0);
73	return(1);
74}
75
76/*
77 * We need some control over the order of attachment on OBIO,
78 * and all OBIO device addresses are known and fixed foerver.
79 * Therefore, this uses a list of addresses to attach.
80 * XXX - Any other way to control search/attach order?
81 */
82static int obio_alist[] = {
83	OBIO_ZS_KBD_MS,
84	OBIO_ZS_TTY_AB,
85
86	OBIO_EEPROM,	/* the next two are part of the eeprom */
87	OBIO_IDPROM2,	/* 3/80 only */
88	OBIO_CLOCK2,	/* 3/80 only */
89
90	OBIO_CLOCK1,	/* 3/470 only */
91
92	/* These are all in the same page - could be just one driver... */
93	OBIO_ENABLEREG,
94	OBIO_BUSERRREG,
95	OBIO_DIAGREG,
96	OBIO_IDPROM1,
97	OBIO_MEMREG,
98	OBIO_INTERREG,
99
100	OBIO_P4_REG,
101	OBIO_IOMMU,
102
103	OBIO_INTEL_ETHER,
104	OBIO_LANCE_ETHER,
105
106	/* ...todo... */
107	OBIO_FDC,
108	OBIO_PRINTER_PORT,
109};
110#define	OBIO_ALIST_LEN (sizeof(obio_alist) / \
111						sizeof(obio_alist[0]))
112
113static void
114obio_attach(parent, self, aux)
115	struct device *parent;
116	struct device *self;
117	void *aux;
118{
119	struct confargs *ca = aux;
120	int	i;
121
122	printf("\n");
123
124	/* Configure these in order of address. */
125	for (i = 0; i < OBIO_ALIST_LEN; i++) {
126		/* We know ca_bustype == BUS_OBIO */
127		ca->ca_paddr = obio_alist[i];
128		ca->ca_intpri = -1;
129		ca->ca_intvec = -1;
130		(void) config_found_sm(self, ca, obio_print, obio_submatch);
131	}
132}
133
134/*
135 * Print out the confargs.  The (parent) name is non-NULL
136 * when there was no match found by config_found().
137 */
138static int
139obio_print(args, name)
140	void *args;
141	const char *name;
142{
143	struct confargs *ca = args;
144
145	/* Be quiet about empty OBIO locations. */
146	if (name)
147		return(QUIET);
148
149	if (ca->ca_paddr != -1)
150		printf(" addr 0x%x", ca->ca_paddr);
151	if (ca->ca_intpri != -1)
152		printf(" level %d", ca->ca_intpri);
153
154	return(UNCONF);
155}
156
157int
158obio_submatch(parent, cf, aux)
159	struct device *parent;
160	struct cfdata *cf;
161	void *aux;
162{
163	struct confargs *ca = aux;
164	cfmatch_t submatch;
165
166	/*
167	 * Default addresses are mostly useless for OBIO.
168	 * The address assignments are fixed for all time,
169	 * so our config files might as well reflect that.
170	 */
171#ifdef	DIAGNOSTIC
172	if (cf->cf_paddr == -1)
173		panic("obio_submatch: invalid address for: %s%d\n",
174			cf->cf_driver->cd_name, cf->cf_unit);
175#endif
176
177	/* This enforces exact address match. */
178	if (cf->cf_paddr != ca->ca_paddr)
179		return 0;
180
181	/* Now call the match function of the potential child. */
182	submatch = cf->cf_attach->ca_match;
183	if (submatch == NULL)
184		panic("obio_submatch: no match function for: %s\n",
185			  cf->cf_driver->cd_name);
186
187	return ((*submatch)(parent, cf, aux));
188}
189
190
191/*****************************************************************/
192
193/*
194 * This is our record of "interesting" OBIO mappings that
195 * the PROM has left in the virtual space reserved for it.
196 * Each non-null array element holds the virtual address
197 * of an OBIO mapping where the OBIO address mapped is:
198 *     (array_index * SAVE_INCR)
199 * and the length of the mapping is one page.
200 */
201static struct prom_map {
202	vm_offset_t pa, va;
203} prom_mappings[] = {
204	{ OBIO_ZS_KBD_MS, 0 },	/* Keyboard and Mouse */
205	{ OBIO_ZS_TTY_AB, 0 },	/* Serial Ports */
206	{ OBIO_EEPROM,    0 },	/* EEPROM/IDPROM/clock */
207	{ OBIO_ENABLEREG, 0 },	/* regs: Sys ENA, Bus ERR, etc. */
208};
209#define PROM_MAP_CNT (sizeof(prom_mappings) / \
210		      sizeof(prom_mappings[0]))
211
212/*
213 * Find a virtual address for a device at physical address 'pa'.
214 * If one is found among the mappings already made by the PROM
215 * at power-up time, use it.  Otherwise return 0 as a sign that
216 * a mapping will have to be created.
217 */
218caddr_t
219obio_find_mapping(int pa, int size)
220{
221	int i, off;
222
223	if (size >= NBPG)
224		return (caddr_t)0;
225
226	off = pa & PGOFSET;
227	pa -= off;
228
229	for (i = 0; i < PROM_MAP_CNT; i++) {
230		if (pa == prom_mappings[i].pa) {
231			return ((caddr_t)(prom_mappings[i].va + off));
232		}
233	}
234	return (caddr_t)0;
235}
236
237/*
238 * Search the PROM page tables for OBIO mappings that
239 * we would like to borrow.
240 */
241static void
242save_prom_mappings __P((void))
243{
244	int *mon_pte;
245	vm_offset_t va, pa;
246	int i;
247
248	/* Note: mon_ctbl[0] maps MON_KDB_START */
249	mon_pte = *romVectorPtr->monptaddr;
250
251	for (va = MON_KDB_START; va < MONEND;
252		 va += NBPG, mon_pte++)
253	{
254		/* Is this a valid mapping to OBIO? */
255		/* XXX - Some macros would be nice... */
256		if ((*mon_pte & 0xF0000003) != 0x60000001)
257			continue;
258
259		/* Yes it is.  Is this a mapping we want? */
260		pa = *mon_pte & MMU_SHORT_PTE_BASEADDR;
261		for (i = 0; i < PROM_MAP_CNT; i++) {
262			if (pa != prom_mappings[i].pa)
263				continue;
264			/* Yes, we want it.  Save the va? */
265			if (prom_mappings[i].va == 0) {
266				prom_mappings[i].va = va;
267			}
268		}
269	}
270
271}
272
273/*
274 * These are all the OBIO address that are required early in
275 * the life of the kernel.  All are less than one page long.
276 * This function should make any required mappings that we
277 * were not able to find among the PROM monitor's mappings.
278 */
279static void
280make_required_mappings __P((void))
281{
282	int i;
283
284	for (i = 0; i < PROM_MAP_CNT; i++) {
285		if (prom_mappings[i].va == 0) {
286			/*
287			 * Actually, the PROM always has all the
288			 * "required" mappings we need, (smile)
289			 * but this makes sure that is true.
290			 */
291			mon_printf("obio: no mapping for 0x%x\n",
292			    prom_mappings[i].pa);
293			mon_panic("obio: Ancient PROM?\n");
294		}
295	}
296}
297
298
299/*
300 * Find mappings for devices that are needed before autoconfiguration.
301 * We first look for and record any useful PROM mappings, then call
302 * the "init" functions for drivers that we need to use before the
303 * normal autoconfiguration calls configure().  Warning: this is
304 * called before pmap_bootstrap, so no allocation allowed!
305 */
306void
307obio_init()
308{
309	save_prom_mappings();
310	make_required_mappings();
311
312	/* Init drivers that use the required OBIO mappings. */
313	idprom_init();
314	eeprom_init();
315	zs_init();
316
317	enable_reg = (short*) obio_find_mapping(OBIO_ENABLEREG, 2);
318	intreg_init();
319	clock_init();
320}
321
322caddr_t
323obio_alloc(obio_addr, obio_size)
324	int obio_addr, obio_size;
325{
326	caddr_t cp;
327
328	cp = obio_find_mapping((vm_offset_t)obio_addr, obio_size);
329	if (cp) return (cp);
330
331	cp = bus_mapin(BUS_OBIO, obio_addr, obio_size);
332	return (cp);
333}
334