autoconf.c revision 1.19
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.19 1994/05/12 05:56:30 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, "ztwobus", simple_devprint);
201	if (is_a3000())
202		config_found(dp, "ahsc", simple_devprint);
203	if (is_a3000() || is_a4000()) {
204		config_found(dp, "zthreebus", simple_devprint);
205	}
206	if (is_a4000())
207		config_found(dp, "idesc", simple_devprint);
208}
209
210int
211mbprint(auxp, pnp)
212	void *auxp;
213	char *pnp;
214{
215	if (pnp)
216		printf("%s at %s", (char *)auxp, pnp);
217	return(UNCONF);
218}
219
220void
221swapconf()
222{
223	struct swdevt *swp;
224	u_int maj;
225	int nb;
226
227	for (swp = swdevt; swp->sw_dev > 0; swp++) {
228		maj = major(swp->sw_dev);
229
230		if (maj > nblkdev)
231			break;
232
233		if (bdevsw[maj].d_psize) {
234			nb = bdevsw[maj].d_psize(swp->sw_dev);
235			if (nb > 0 &&
236			    (swp->sw_nblks == 0 || swp->sw_nblks > nb))
237				swp->sw_nblks = nb;
238			else
239				swp->sw_nblks = 0;
240		}
241		swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
242	}
243	if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize)
244	/*dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem;*/
245		dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) -
246			ctob(physmem)/DEV_BSIZE;
247	if (dumplo < 0)
248		dumplo = 0;
249
250}
251
252#define	DOSWAP			/* change swdevt and dumpdev */
253u_long	bootdev = 0;		/* should be dev_t, but not until 32 bits */
254
255static	char devname[][2] = {
256	0,0,
257	0,0,
258	'f','d',	/* 2 = fd */
259	0,0,
260	's','d',	/* 4 = sd -- new SCSI system */
261};
262
263void
264setroot()
265{
266	int majdev, mindev, unit, part, adaptor;
267	dev_t temp, orootdev;
268	struct swdevt *swp;
269
270	if (boothowto & RB_DFLTROOT ||
271	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
272		return;
273	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
274	if (majdev > sizeof(devname) / sizeof(devname[0]))
275		return;
276	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
277	part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
278	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
279	orootdev = rootdev;
280	rootdev = MAKEDISKDEV(majdev, unit, part);
281	/*
282	 * If the original rootdev is the same as the one
283	 * just calculated, don't need to adjust the swap configuration.
284	 */
285	if (rootdev == orootdev)
286		return;
287	printf("changing root device to %c%c%d%c\n",
288		devname[majdev][0], devname[majdev][1],
289		unit, part + 'a');
290#ifdef DOSWAP
291	mindev = DISKUNIT(rootdev);
292	for (swp = swdevt; swp->sw_dev; swp++) {
293		if (majdev == major(swp->sw_dev) &&
294		    mindev == DISKUNIT(swp->sw_dev)) {
295			temp = swdevt[0].sw_dev;
296			swdevt[0].sw_dev = swp->sw_dev;
297			swp->sw_dev = temp;
298			break;
299		}
300	}
301	if (swp->sw_dev == 0)
302		return;
303	/*
304	 * If dumpdev was the same as the old primary swap
305	 * device, move it to the new primary swap device.
306	 */
307	if (temp == dumpdev)
308		dumpdev = swdevt[0].sw_dev;
309#endif
310}
311
312
313/*
314 * Try to determine, of this machine is an A3000, which has a builtin
315 * realtime clock and scsi controller, so that this hardware is only
316 * included as "configured" if this IS an A3000
317 */
318
319int a3000_flag = 1;		/* patchable */
320#ifdef A4000
321int a4000_flag = 1;		/* patchable - default to A4000 */
322#else
323int a4000_flag = 0;		/* patchable */
324#endif
325
326int
327is_a3000()
328{
329	/* this is a dirty kludge.. but how do you do this RIGHT ? :-) */
330	extern long orig_fastram_start;
331	short sc;
332
333	if ((machineid >> 16) == 3000)
334		return (1);			/* It's an A3000 */
335	if (machineid >> 16)
336		return (0);			/* It's not an A3000 */
337	/* Machine type is unknown, so try to guess it */
338	/* where is fastram on the A4000 ?? */
339	/* if fastram is below 0x07000000, assume it's not an A3000 */
340	if (orig_fastram_start < 0x07000000)
341		return(0);
342	/*
343	 * OK, fastram starts at or above 0x07000000, check specific
344	 * machines
345	 */
346	for (sc = 0; sc < ncfdev; sc++) {
347		switch (cfdev[sc].rom.manid) {
348		case 2026:		/* Progressive Peripherals, Inc */
349			switch (cfdev[sc].rom.prodid) {
350			case 0:		/* PPI Mercury - A3000 */
351			case 1:		/* PP&S A3000 '040 */
352				return(1);
353			case 150:	/* PPI Zeus - it's an A2000 */
354			case 105:	/* PP&S A2000 '040 */
355			case 187:	/* PP&S A500 '040 */
356				return(0);
357			}
358			break;
359
360		case 2112:			/* IVS */
361			switch (cfdev[sc].rom.prodid) {
362			case 242:
363				return(0);	/* A2000 accelerator? */
364			}
365			break;
366		}
367	}
368	return (a3000_flag);		/* XXX let flag tell now */
369}
370
371int
372is_a4000()
373{
374	if ((machineid >> 16) == 4000)
375		return (1);		/* It's an A4000 */
376	if ((custom.deniseid & 0xff) == 0xf8)
377		return (1);
378#ifdef DEBUG
379	if (a4000_flag)
380		printf ("Denise ID = %04x\n", (unsigned short)custom.deniseid);
381#endif
382	if (machineid >> 16)
383		return (0);		/* It's not an A4000 */
384	return (a4000_flag);		/* Machine type not set */
385}
386