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