autoconf.c revision 1.42
1/*	$NetBSD: autoconf.c,v 1.42 1996/10/11 19:49:49 mhitch Exp $	*/
2
3/*
4 * Copyright (c) 1994 Christian E. Hopps
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed by Christian E. Hopps.
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/reboot.h>
35#include <sys/conf.h>
36#include <sys/device.h>
37#include <sys/disklabel.h>
38#include <machine/cpu.h>
39#include <amiga/amiga/cfdev.h>
40#include <amiga/amiga/device.h>
41#include <amiga/amiga/custom.h>
42
43void setroot __P((void));
44void swapconf __P((void));
45void mbattach __P((struct device *, struct device *, void *));
46int mbprint __P((void *, const char *));
47int mbmatch __P((struct device *, void *, void *));
48
49int cold;	/* 1 if still booting */
50#include <sys/kernel.h>
51/*
52 * called at boot time, configure all devices on system
53 */
54void
55configure()
56{
57	/*
58	 * this is the real thing baby (i.e. not console init)
59	 */
60	amiga_realconfig = 1;
61#ifdef DRACO
62	if (is_draco()) {
63		*draco_intena &= ~DRIRQ_GLOBAL;
64	} else
65#endif
66	custom.intena = INTF_INTEN;
67
68	if (config_rootfound("mainbus", "mainbus") == NULL)
69		panic("no mainbus found");
70
71#ifdef DEBUG_KERNEL_START
72	kprintf("survived autoconf, going to enable interrupts\n");
73#endif
74
75#ifdef DRACO
76	if (is_draco()) {
77		*draco_intena |= DRIRQ_GLOBAL;
78		/* softints always enabled */
79	} else
80#endif
81	{
82		custom.intena = INTF_SETCLR | INTF_INTEN;
83
84		/* also enable hardware aided software interrupts */
85		custom.intena = INTF_SETCLR | INTF_SOFTINT;
86	}
87#ifdef DEBUG_KERNEL_START
88	kprintf("survived interrupt enable\n");
89#endif
90
91#ifdef GENERIC
92	if ((boothowto & RB_ASKNAME) == 0) {
93		setroot();
94#ifdef DEBUG_KERNEL_START
95		kprintf("survived setroot()\n");
96#endif
97	}
98	setconf();
99#ifdef DEBUG_KERNEL_START
100	kprintf("survived setconf()\n");
101#endif
102#else
103	setroot();
104#ifdef DEBUG_KERNEL_START
105	kprintf("survived setroot()\n");
106#endif
107#endif
108#ifdef DEBUG_KERNEL_START
109	kprintf("survived root device search\n");
110#endif
111	swapconf();
112#ifdef DEBUG_KERNEL_START
113	kprintf("survived swap device search\n");
114#endif
115	cold = 0;
116}
117
118/*ARGSUSED*/
119int
120simple_devprint(auxp, pnp)
121	void *auxp;
122	const char *pnp;
123{
124	return(QUIET);
125}
126
127int
128matchname(fp, sp)
129	char *fp, *sp;
130{
131	int len;
132
133	len = strlen(fp);
134	if (strlen(sp) != len)
135		return(0);
136	if (bcmp(fp, sp, len) == 0)
137		return(1);
138	return(0);
139}
140
141/*
142 * use config_search to find appropriate device, then call that device
143 * directly with NULL device variable storage.  A device can then
144 * always tell the difference betwean the real and console init
145 * by checking for NULL.
146 */
147int
148amiga_config_found(pcfp, pdp, auxp, pfn)
149	struct cfdata *pcfp;
150	struct device *pdp;
151	void *auxp;
152	cfprint_t pfn;
153{
154	struct device temp;
155	struct cfdata *cf;
156
157	if (amiga_realconfig)
158		return(config_found(pdp, auxp, pfn) != NULL);
159
160	if (pdp == NULL)
161		pdp = &temp;
162
163	pdp->dv_cfdata = pcfp;
164	if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) {
165		cf->cf_attach->ca_attach(pdp, NULL, auxp);
166		pdp->dv_cfdata = NULL;
167		return(1);
168	}
169	pdp->dv_cfdata = NULL;
170	return(0);
171}
172
173/*
174 * this function needs to get enough configured to do a console
175 * basically this means start attaching the grfxx's that support
176 * the console. Kinda hacky but it works.
177 */
178void
179config_console()
180{
181	struct cfdata *cf;
182
183	/*
184	 * we need mainbus' cfdata.
185	 */
186	cf = config_rootsearch(NULL, "mainbus", "mainbus");
187	if (cf == NULL) {
188		panic("no mainbus");
189	}
190	/*
191	 * internal grf.
192	 */
193#ifdef DRACO
194	if (!(is_draco()))
195#endif
196		amiga_config_found(cf, NULL, "grfcc", NULL);
197	/*
198	 * zbus knows when its not for real and will
199	 * only configure the appropriate hardware
200	 */
201	amiga_config_found(cf, NULL, "zbus", NULL);
202}
203
204/*
205 * mainbus driver
206 */
207struct cfattach mainbus_ca = {
208	sizeof(struct device), mbmatch, mbattach
209};
210
211struct cfdriver mainbus_cd = {
212	NULL, "mainbus", DV_DULL, NULL, 0
213};
214
215int
216mbmatch(pdp, match, auxp)
217	struct device *pdp;
218	void *match, *auxp;
219{
220	struct cfdata *cfp = match;
221
222	if (cfp->cf_unit > 0)
223		return(0);
224	/*
225	 * We are always here
226	 */
227	return(1);
228}
229
230/*
231 * "find" all the things that should be there.
232 */
233void
234mbattach(pdp, dp, auxp)
235	struct device *pdp, *dp;
236	void *auxp;
237{
238	kprintf("\n");
239	config_found(dp, "clock", simple_devprint);
240#ifdef DRACO
241	if (is_draco()) {
242		config_found(dp, "kbd", simple_devprint);
243		config_found(dp, "drsc", simple_devprint);
244		/*
245		 * XXX -- missing here:
246		 * SuperIO chip serial, parallel, floppy
247		 * or maybe just make that into a pseudo
248		 * ISA bus.
249		 */
250	} else
251#endif
252	{
253		config_found(dp, "ser", simple_devprint);
254		config_found(dp, "par", simple_devprint);
255		config_found(dp, "kbd", simple_devprint);
256		config_found(dp, "ms", simple_devprint);
257		config_found(dp, "ms", simple_devprint);
258		config_found(dp, "grfcc", simple_devprint);
259		config_found(dp, "fdc", simple_devprint);
260	}
261	if (is_a4000() || is_a1200())
262		config_found(dp, "idesc", simple_devprint);
263	if (is_a4000())			/* Try to configure A4000T SCSI */
264		config_found(dp, "afsc", simple_devprint);
265	config_found(dp, "zbus", simple_devprint);
266	if (is_a3000())
267		config_found(dp, "ahsc", simple_devprint);
268}
269
270int
271mbprint(auxp, pnp)
272	void *auxp;
273	const char *pnp;
274{
275	if (pnp)
276		kprintf("%s at %s", (char *)auxp, pnp);
277	return(UNCONF);
278}
279
280void
281swapconf()
282{
283	struct swdevt *swp;
284	u_int maj;
285	int nb;
286
287	for (swp = swdevt; swp->sw_dev > 0; swp++) {
288		maj = major(swp->sw_dev);
289
290		if (maj > nblkdev)
291			break;
292
293		if (bdevsw[maj].d_psize) {
294			nb = bdevsw[maj].d_psize(swp->sw_dev);
295			if (nb > 0 &&
296			    (swp->sw_nblks == 0 || swp->sw_nblks > nb))
297				swp->sw_nblks = nb;
298			else
299				swp->sw_nblks = 0;
300		}
301		swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
302	}
303	dumpconf();
304	if (dumplo < 0)
305		dumplo = 0;
306
307}
308
309#define	DOSWAP			/* change swdevt and dumpdev */
310u_long	bootdev = 0;		/* should be dev_t, but not until 32 bits */
311
312static	char devname[][2] = {
313	{ 0	,0	},
314	{ 0	,0	},
315	{ 'f'	,'d'	},	/* 2 = fd */
316	{ 0	,0	},
317	{ 's'	,'d'	}	/* 4 = sd -- new SCSI system */
318};
319
320void
321setroot()
322{
323	int majdev, mindev, unit, part, adaptor;
324	dev_t temp = 0;
325	dev_t orootdev;
326	struct swdevt *swp;
327
328	if (boothowto & RB_DFLTROOT ||
329	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
330		return;
331	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
332	if (majdev > sizeof(devname) / sizeof(devname[0]))
333		return;
334	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
335	part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
336	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
337	orootdev = rootdev;
338	rootdev = MAKEDISKDEV(majdev, unit, part);
339	/*
340	 * If the original rootdev is the same as the one
341	 * just calculated, don't need to adjust the swap configuration.
342	 */
343	if (rootdev == orootdev)
344		return;
345	kprintf("changing root device to %c%c%d%c\n",
346	    devname[majdev][0], devname[majdev][1],
347	    unit, part + 'a');
348#ifdef DOSWAP
349	mindev = DISKUNIT(rootdev);
350	for (swp = swdevt; swp->sw_dev; swp++) {
351		if (majdev == major(swp->sw_dev) &&
352		    mindev == DISKUNIT(swp->sw_dev)) {
353			temp = swdevt[0].sw_dev;
354			swdevt[0].sw_dev = swp->sw_dev;
355			swp->sw_dev = temp;
356			break;
357		}
358	}
359	if (swp->sw_dev == 0)
360		return;
361	/*
362	 * If dumpdev was the same as the old primary swap
363	 * device, move it to the new primary swap device.
364	 */
365	if (temp == dumpdev)
366		dumpdev = swdevt[0].sw_dev;
367#endif
368}
369
370
371/*
372 * Try to determine, of this machine is an A3000, which has a builtin
373 * realtime clock and scsi controller, so that this hardware is only
374 * included as "configured" if this IS an A3000
375 */
376
377int a3000_flag = 1;		/* patchable */
378#ifdef A4000
379int a4000_flag = 1;		/* patchable - default to A4000 */
380#else
381int a4000_flag = 0;		/* patchable */
382#endif
383
384int
385is_a3000()
386{
387	/* this is a dirty kludge.. but how do you do this RIGHT ? :-) */
388	extern long boot_fphystart;
389	short sc;
390
391	if ((machineid >> 16) == 3000)
392		return (1);			/* It's an A3000 */
393	if (machineid >> 16)
394		return (0);			/* It's not an A3000 */
395	/* Machine type is unknown, so try to guess it */
396	/* where is fastram on the A4000 ?? */
397	/* if fastram is below 0x07000000, assume it's not an A3000 */
398	if (boot_fphystart < 0x07000000)
399		return(0);
400	/*
401	 * OK, fastram starts at or above 0x07000000, check specific
402	 * machines
403	 */
404	for (sc = 0; sc < ncfdev; sc++) {
405		switch (cfdev[sc].rom.manid) {
406		case 2026:		/* Progressive Peripherals, Inc */
407			switch (cfdev[sc].rom.prodid) {
408			case 0:		/* PPI Mercury - A3000 */
409			case 1:		/* PP&S A3000 '040 */
410				return(1);
411			case 150:	/* PPI Zeus - it's an A2000 */
412			case 105:	/* PP&S A2000 '040 */
413			case 187:	/* PP&S A500 '040 */
414				return(0);
415			}
416			break;
417
418		case 2112:			/* IVS */
419			switch (cfdev[sc].rom.prodid) {
420			case 242:
421				return(0);	/* A2000 accelerator? */
422			}
423			break;
424		}
425	}
426	return (a3000_flag);		/* XXX let flag tell now */
427}
428
429int
430is_a4000()
431{
432	if ((machineid >> 16) == 4000)
433		return (1);		/* It's an A4000 */
434	if ((machineid >> 16) == 1200)
435		return (0);		/* It's an A1200, so not A4000 */
436#ifdef DRACO
437	if (is_draco())
438		return (0);
439#endif
440	/* Do I need this any more? */
441	if ((custom.deniseid & 0xff) == 0xf8)
442		return (1);
443#ifdef DEBUG
444	if (a4000_flag)
445		kprintf("Denise ID = %04x\n", (unsigned short)custom.deniseid);
446#endif
447	if (machineid >> 16)
448		return (0);		/* It's not an A4000 */
449	return (a4000_flag);		/* Machine type not set */
450}
451
452int
453is_a1200()
454{
455	if ((machineid >> 16) == 1200)
456		return (1);		/* It's an A1200 */
457	return (0);			/* Machine type not set */
458}
459
460#ifdef DRACO
461int
462is_draco()
463{
464	if ((machineid >> 24) == 0x7D)
465		return ((machineid >> 16) & 0xFF);
466	return (0);
467}
468#endif
469