autoconf.c revision 1.27
1/*	$NetBSD: autoconf.c,v 1.27 1994/12/28 09:06:37 chopps 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 configure __P((void));
44void setroot __P((void));
45void swapconf __P((void));
46void mbattach __P((struct device *, struct device *, void *));
47int mbprint __P((void *, char *));
48int mbmatch __P((struct device *, struct cfdata *, void *));
49
50int cold;	/* 1 if still booting */
51#include <sys/kernel.h>
52/*
53 * called at boot time, configure all devices on system
54 */
55void
56configure()
57{
58	/*
59	 * this is the real thing baby (i.e. not console init)
60	 */
61	amiga_realconfig = 1;
62	custom.intena = INTF_INTEN;
63
64	if (config_rootfound("mainbus", "mainbus") == 0)
65		panic("no mainbus found");
66
67	custom.intena = INTF_SETCLR | INTF_INTEN;
68#ifdef GENERIC
69	if ((boothowto & RB_ASKNAME) == 0)
70		setroot();
71	setconf();
72#else
73	setroot();
74#endif
75	swapconf();
76	cold = 0;
77}
78
79/*ARGSUSED*/
80int
81simple_devprint(auxp, pnp)
82	void *auxp;
83	char *pnp;
84{
85	return(QUIET);
86}
87
88int
89matchname(fp, sp)
90	char *fp, *sp;
91{
92	int len;
93
94	len = strlen(fp);
95	if (strlen(sp) != len)
96		return(0);
97	if (bcmp(fp, sp, len) == 0)
98		return(1);
99	return(0);
100}
101
102/*
103 * use config_search to find appropriate device, then call that device
104 * directly with NULL device variable storage.  A device can then
105 * always tell the difference betwean the real and console init
106 * by checking for NULL.
107 */
108int
109amiga_config_found(pcfp, pdp, auxp, pfn)
110	struct cfdata *pcfp;
111	struct device *pdp;
112	void *auxp;
113	cfprint_t pfn;
114{
115	struct device temp;
116	struct cfdata *cf;
117
118	if (amiga_realconfig)
119		return(config_found(pdp, auxp, pfn));
120
121	if (pdp == NULL)
122		pdp = &temp;
123
124	pdp->dv_cfdata = pcfp;
125	if ((cf = config_search((cfmatch_t)NULL, pdp, auxp)) != NULL) {
126		cf->cf_driver->cd_attach(pdp, NULL, auxp);
127		pdp->dv_cfdata = NULL;
128		return(1);
129	}
130	pdp->dv_cfdata = NULL;
131	return(0);
132}
133
134/*
135 * this function needs to get enough configured to do a console
136 * basically this means start attaching the grfxx's that support
137 * the console. Kinda hacky but it works.
138 */
139int
140config_console()
141{
142	struct cfdata *cf;
143
144	/*
145	 * we need mainbus' cfdata.
146	 */
147	cf = config_rootsearch(NULL, "mainbus", "mainbus");
148	if (cf == NULL)
149		panic("no mainbus");
150	/*
151	 * internal grf.
152	 */
153	amiga_config_found(cf, NULL, "grfcc", NULL);
154	/*
155	 * zbus knows when its not for real and will
156	 * only configure the appropriate hardware
157	 */
158	amiga_config_found(cf, NULL, "zbus", NULL);
159}
160
161/*
162 * mainbus driver
163 */
164struct cfdriver mainbuscd = {
165	NULL, "mainbus", (cfmatch_t)mbmatch, mbattach,
166	DV_DULL, sizeof(struct device), NULL, 0
167};
168
169int
170mbmatch(pdp, cfp, auxp)
171	struct device *pdp;
172	struct cfdata *cfp;
173	void *auxp;
174{
175	if (cfp->cf_unit > 0)
176		return(0);
177	/*
178	 * We are always here
179	 */
180	return(1);
181}
182
183/*
184 * "find" all the things that should be there.
185 */
186void
187mbattach(pdp, dp, auxp)
188	struct device *pdp, *dp;
189	void *auxp;
190{
191	printf ("\n");
192	config_found(dp, "clock", simple_devprint);
193	config_found(dp, "ser", simple_devprint);
194	config_found(dp, "par", simple_devprint);
195	config_found(dp, "kbd", simple_devprint);
196	config_found(dp, "grfcc", simple_devprint);
197	config_found(dp, "fdc", simple_devprint);
198	if (is_a4000() || is_a1200())
199		config_found(dp, "idesc", simple_devprint);
200	config_found(dp, "zbus", simple_devprint);
201	if (is_a3000())
202		config_found(dp, "ahsc", simple_devprint);
203}
204
205int
206mbprint(auxp, pnp)
207	void *auxp;
208	char *pnp;
209{
210	if (pnp)
211		printf("%s at %s", (char *)auxp, pnp);
212	return(UNCONF);
213}
214
215void
216swapconf()
217{
218	struct swdevt *swp;
219	u_int maj;
220	int nb;
221
222	for (swp = swdevt; swp->sw_dev > 0; swp++) {
223		maj = major(swp->sw_dev);
224
225		if (maj > nblkdev)
226			break;
227
228		if (bdevsw[maj].d_psize) {
229			nb = bdevsw[maj].d_psize(swp->sw_dev);
230			if (nb > 0 &&
231			    (swp->sw_nblks == 0 || swp->sw_nblks > nb))
232				swp->sw_nblks = nb;
233			else
234				swp->sw_nblks = 0;
235		}
236		swp->sw_nblks = ctod(dtoc(swp->sw_nblks));
237	}
238	if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize)
239	/*dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem;*/
240		dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) -
241			ctob(physmem)/DEV_BSIZE;
242	if (dumplo < 0)
243		dumplo = 0;
244
245}
246
247#define	DOSWAP			/* change swdevt and dumpdev */
248u_long	bootdev = 0;		/* should be dev_t, but not until 32 bits */
249
250static	char devname[][2] = {
251	0,0,
252	0,0,
253	'f','d',	/* 2 = fd */
254	0,0,
255	's','d',	/* 4 = sd -- new SCSI system */
256};
257
258void
259setroot()
260{
261	int majdev, mindev, unit, part, adaptor;
262	dev_t temp, orootdev;
263	struct swdevt *swp;
264
265	if (boothowto & RB_DFLTROOT ||
266	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
267		return;
268	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
269	if (majdev > sizeof(devname) / sizeof(devname[0]))
270		return;
271	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
272	part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
273	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
274	orootdev = rootdev;
275	rootdev = MAKEDISKDEV(majdev, unit, part);
276	/*
277	 * If the original rootdev is the same as the one
278	 * just calculated, don't need to adjust the swap configuration.
279	 */
280	if (rootdev == orootdev)
281		return;
282	printf("changing root device to %c%c%d%c\n",
283		devname[majdev][0], devname[majdev][1],
284		unit, part + 'a');
285#ifdef DOSWAP
286	mindev = DISKUNIT(rootdev);
287	for (swp = swdevt; swp->sw_dev; swp++) {
288		if (majdev == major(swp->sw_dev) &&
289		    mindev == DISKUNIT(swp->sw_dev)) {
290			temp = swdevt[0].sw_dev;
291			swdevt[0].sw_dev = swp->sw_dev;
292			swp->sw_dev = temp;
293			break;
294		}
295	}
296	if (swp->sw_dev == 0)
297		return;
298	/*
299	 * If dumpdev was the same as the old primary swap
300	 * device, move it to the new primary swap device.
301	 */
302	if (temp == dumpdev)
303		dumpdev = swdevt[0].sw_dev;
304#endif
305}
306
307
308/*
309 * Try to determine, of this machine is an A3000, which has a builtin
310 * realtime clock and scsi controller, so that this hardware is only
311 * included as "configured" if this IS an A3000
312 */
313
314int a3000_flag = 1;		/* patchable */
315#ifdef A4000
316int a4000_flag = 1;		/* patchable - default to A4000 */
317#else
318int a4000_flag = 0;		/* patchable */
319#endif
320
321int
322is_a3000()
323{
324	/* this is a dirty kludge.. but how do you do this RIGHT ? :-) */
325	extern long boot_fphystart;
326	short sc;
327
328	if ((machineid >> 16) == 3000)
329		return (1);			/* It's an A3000 */
330	if (machineid >> 16)
331		return (0);			/* It's not an A3000 */
332	/* Machine type is unknown, so try to guess it */
333	/* where is fastram on the A4000 ?? */
334	/* if fastram is below 0x07000000, assume it's not an A3000 */
335	if (boot_fphystart < 0x07000000)
336		return(0);
337	/*
338	 * OK, fastram starts at or above 0x07000000, check specific
339	 * machines
340	 */
341	for (sc = 0; sc < ncfdev; sc++) {
342		switch (cfdev[sc].rom.manid) {
343		case 2026:		/* Progressive Peripherals, Inc */
344			switch (cfdev[sc].rom.prodid) {
345			case 0:		/* PPI Mercury - A3000 */
346			case 1:		/* PP&S A3000 '040 */
347				return(1);
348			case 150:	/* PPI Zeus - it's an A2000 */
349			case 105:	/* PP&S A2000 '040 */
350			case 187:	/* PP&S A500 '040 */
351				return(0);
352			}
353			break;
354
355		case 2112:			/* IVS */
356			switch (cfdev[sc].rom.prodid) {
357			case 242:
358				return(0);	/* A2000 accelerator? */
359			}
360			break;
361		}
362	}
363	return (a3000_flag);		/* XXX let flag tell now */
364}
365
366int
367is_a4000()
368{
369	if ((machineid >> 16) == 4000)
370		return (1);		/* It's an A4000 */
371	if ((machineid >> 16) == 1200)
372		return (0);		/* It's an A1200, so not A4000 */
373	/* Do I need this any more? */
374	if ((custom.deniseid & 0xff) == 0xf8)
375		return (1);
376#ifdef DEBUG
377	if (a4000_flag)
378		printf ("Denise ID = %04x\n", (unsigned short)custom.deniseid);
379#endif
380	if (machineid >> 16)
381		return (0);		/* It's not an A4000 */
382	return (a4000_flag);		/* Machine type not set */
383}
384
385int
386is_a1200()
387{
388	if ((machineid >> 16) == 1200)
389		return (1);		/* It's an A1200 */
390	return (0);			/* Machine type not set */
391}
392